CodeGraph exposes Agent Client Protocol (ACP) over JSON-RPC for editor integrations. ACP v1 is
the default and production-compatible profile. An experimental ACP v2 alpha profile is available
behind CODEGRAPH_ACP_EXPERIMENTAL_V2=true. The profile is selected by initialize and remains
fixed for the lifetime of that connection.
Both profiles use the same CodeGraph session core, workspace controls, permission requests, and Model Context Protocol (MCP) bridge. Image and audio capabilities are not advertised.
Transports and routes
| Transport | Entry point | Contract |
|---|---|---|
| stdio | codegraph-acp |
A local IDE starts one agent subprocess. Requests, responses, and notifications are streamed. |
| HTTP | POST /api/v1/admin/runtime/acp/rpc |
CodeGraph request/response JSON-RPC endpoint. It is not the official ACP Streamable HTTP transport. |
| WebSocket | WS /api/v1/admin/runtime/acp/ws |
Bidirectional requests, agent-to-client calls, and streamed notifications. |
HTTP session administration is available through
GET /api/v1/admin/runtime/acp/sessions and
DELETE /api/v1/admin/runtime/acp/sessions/{session_id}. HTTP protocol state and sessions are
isolated by authenticated subject and project. WebSocket connections keep the project scope
resolved from the token, machine credential, or explicitly enabled local-development boundary.
The HTTP endpoint collects ACP v1 prompt notifications and returns them in
result._meta.codegraph.sessionUpdates. ACP v2 session/prompt is asynchronous and needs a
streaming transport, so HTTP rejects it with JSON-RPC error -32004 before executing the turn.
Authentication boundary
The HTTP JSON-RPC and session routes require an administrator, the admin:all scope, or a
service account with scenarios:execute. An unauthenticated localhost bypass exists only when
local_dev_unauthenticated_surfaces_enabled is explicitly enabled.
WebSocket accepts a bearer access token or an API key. Machine credentials are additionally
checked against project scope, the X-CodeGraph-Machine-Contract version, interface policy, and
configured mTLS requirements. Transport authentication finishes before JSON-RPC parameters are
parsed. Both ACP initialize responses advertise an empty authMethods list; the legacy v1
authenticate method therefore operates only inside an already verified transport boundary.
ACP v1 methods
Call initialize with protocolVersion: 1 before any other method. The server rejects an
uninitialized request with -32002.
The standard v1 surface contains session/new, session/load, session/prompt, and
session/cancel. During a prompt, the server can issue client requests for
fs/read_text_file, fs/write_text_file, terminal operations, and session/request_permission.
Clients must route responses by JSON-RPC request ID while continuing to process
session/update notifications.
CodeGraph v1 prompts may opt in to those client calls with the
_meta.codegraph.clientContext extension on a content block. Its readTextFiles array accepts
objects with path; its terminals array accepts command, string args, and optional cwd,
env, or outputByteLimit. CodeGraph invokes only capabilities advertised at initialize, adds
the returned editor-visible file content and terminal result to that prompt, and always releases
a created terminal. This metadata is a CodeGraph extension, not a new standard ACP method.
CodeGraph-specific editor functions use the _codegraph/ namespace:
_codegraph/thread/start,_codegraph/thread/resume,_codegraph/thread/fork,_codegraph/thread/list,_codegraph/thread/archive, and_codegraph/thread/compact;_codegraph/turn/startand_codegraph/turn/interrupt;_codegraph/diagnostics/subscribe,_codegraph/diagnostics/unsubscribe, and_codegraph/hover/request;_codegraph/item/fileChange/respondApproval.
Pre-Story-1257 unprefixed names remain available through an explicit compatibility adapter. Such
responses carry _meta.codegraph.legacyMethod; new clients should use the namespaced methods.
The internal ClientCapabilitiesV2 class names the extended CodeGraph capability model and does
not mean ACP protocol v2.
Experimental ACP v2 profile
With CODEGRAPH_ACP_EXPERIMENTAL_V2=true, a connection may initialize with
protocolVersion: 2, info.name, and info.version. The profile supports session/new,
session/list, session/resume, session/close, session/delete, session/prompt,
session/cancel, and $/cancel_request.
session/prompt acknowledges the request before the turn finishes. The client then receives
session/update notifications, including state transitions and tool-call updates. Use stdio or
WebSocket for this flow. Reinitializing a connection with another protocol version fails closed;
open a new connection instead.
To roll back the experimental profile, set CODEGRAPH_ACP_EXPERIMENTAL_V2=false and restart ACP
connections. ACP v1 does not depend on the v2 flag.
MCP servers and permission flow
session/new and the applicable resume/load flows accept ACP MCP descriptors for stdio and
http transports. Stdio commands are resolved to an executable and run as a native argv with no
shell. Environment and header entries must use name/value objects; names are validated and values
cannot contain NUL, carriage-return, or newline characters.
HTTP MCP descriptors accept public HTTPS endpoints only. Credentials in the URL, query strings, fragments, loopback addresses, private networks, link-local addresses, and plaintext HTTP are rejected. Redirect handling remains subject to the shared outbound URL policy.
Every declared MCP server must connect during session creation. If any connection fails, the
server closes connections already opened for that request and removes the incomplete ACP session.
Before invoking an MCP tool, CodeGraph sends session/request_permission; a denial or timeout
prevents the call. One lifecycle-owner task performs each MCP SDK context entry, operation, and
exit so session close and transport shutdown can release subprocesses and network clients.
Workspace and terminal containment
File calls require an absolute workspaceRoot and target path. A path that resolves outside
the root fails with outside workspace root. Writes also reject sensitive path fragments such as
.git, .env, .ssh, .aws, and node_modules.
Terminal calls require the same absolute workspaceRoot; cwd must remain below it. Commands
run as argv with shell=False. The checked-in allowlist contains bounded build and inspection
commands. Interpreters and shells such as python, powershell, pwsh, cmd, bash, sh,
and node are blocked. Arguments must be a native list of strings without NUL or newline control
characters.
These checks do not turn ACP into a general remote shell. Keep network routes behind the normal authentication and project boundary.
File-change approval limitation
The server advertises an approval flow and sends the established
item/fileChange/requestApproval notification. Clients answer with the canonical
_codegraph/item/fileChange/respondApproval method; the unprefixed response name is accepted by
the compatibility adapter. An unanswered request is declined after the configured timeout.
The current fs/write_text_file handler does not automatically invoke that bridge. It performs a
workspace-contained write after its own path checks. A client or outer workflow that requires
human approval must enforce and record it before exposing the write operation.
Runtime limits
Defaults in ACPRuntimeConfig bound the service to 100 concurrent sessions with a 60-minute
session timeout, 128 pending agent-to-client requests per connection, 256 queued stdio
notifications, and a 300-second approval timeout. The same configuration also controls terminal
wait and cleanup timing, bridge polling, and streamed chunk sizes. Deployments may override these
values through the unified runtime configuration; clients must not assume that defaults were
retained.
Recovery checklist
- Confirm the route prefix is
/api/v1/admin/runtime/acp, not the historical/acpprefix. - Verify transport authentication before debugging JSON-RPC parameters.
- Send one
initializerequest and keep that protocol profile for the connection. - Use stdio or WebSocket for ACP v2 prompts and agent-to-client requests.
- For file or terminal errors, keep absolute
workspaceRoot,path, andcwdvalues below the same root. - Treat a blocked executable, rejected MCP endpoint, or missing permission as a policy outcome.
Source of truth
src/api/routers/collaboration_suite/acp.py: HTTP/WebSocket routes and authentication.src/acp/server/core/agent.py: v1 dispatch, profile selection, client requests, and shared MCP execution.src/acp/server/core/v2_profile.py: experimental v2 session lifecycle and asynchronous turns.src/acp/server/core/session_manager.py: session ownership, MCP setup, cancellation, and cleanup.src/acp/server/routing/handlers.py: workspace containment and bounded terminal policy.src/acp/integration/mcp_bridge.py: MCP descriptor validation and connection lifecycle.src/acp/transport/: stdio, HTTP, and WebSocket behavior.src/config/runtime_sections/unified_config_runtime_models.py: ACP runtime defaults.