Skip to content

Conversation

@mstfash
Copy link
Collaborator

@mstfash mstfash commented Jan 30, 2026

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 spawns stakpak mcp proxy as a subprocess. That subprocess requires a mcp.toml/mcp.json config 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 ToolCallAccumulator with ID-based matching that handles this correctly.

3. Empty tool_calls array rejected by API

After streaming, the tool calls filter always produced tool_calls: Some([]) (empty array) for text-only responses. The API rejects empty tool_calls arrays in conversation history, causing the second message to fail with InvalidAgentInput / decode error.

4. Authentication didn't rebuild the AgentClient

After browser authentication in IntelliJ/Zed, authenticate() saved the API key to config.toml on disk but never updated the in-memory self.config or rebuilt self.client. The AgentClient was created at startup with stakpak: None and 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_command but the ACP server compared against constants like "run_command", so all tool matching for permissions, display, and routing failed silently.

---MISSING---

  • Plan mode with Stakpak board.

Changes

cli/src/commands/acp/server.rs

  • Replaced subprocess-based MCP init with in-process mcp_init::initialize_mcp_server_and_tools() (same as interactive mode)
  • Shutdown handles (server_shutdown_tx, proxy_shutdown_tx) kept alive for the ACP session lifetime
  • Replaced inline index-based tool call accumulation with shared ToolCallAccumulator
  • Empty tool calls now set to None instead of Some([]) (matching interactive mode)
  • Wrapped config and client in Arc<RwLock<>> for in-memory updates after authentication
  • authenticate() now updates in-memory config and rebuilds AgentClient with the new API key
  • All client read sites (initialize, new_session, prompt) use .read().await
  • All tool name comparisons use strip_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_write

cli/src/commands/acp/utils.rs

  • Added strip_tool_name() function (same logic as tui/src/utils.rs — strips prefix__ and trailing ())
  • Added unit tests for edge cases

cli/src/commands/acp/fs_handler.rs

  • Strip tool name before the match statement for filesystem tool routing

cli/src/commands/agent/run/stream.rs

  • Made ToolCallAccumulator and its methods (new, process_delta, into_tool_calls) public so the ACP server can reuse the same accumulation logic

.gitignore

  • Added debug_acp.sh (local debug helper)

Testing

Zed

  • Verified MCP server initializes successfully with tools on startup
  • Confirmed tool calls are accumulated correctly from streaming responses
  • Confirmed text-only responses no longer produce empty tool_calls arrays
  • Confirmed follow-up messages after tool execution work without decode errors

IntelliJ IDEA

  • Verified browser authentication flow saves key and rebuilds client in-memory
  • First message after auth works immediately (no 401)
  • Second message works (no decode error)
  • Tool calls route correctly through permission flow and execute via MCP

CI

  • cargo check — clean
  • cargo clippy — zero warnings
  • cargo test — all tests pass (including new strip_tool_name tests)

@mstfash mstfash marked this pull request as ready for review January 30, 2026 22:44
@mstfash mstfash merged commit 19f8fb7 into main Jan 31, 2026
1 check passed
@ahmedhesham6 ahmedhesham6 deleted the fix/acp-tool-calls-and-mcp-init branch January 31, 2026 14:12
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.

3 participants