feat(acp): Honor MCP servers passed from ACP clients
Please explain the motivation behind the feature request.
Per the ACP specification, agents MUST support stdio MCP servers passed from clients via NewSessionRequest.mcp_servers. Currently, goose ignores this field entirely in acp.rs:new_session, making it non-compliant with the protocol.
This matters because:
- Editors like Zed allow users to configure MCP servers that should be available to all agents
- Users expect consistent tool availability across different agents in their editor
- The spec is clear: "All Agents MUST support the stdio transport" (session-setup docs)
Describe the solution you'd like
In new_session, merge editor-provided MCP servers with goose's configured extensions, taking care to behave like --with-extension which scopes an MCP server addition, not persisting it forever.
Recommended behavior: Union with ACP wins - editor-provided servers are added to goose's built-in extensions. On name conflict, editor-provided servers win (override). This is the same behavior across claude-code-acp, gemini-cli, qwen-code, codex-acp, opencode, and openhands-cli.
Describe alternatives you've considered
- Replace all: Editor servers replace goose's built-ins entirely - too disruptive
- Goose wins on conflict: Built-ins override editor servers - violates user expectations
- Error on conflict: Reject sessions with conflicting names - poor UX
Additional context
The McpCapabilities in goose's initialize response currently sets http(false) and sse(false), which is correct for now, but should be implemented to close this issue. The first gap to fill is that even stdio servers (which are mandatory) are ignored.
- [x] I have verified this does not duplicate an existing feature request
/goose put together a minimal implementation of this feature. curl the linked acp standard documentation (https://agentclientprotocol.com/protocol/session-setup#mcp-servers) to ensure you understand what is required to correctly implement this. Do not add new tests or comments. Code should be self-obvious. Document any unaddressable edge cases, security concerns, or potential issues. Make the PR as easy to review as possible.
@tlongwell-block so to be clear, you want this to have no tests or comments? per this advice "Do not add new tests or comments." Adding no tests means only manual testing.
I think we're all for testing. but the tests have to have a value - LLMs will generate tests that are trivial, test what happens and brittle more often than not: https://engineering.block.xyz/blog/the-high-cost-of-free-testing
we have the ability to set a fake openai endpoint so we can pre-can and avoid volatility. I'm doing this already for a lot of other codebases besides goose.
I am not an llm either
I have struggled with rust and trying to carve out places to add tests where there aren't any, and have definitely generated tests to cover edge cases and possibly gotten some wrong. The basic idea here is to pre-can an end-to-end test similar to what exists in other agents like gemini where you don't need to just guess if something works or rely on a python script because not sure. So for example.
basic chat is a feature you can exercise in ACP. There is no test for this so I would have to add one or get someone else to do it. Once that's in, we can add tests for other features like bringing the MCP server. As you highlighted a bug iin the other PR, we can even check it didn't taint the global config and instead scoped it properly.
Once any test exists in the right fashion it is indeed easier to get LLMs to generate the next, but placing the burden on folks new to the language to either go completely without tests or to design a test framework just to be able to add one.. both of these are bad-bad experiences waiting to happen.
EOF
/goose I took out the slightly faulty code example from this issue description. there's a comment here with instructions https://github.com/block/goose/pull/6113#issuecomment-3658337198
Any other action items here?
Yeah sorry lost myself in code mode :)
So the plumbing needs to happen and another test in the acp integration file that it works.
On my list for this weekend
https://github.com/block/goose/pull/6230 sorts this