fix/acp tool calls and mcp init #473
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fix ACP server tool calls, authentication, and MCP initialization
this should solve #461 and add Stakpak to ACP Registry
Problems
1. MCP initialization failed — no tools available
The ACP server used
stakpak_mcp_client::connect()which spawnsstakpak mcp proxyas a subprocess. That subprocess requires amcp.toml/mcp.jsonconfig file on disk, which doesn't exist in a standard setup. This caused MCP initialization to fail entirely, leaving the ACP server with zero tools — the AI could never produce tool calls.Interactive mode works because it uses a completely different path (
mcp_init::initialize_mcp_server_and_tools) that sets up the MCP server and proxy in-process as tokio tasks, with mTLS on ephemeral ports, requiring no config file.2. Tool call streaming accumulation was broken
The ACP server used a naive index-based tool call delta accumulator. The Anthropic/StakAI API can send multiple tool calls with the same index but different IDs. The naive accumulator merged these into a single tool call, corrupting the arguments JSON. Interactive mode already had a proper
ToolCallAccumulatorwith ID-based matching that handles this correctly.3. Empty
tool_callsarray rejected by APIAfter streaming, the tool calls filter always produced
tool_calls: Some([])(empty array) for text-only responses. The API rejects emptytool_callsarrays in conversation history, causing the second message to fail withInvalidAgentInput/ decode error.4. Authentication didn't rebuild the AgentClient
After browser authentication in IntelliJ/Zed,
authenticate()saved the API key toconfig.tomlon disk but never updated the in-memoryself.configor rebuiltself.client. TheAgentClientwas created at startup withstakpak: Noneand stayed that way, causing 401 errors on the first message after auth.5. Tool names not stripped of MCP prefix
Tool calls arrive from the API with names like
stakpak__run_commandbut the ACP server compared against constants like"run_command", so all tool matching for permissions, display, and routing failed silently.---MISSING---
Changes
cli/src/commands/acp/server.rsmcp_init::initialize_mcp_server_and_tools()(same as interactive mode)server_shutdown_tx,proxy_shutdown_tx) kept alive for the ACP session lifetimeToolCallAccumulatorNoneinstead ofSome([])(matching interactive mode)configandclientinArc<RwLock<>>for in-memory updates after authenticationauthenticate()now updates in-memory config and rebuildsAgentClientwith the new API keyclientread sites (initialize,new_session,prompt) use.read().awaitstrip_tool_name()for:generate_tool_title,get_tool_kind,should_use_diff_content,is_file_creation_tool,is_auto_approved_tool, view directory check,is_fs_file_read/is_fs_file_writecli/src/commands/acp/utils.rsstrip_tool_name()function (same logic astui/src/utils.rs— stripsprefix__and trailing())cli/src/commands/acp/fs_handler.rsmatchstatement for filesystem tool routingcli/src/commands/agent/run/stream.rsToolCallAccumulatorand its methods (new,process_delta,into_tool_calls) public so the ACP server can reuse the same accumulation logic.gitignoredebug_acp.sh(local debug helper)Testing
Zed
tool_callsarraysIntelliJ IDEA
CI
cargo check— cleancargo clippy— zero warningscargo test— all tests pass (including newstrip_tool_nametests)