Environment: droid CLI run as an ACP agent via droid exec --output-format acp (also --output-format acp-daemon), macOS, embedded by an ACP client/host.
Summary: When Droid runs as an ACP agent, it loads the user's global MCP servers from ~/.factory/mcp.json in addition to the mcpServers the ACP client supplies in session/new, and it blocks ACP initialize/session startup until every global server connects. If a global server is slow or requires interactive authorization, init hangs until the user responds, stalling the client's turn. With N such servers the delay compounds (serial, blocking).
Concrete example (Xcode's MCP server): With Xcode's MCP server added to Droid (droid mcp list → xcode stdio enabled [user]; ~/.factory/mcp.json has "xcode": { "command": "xcrun", … }), starting Droid over ACP makes Xcode pop its own dialog — "Allow 'Factory CLI' to access Xcode? The agent wants to use Xcode's tools to perform actions like building, testing, or modifying code." — and Droid's initialize blocks until the user clicks Allow. Slow to allow → the ACP client's readiness probe times out and reports the agent as not connected; allow quickly → the session proceeds. The Xcode server is irrelevant to the client's request, yet it gates startup.
Expected: In an ACP session the client is the authority on MCP servers (via session/new.mcpServers). Droid should (1) not pull global mcp.json servers into a client-driven ACP session, or make it opt-in; and (2) not block initialize on MCP connections — connect lazily/in the background, tolerant of failures.
Repro:
- Add Xcode's MCP server to Droid (
xcrun-launched stdio; any slow/prompt-on-connect server works).
- With Xcode running,
droid exec --output-format acp from any ACP client.
- Xcode pops "Allow 'Factory CLI' to access Xcode?" and
initialize hangs until allowed.
Contrast: @agentclientprotocol/claude-agent-acp and @zed-industries/codex-acp use only client-provided mcpServers and don't block init on global servers — Droid is the outlier (same global config present for all three; only Droid hangs/prompts).
Notes from the binary: --output-format acp → runAcpChild (single session); acp-daemon → runAcpDaemon, which forks its own acp children. Settings/MCP merge is additive, so --settings/FACTORY_RUNTIME_SETTINGS_PATH can add but not remove global servers. Config dir is homedir()/.factory with no override, so a host can't isolate config without hijacking HOME (breaks auth).
Requests: don't load global mcp.json into client ACP sessions (or make it opt-in) and never block initialize on MCP connections; a --no-mcp flag for droid exec; a FACTORY_HOME/config-dir override.
Environment:
droidCLI run as an ACP agent viadroid exec --output-format acp(also--output-format acp-daemon), macOS, embedded by an ACP client/host.Summary: When Droid runs as an ACP agent, it loads the user's global MCP servers from
~/.factory/mcp.jsonin addition to themcpServersthe ACP client supplies insession/new, and it blocks ACPinitialize/session startup until every global server connects. If a global server is slow or requires interactive authorization, init hangs until the user responds, stalling the client's turn. With N such servers the delay compounds (serial, blocking).Concrete example (Xcode's MCP server): With Xcode's MCP server added to Droid (
droid mcp list→xcode stdio enabled [user];~/.factory/mcp.jsonhas"xcode": { "command": "xcrun", … }), starting Droid over ACP makes Xcode pop its own dialog — "Allow 'Factory CLI' to access Xcode? The agent wants to use Xcode's tools to perform actions like building, testing, or modifying code." — and Droid'sinitializeblocks until the user clicks Allow. Slow to allow → the ACP client's readiness probe times out and reports the agent as not connected; allow quickly → the session proceeds. The Xcode server is irrelevant to the client's request, yet it gates startup.Expected: In an ACP session the client is the authority on MCP servers (via
session/new.mcpServers). Droid should (1) not pull globalmcp.jsonservers into a client-driven ACP session, or make it opt-in; and (2) not blockinitializeon MCP connections — connect lazily/in the background, tolerant of failures.Repro:
xcrun-launched stdio; any slow/prompt-on-connect server works).droid exec --output-format acpfrom any ACP client.initializehangs until allowed.Contrast:
@agentclientprotocol/claude-agent-acpand@zed-industries/codex-acpuse only client-providedmcpServersand don't block init on global servers — Droid is the outlier (same global config present for all three; only Droid hangs/prompts).Notes from the binary:
--output-format acp→runAcpChild(single session);acp-daemon→runAcpDaemon, which forks its ownacpchildren. Settings/MCP merge is additive, so--settings/FACTORY_RUNTIME_SETTINGS_PATHcan add but not remove global servers. Config dir ishomedir()/.factorywith no override, so a host can't isolate config without hijackingHOME(breaks auth).Requests: don't load global
mcp.jsoninto client ACP sessions (or make it opt-in) and never blockinitializeon MCP connections; a--no-mcpflag fordroid exec; aFACTORY_HOME/config-dir override.