feat(coding-agent): support ACP MCP programs - #1378
Conversation
e278ab6 to
30b44fa
Compare
|
Took over this branch and rebuilt it on current The old per-tool temporary-skill implementation is gone. ACP-provided HTTP and stdio servers now use the kernel-owned OAuth scope is explicit: ACP HTTP uses only client-supplied URL/headers and cannot read or refresh stored Prime Agent OAuth, including on same-name collisions. ACP stdio remains trusted same-user code, not a credential sandbox, and the docs now say so. Discussion #1574 remains separate because it concerns OAuth discovery for user-configured MCP servers. Validation: |
|
Macroscope has since reviewed this pull request. An earlier review was skipped by a cost limit; a review has now completed, so that notice no longer applies. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8e525ed. Configure here.

Summary
session/newmcp.list_toolsandmcp.call_toolPython program APIRelated Linear task: RES-1159
Architecture
This branch is reconciled with current
mainand now builds on the kernel-owned generic MCP runtime merged in #1495 and hardened in #1585. It no longer generates one temporary Python package per tool or duplicates MCP transports inmcp_base.py.ACP server names are added to the session prompt, and the model discovers and calls their tools through:
OAuth and credential boundary
ACP HTTP credentials are treated as client-supplied session authority:
auth.json, resolves host bearer-token environment variables, or starts or refreshes Prime Agent OAuth.session/close, replacement, failed admission, and disconnect.ACP stdio is trusted same-user code, not a credential sandbox. It uses the real agent cwd, a scrubbed base environment, and the literal environment values supplied by the ACP client, but the launched process can still read any files available to the Prime Agent user. Only trusted ACP clients should supply stdio servers, or Prime Agent must run inside an external sandbox.
Discussion #1574 tracks a separate path-scoped OAuth discovery bug for user-configured MCP servers. ACP-provided servers do not run that OAuth flow, so this PR keeps that issue out of scope rather than mixing the two credential models.
Daemon compatibility
acp_mcp_serverscapabilityreplace_acp_mcp_serversis sent only after capability negotiationValidation
npm run checknpx tsx ../../node_modules/vitest/dist/cli.js --run test/acp-mcp.test.ts test/mcp-manager.test.ts test/daemon-protocol.test.ts test/agent-connection-daemon.test.ts test/system-prompt.test.ts test/agent-session-services.test.ts— 150 passeduv run python -m unittest discover -s testinprime-agent-runtime— 98 passedgit diff --checkNote
Cursor Bugbot is generating a summary for commit b2a213a. Configure here.
Note
Summary
session/newmcp.list_toolsandmcp.call_toolPython program APIRelated Linear task: RES-1159
Architecture
This branch is reconciled with current
mainand now builds on the kernel-owned generic MCP runtime merged in #1495 and hardened in #1585. It no longer generates one temporary Python package per tool or duplicates MCP transports inmcp_base.py.ACP server names are added to the session prompt, and the model discovers and calls their tools through:
OAuth and credential boundary
ACP HTTP credentials are treated as client-supplied session authority:
auth.json, resolves host bearer-token environment variables, or starts or refreshes Prime Agent OAuth.session/close, replacement, failed admission, and disconnect.ACP stdio is trusted same-user code, not a credential sandbox. It uses the real agent cwd, a scrubbed base environment, and the literal environment values supplied by the ACP client, but the launched process can still read any files available to the Prime Agent user. Only trusted ACP clients should supply stdio servers, or Prime Agent must run inside an external sandbox.
Discussion #1574 tracks a separate path-scoped OAuth discovery bug for user-configured MCP servers. ACP-provided servers do not run that OAuth flow, so this PR keeps that issue out of scope rather than mixing the two credential models.
Daemon compatibility
acp_mcp_serverscapabilityreplace_acp_mcp_serversis sent only after capability negotiationValidation
npm run checknpx tsx ../../node_modules/vitest/dist/cli.js --run test/acp-mcp.test.ts test/mcp-manager.test.ts test/daemon-protocol.test.ts test/agent-connection-daemon.test.ts test/system-prompt.test.ts test/agent-session-services.test.ts— 150 passeduv run python -m unittest discover -s testinprime-agent-runtime— 98 passedgit diff --checkChanges since #1378 opened
AgentDaemon.handleCommandforreplace_acp_mcp_serverscase to trackacpMcpOwnersentries with server names and optional in-flight release promises, acquire session input pause when replacing with non-empty servers, roll back failures by callingsession.releaseAcpMcpServerswith the union of claimed names, clear ownership by callingsession.releaseAcpMcpServerswith stored names when replacing with empty servers, store release promises to prevent duplicate concurrent releases, and fence ownership changes until prior releases complete [b2a213a]AgentSession.releaseAcpMcpServersmethod to asynchronously acceptownerIdandserverNames, checkmanager.canReleaseAcpServers(ownerId)before proceeding, callreplaceAcpServers([], ownerId)to revoke credentials, immediately update base and system prompts without rebuilding the kernel, deduplicate provided server names and if any are present acquire a session input pause, wait for agent idle and event queue drain, execute Python in-kernel to importrlm.mcpand awaitreload(name)for each server, validate kernel execute result status equals 'ok' and throw on failure, and always release the input pause in finally [b2a213a]mcp._Registry._get_lockedmethod in the Python runtime to reorder and guard configuration fetch by attempting to obtain config within a try/except block, close and remove current generation from registry on exception before re-raising, while preserving existing behavior of returning current generation when config is unchanged or closing and replacing generation when config changes [b2a213a]AgentConnectioninterface with optionalreleaseAcpMcpServersmethod acceptingownerIdandserverNamesand returning a promise, implementedDaemonAgentConnection.releaseAcpMcpServersto proxy toreplaceAcpMcpServers([], ownerId)while ignoring provided names at the transport layer, and implementedInProcessAgentConnection.releaseAcpMcpServersto forward calls toruntimeHost.session.releaseAcpMcpServers[b2a213a]runAcpModeWithConnectionfunction to requireconnection.releaseAcpMcpServerscapability in the capability gate, replacehasAcpMcpServersboolean withacpMcpServerNamesstring array tracking last admitted names, modifyclearAcpMcpServersto callconnection.releaseAcpMcpServers(ownerId, serverNames)and clear tracked names, and modifyreplaceAcpMcpServersto resolve input to configs, capture names, and attempt owner-scoped cleanup for those names usingreleaseAcpMcpServerson admission error [b2a213a]releaseAcpMcpServers(ownerId, [names])instead ofreplaceAcpMcpServers([], ownerId), added spies and mocks for name-scoped release assertions, verified daemon release expectations on rollback and detach with specific server names, extended capability tests to usereleaseAcpMcpServers, mocked running IPython kernel manager to assert Python snippet execution invokingawait _prime_mcp.reload(name)without runtime rebuild, augmented stdio fixture to optionally write PID to file viaFIXTURE_PID_FILEenv for process reaping assertions, and added tests for closing cached generations on missing config and reaping real ACP stdio processes on reload [b2a213a]mcp._Registry._get_lockedto preserve cached MCP server generations when configuration retrieval fails [8e525ed]replaceAcpMcpServershelper withinrunAcpModeWithConnectionto always clear existing MCP servers whenacpMcpServerNamesis non-empty, regardless of whether replacement servers are provided [80136a7]