Skip to content

fix(acp): give MCP-less harnesses a sibling buzz-dev-mcp so replies can publish - #5393

Open
NedMalki-Chief wants to merge 1 commit into
block:mainfrom
NedMalki-Chief:fix/claude-mcp-sibling-fallback
Open

fix(acp): give MCP-less harnesses a sibling buzz-dev-mcp so replies can publish#5393
NedMalki-Chief wants to merge 1 commit into
block:mainfrom
NedMalki-Chief:fix/claude-mcp-sibling-fallback

Conversation

@NedMalki-Chief

Copy link
Copy Markdown

Problem

Claude Code agents go silent after a turn; Codex agents reply normally.

An agent's reply reaches the relay only through the MCP server. BUZZ_PRIVATE_KEY and BUZZ_RELAY_URL are injected exclusively into the MCP server's environment when it is registered at session/new (build_mcp_servers, crates/buzz-acp/src/lib.rs). A harness spawned with an empty mcp_command therefore has no keyed channel back to the relay: it can run a full turn — think, call tools — and then have no authenticated way to publish the result.

Desktop spawns Claude Code exactly this way. In the KnownAcpRuntime catalog (desktop/src-tauri/src/managed_agents/discovery.rs):

  • codexmcp_command: Some("buzz-dev-mcp")
  • claudemcp_command: None

So every Claude Code agent launches with an empty mcp_command and cannot publish. Reproduced on Windows 11: two Claude Code agents (opus[1m], sonnet) stayed mute after mentions while a Codex agent (gpt-5.6-sol) in the same channel replied. Their runtime lines differ in exactly one field — mcp_cmd= empty vs mcp_cmd=…\buzz-dev-mcp.exe.

Change

When mcp_command is empty, fall back to a buzz-dev-mcp binary sitting next to the running buzz-acp executable.

The path is derived from std::env::current_exe() — the trusted install directory — never from user input. That is deliberate: it adds no user-controllable code-execution surface, which is why this is not an env/config knob (BUZZ_ACP_MCP_COMMAND is a Desktop-reserved key precisely to prevent a config from pointing the agent at an arbitrary binary). When no sibling exists (cargo test, unusual layouts), the command stays empty and behaviour is unchanged.

This is a one-function, ~10-line change plus two tests. It fixes the packaged desktop case (buzz-acp and buzz-dev-mcp ship in the same directory) without requiring the Desktop catalog to grow an mcp_command for every current and future harness.

Alternative considered

Adding mcp_command: Some("buzz-dev-mcp") to the claude catalog entry would fix Claude specifically, but any future MCP-less harness would hit the same silent failure. Defaulting at the buzz-acp layer covers them all, and the runtime is the layer that actually knows its own install directory.

Verification

Windows 11, release binary from this branch installed into the packaged desktop layout:

  • Both Claude Code agents now boot with mcp_cmd=…\buzz-dev-mcp.exe and log mcp_command empty; using sibling buzz-dev-mcp fallback, where before they booted with an empty mcp_cmd.
  • cargo test -p buzz-acp --lib — two new tests pass (configured command is preserved; empty stays empty when no sibling is present).
  • cargo fmt -p buzz-acp -- --check clean.

Commit is DCO signed-off. Independent of my other open PR #5379 (probe timeout) — this branches from main and touches a different code path.

…an publish

An agent's reply reaches the relay only through the MCP server: BUZZ_PRIVATE_KEY
and BUZZ_RELAY_URL are injected exclusively into the MCP server's environment at
session/new. A harness spawned with an empty mcp_command therefore has no keyed
channel back — it can run a full turn, think, and call tools, then have no way
to publish the result.

Desktop spawns Claude Code exactly this way: the `claude` entry in the
KnownAcpRuntime catalog has `mcp_command: None`, while `codex` has
`Some("buzz-dev-mcp")`. The observable effect is that Codex agents reply
normally while Claude Code agents go silent after a turn — reproduced on
Windows with Honey/Bumble (Claude) mute and Fizz (Codex) replying.

When mcp_command is empty, fall back to a buzz-dev-mcp binary sitting next to
the running buzz-acp executable. The path is derived from the trusted install
directory of the current exe, never from user input, so it adds no
code-execution surface — which is why this is not exposed as an env/config knob
(BUZZ_ACP_MCP_COMMAND is a Desktop-reserved key for that reason). When no
sibling exists (cargo test, unusual layouts) the command stays empty and
behaviour is unchanged.

Verified on Windows: both Claude Code agents now boot with
mcp_cmd=buzz-dev-mcp.exe and log "mcp_command empty; using sibling buzz-dev-mcp
fallback", where before they booted with an empty mcp_cmd.

Signed-off-by: Ned Malki <ned@ottomato.ai>
@NedMalki-Chief
NedMalki-Chief requested a review from a team as a code owner August 9, 2026 12:34
@wolfyy970

Copy link
Copy Markdown

The diagnosis is useful, but I do not think an absent reply path should implicitly grant the bundled developer MCP.

buzz-dev-mcp exposes shell and file-edit capabilities as well as the path an agent can use to publish. This fallback changes the tool set of Claude and every future MCP-less harness without an agent definition, Project binding or review surface saying those tools were added. Deriving the binary from the install directory protects the executable path; it does not solve the capability boundary.

For the immediate Claude regression, an explicit catalog-owned binding is safer because Buzz can report exactly what that runtime receives. The durable fix should be a narrow target-owned publish capability, along the lines of #5288, rather than treating all developer tools as the reply transport.

Please include an end-to-end test that proves the agent can reply and records the exact capabilities exposed to it. I would not make empty mcp_command mean a hidden buzz-dev-mcp grant.

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