block / block/buzz

Agents eagerly spawn every configured MCP server, no per-agent toggle or lazy-start

Open
#6,117 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## Problem

Every loaded agent (one `buzz-acp` process per agent, e.g. multiple personas active in one Buzz Desktop instance) eagerly spawns a full `claude-agent-acp` worker process for **every** MCP server configured in the user's global `~/.claude/settings.json` + `~/.claude.json` — there is currently no way to scope which connectors a given agent needs, and no lazy-start path.

Observed impact: 5 concurrently loaded agents × ~10 configured MCP servers (Gmail, Linear, Figma, Notion, Supabase, Atlassian Rovo, Playwright, context7, etc.) × ~100MB/worker ≈ 5GB resident RAM before any agent does actual work, which pushed a 15GB dev laptop into swap and caused a multi-minute freeze.

## Root cause (traced in source)

**No per-agent MCP filtering:**
- `desktop/src/features/agents/ui/AgentDefinitionDialog.tsx` (agent-edit UI) has no MCP-related controls at all.
- A per-persona MCP merge mechanism exists — `crates/buzz-persona/src/resolve.rs::merge_mcp_servers()` (~line 275), merging a pack's `.mcp.json` with per-persona frontmatter `mcp_servers:` — but it's only invoked once, at team-pack import time (`desktop/src-tauri/src/migration.rs:1128`), never applied to live agent sessions.
- Live sessions build their MCP list via `crates/buzz-acp/src/lib.rs::build_mcp_servers()` (~line 4827), which only emits Buzz's own internal relay MCP server — the user's actual connectors are pulled in unfiltered elsewhere.
- `desktop/src-tauri/src/managed_agents/config_bridge/claude.rs::read_config_file()` reads `~/.claude/settings.json` + `~/.claude.json` and marks every `mcpServers` entry `enabled: true` unconditionally (read-only display, not a filter).
- Net effect: every "claude" runtime agent inherits the user's **entire global** connector list, with no override.

**No lazy MCP-server start:**
- `crates/buzz-agent/src/mcp.rs::McpRegistry::spawn_all()` (~line 202) spawns every configured server synchronously at session start.
- `BUZZ_ACP_LAZY_POOL` (`crates/buzz-acp/src/config.rs`, `desktop/src-tauri/src/managed_agents/runtime.rs:533`) only defers spawning the whole agent harness process, not individual MCP servers within it.
- The vendored `@agentclientprotocol/claude-agent-acp` npm package (under `~/.local/share/Buzz/node-tools/lib/node_modules/`) eagerly resolves and merges `mcpServers` in `dist/settings.js::SettingsManager` / `dist/acp-agent.js:4450`. Its own dependency, `@anthropic-ai/claude-agent-sdk`, already exposes `toggleMcpServer(name, enabled)` / `reconnectMcpServer(name)` control-protocol methods — but `claude-agent-acp` never calls or exposes them over ACP, so Buzz has no hook into lazy start/stop today.

## Suggested fix

1. Add a per-agent MCP server allow-list (surfaced in `AgentDefinitionDialog.tsx`, persisted per agent, applied wherever the live session's MCP list is actually assembled — needs tracing beyond `build_mcp_servers()`, since that function currently only handles Buzz's internal relay server).
2. Have Buzz's ACP bridge call the SDK's existing `toggleMcpServer`/`reconnectMcpServer` hooks to defer starting a connector's worker process until an agent actually invokes one of its tools, instead of eager-spawning all of them at agent load.

## Workaround (no code change)

Trim the `mcpServers` list in `~/.claude/settings.json` / `~/.claude.json` — since every agent currently shares that one global list, cutting it there reduces resident workers for all loaded agents at once. Not a real fix since it's global rather than per-agent, but it's the only lever available today.

---
Filed from investigation in a Buzz Desktop dev-build session, prompted by a real RAM/swap-induced freeze with 5 agents loaded simultaneously.

Contributor guide

Open the contributing guide

Research direction

Start by tracing the live session path from desktop/src/features/agents/ui/AgentDefinitionDialog.tsx through crates/buzz-acp/src/lib.rs::build_mcp_servers() and crates/buzz-agent/src/mcp.rs::McpRegistry::spawn_all(). Read the Claude bridge files and the vendored claude-agent-acp settings and ACP code to identify where per-agent selection and SDK controls can connect. Done means each agent can use an allow-list and MCP workers no longer all start eagerly.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, rust, typescript
Domain
desktop, devtools, performance
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.