Skip to content

feat(acp): allow multiple MCP servers per agent - #2900

Open
ArgussLabs wants to merge 1 commit into
block:mainfrom
ArgussLabs:feat/acp-multiple-mcp-servers
Open

feat(acp): allow multiple MCP servers per agent#2900
ArgussLabs wants to merge 1 commit into
block:mainfrom
ArgussLabs:feat/acp-multiple-mcp-servers

Conversation

@ArgussLabs

Copy link
Copy Markdown

Summary

--mcp-command / BUZZ_ACP_MCP_COMMAND accepted a single binary, so an agent got exactly one MCP server. In practice that is an either/or rather than a preference: a Buzz agent acts in Buzz by shelling out to the buzz CLI, and that shell tool comes from buzz-dev-mcp — so pointing the slot at any domain-specific MCP server leaves the agent able to answer but unable to post.

This makes the flag repeatable and the env var comma-separated, matching the agent_args field directly above it in Args.

Defaults are unchanged. No value still means no MCP servers; a single value behaves exactly as before; the flag keeps its --mcp-command name so existing invocations and env values keep working.

  • Args.mcp_command: StringArgs.mcp_commands: Vec<String> with value_delimiter = ','
  • Empty entries are filtered — BUZZ_ACP_MCP_COMMAND="" yields one empty entry through the delimiter
  • build_mcp_servers maps over the list, injecting BUZZ_RELAY_URL / BUZZ_PRIVATE_KEY / BUZZ_AUTH_TAG into each server as before
  • Server names are made unique. Two distinct binaries can share a file stem (/a/bin/mcp and /b/bin/mcp), and a duplicate name would let one shadow the other in the agent's tool namespace, so later collisions get a -2 / -3 suffix

Related issue

#2899, opened just before this with the reproduction and the reasoning. Searched open issues/PRs first and found nothing for multiple MCP servers — closest adjacent are #2883 and #2368, neither overlapping.

Worth a maintainer's judgement: PersonaConfig.mcp_servers is already a Vec that buzz-persona parses, merges, and validates but never plumbs to the runtime, so you may prefer to solve this at the persona/runtime layer instead. This PR is the narrow harness-level fix; happy to redirect.

Testing

  • cargo test -p buzz-acp --lib build_mcp_servers → 9 passed. The four existing tests are updated to the Vec form, plus four new ones: two servers both reaching the agent, env injection per server, and file-stem collisions producing unique names.
  • cargo clippy -p buzz-acp --all-targets -- -D warnings → clean.
  • cargo fmt -p buzz-acp applied.
  • cargo test -p buzz-acp → 599 passed, 2 failed: acp::tests::idle_resets_on_stdout_activity and acp::tests::keepalive_resets_idle_past_deadline. Both are pre-existing on a clean tree — I verified by stashing this change and rerunning — and both are timing-sensitive tests in acp.rs, which this PR does not touch. Likely flaky under load on my machine rather than anything to do with this change, but flagging in case it is news.
  • Verified end to end against a local relay: with buzz-dev-mcp and a second MCP server both passed to --mcp-command, one agent turn called a tool on the second server and then used shell to post the result into the channel.

@ArgussLabs
ArgussLabs requested a review from a team as a code owner July 25, 2026 22:11
`--mcp-command` / `BUZZ_ACP_MCP_COMMAND` accepted a single binary, so an agent
got exactly one MCP server. That is an either/or in practice: a Buzz agent acts
in Buzz by shelling out to the `buzz` CLI, and that shell tool comes from
buzz-dev-mcp — so pointing the slot at any domain-specific MCP server leaves the
agent able to answer but unable to post.

Observed while running an external MCP server behind buzz-acp: the agent was
offered 61 tools (60 from the domain server plus load_skill) and zero shell or
buzz tools. It could query and had no way to say anything.

Makes the flag repeatable and the env var comma-separated, matching the
`agent_args` field directly above it. Defaults are unchanged: no value still
means no MCP servers, and a single value behaves exactly as before.

- Args.mcp_command: String -> Args.mcp_commands: Vec<String>, value_delimiter=','
  keeping the `--mcp-command` flag name, so existing invocations and env values
  keep working.
- Empty entries are filtered, since BUZZ_ACP_MCP_COMMAND="" yields one empty
  entry through the delimiter.
- build_mcp_servers maps over the list, injecting BUZZ_RELAY_URL /
  BUZZ_PRIVATE_KEY / BUZZ_AUTH_TAG into each server as before.
- Server names are made unique. Two distinct binaries can share a file stem
  (/a/bin/mcp and /b/bin/mcp); a duplicate name would let one shadow the other
  in the agent's tool namespace, so subsequent collisions get a -2, -3 suffix.

Tests: the four existing build_mcp_servers tests are updated to the Vec form,
plus four new ones covering two servers reaching the agent, env injection per
server, and file-stem collisions.

Signed-off-by: Ken Lathrop <103387858+ArgussLabs@users.noreply.github.com>
@ArgussLabs
ArgussLabs force-pushed the feat/acp-multiple-mcp-servers branch from 7f2975f to a6b46f6 Compare July 25, 2026 22:12

wolfyy970 commented Aug 1, 2026

Copy link
Copy Markdown

I found this after implementing a different path in #4164.

This PR allows several MCP commands. #4164 adds a versioned config for servers that also need their own name, arguments, and environment. It keeps the existing privileged companion path unchanged and does not copy Buzz credentials into structured third-party servers.

The scope and acceptance criteria are in #4154.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants