Summary
ACP agents (Claude Code / Codex / Gemini CLI / custom) currently cannot use MCP servers. The block is entirely in our own stack — the ACP protocol and all three built-in servers already support MCP. We should let users configure MCP servers for an ACP agent and have them forwarded to the ACP subprocess at session creation.
Why it doesn't work today
The limitation is in software-agent-sdk, not the protocol:
ACPAgent.supports_openhands_mcp returns False.
ACPAgent.init_state() hard-rejects any config: if self.mcp_config: raise NotImplementedError(...).
- Session creation passes no servers:
new_session(...) omits mcp_servers, and load_session(..., mcp_servers=[]) is hardcoded empty.
ACPAgentSettings has no mcp_config field, and the typescript-client ACP_SETTINGS_KEYS allow-list omits it.
What already supports MCP (verified)
- ACP protocol:
new_session/load_session/fork_session all accept mcp_servers: [HttpMcpServer | SseMcpServer | McpServerStdio]; InitializeResponse.agent_capabilities.mcp_capabilities advertises http/sse.
- claude-agent-acp v0.18 —
mcpCapabilities: { http: true, sse: true }; maps the ACP mcpServers array into the Claude Code SDK. stdio + http + sse.
- codex-acp v0.10 —
mcp_capabilities(...http(true)); stdio + http (sse ignored).
- gemini-cli — supports MCP natively.
Plan (full stack)
Reuse the existing mcp_config ({"mcpServers": {...}}) shape rather than inventing a new field — ACPAgent already inherits mcp_config + its secret-encryption machinery from AgentBase.
- software-agent-sdk — drop the
NotImplementedError; translate mcp_config → ACP McpServerStdio/HttpMcpServer/SseMcpServer; gate http/sse on mcp_capabilities; pass into new_session and load_session (resume must re-pass). Add mcp_config: MCPConfig | None to ACPAgentSettings + thread through create_agent().
- typescript-client — add
mcp_config to ACP_SETTINGS_KEYS.
- agent-canvas (this repo) — add
mcp_config to buildAcpAgentSettingsDiff; render the existing MCPServerList/MCPServerForm editor in the ACP branch of agent-settings.tsx; add a MCPServerConfig[] ⇄ {mcpServers:{...}} adapter (the editor's flat model differs from the SDK field's keyed shape).
Notes / constraints
- No runtime add — MCP binds at session creation; changing config restarts the (cwd-keyed) session, unlike the live model-switch feature.
- stdio binaries (
npx/uvx) must exist in the runtime image; remote http/sse needs none.
- Secrets in MCP
env/headers are encrypted at rest by the inherited mcp_config machinery and passed inline to the subprocess.
Summary
ACP agents (Claude Code / Codex / Gemini CLI / custom) currently cannot use MCP servers. The block is entirely in our own stack — the ACP protocol and all three built-in servers already support MCP. We should let users configure MCP servers for an ACP agent and have them forwarded to the ACP subprocess at session creation.
Why it doesn't work today
The limitation is in
software-agent-sdk, not the protocol:ACPAgent.supports_openhands_mcpreturnsFalse.ACPAgent.init_state()hard-rejects any config:if self.mcp_config: raise NotImplementedError(...).new_session(...)omitsmcp_servers, andload_session(..., mcp_servers=[])is hardcoded empty.ACPAgentSettingshas nomcp_configfield, and the typescript-clientACP_SETTINGS_KEYSallow-list omits it.What already supports MCP (verified)
new_session/load_session/fork_sessionall acceptmcp_servers: [HttpMcpServer | SseMcpServer | McpServerStdio];InitializeResponse.agent_capabilities.mcp_capabilitiesadvertiseshttp/sse.mcpCapabilities: { http: true, sse: true }; maps the ACPmcpServersarray into the Claude Code SDK. stdio + http + sse.mcp_capabilities(...http(true)); stdio + http (sse ignored).Plan (full stack)
Reuse the existing
mcp_config({"mcpServers": {...}}) shape rather than inventing a new field —ACPAgentalready inheritsmcp_config+ its secret-encryption machinery fromAgentBase.NotImplementedError; translatemcp_config→ ACPMcpServerStdio/HttpMcpServer/SseMcpServer; gate http/sse onmcp_capabilities; pass intonew_sessionandload_session(resume must re-pass). Addmcp_config: MCPConfig | NonetoACPAgentSettings+ thread throughcreate_agent().mcp_configtoACP_SETTINGS_KEYS.mcp_configtobuildAcpAgentSettingsDiff; render the existingMCPServerList/MCPServerFormeditor in the ACP branch ofagent-settings.tsx; add aMCPServerConfig[] ⇄ {mcpServers:{...}}adapter (the editor's flat model differs from the SDK field's keyed shape).Notes / constraints
npx/uvx) must exist in the runtime image; remote http/sse needs none.env/headersare encrypted at rest by the inheritedmcp_configmachinery and passed inline to the subprocess.