ACP Protocol

March 21, 2026 · View on GitHub

The Agent Communication Protocol (ACP) is an advanced protocol for agent-to-agent and agent-to-tool communication. It provides session management, streaming, and structured tool execution beyond what MCP offers.


Overview

ACP is designed for:

  • Multi-agent systems with independent conversation contexts
  • Session management with persistence and isolation
  • Tool lifecycle tracking with detailed progress notifications
  • Bidirectional communication over JSON-RPC 2.0

When to Use ACP vs MCP

FeatureMCPACP
Tool exposure
Session management-
Conversation history-
Tool lifecycle tracking-
Streaming notifications-
Multi-session support-
Editor integration-

Use MCP when:

  • Integrating with AI editors (Cursor, Claude Code)
  • Simple tool exposure is sufficient
  • No session state needed

Use ACP when:

  • Building multi-agent systems
  • Need conversation persistence
  • Require detailed tool execution tracking
  • Building custom AI platforms

Starting the ACP Server

# Start ACP server via stdio
node index.js --acp

# With options
node index.js --acp --path ./my-project --debug

Server Options:

OptionDescription
--pathWorking directory
--debugEnable debug logging
--providerAI provider name
--modelAI model name
--allow-editEnable file editing
--enable-delegateEnable task delegation
--enable-mcpEnable MCP integration

Protocol Specification

Transport

  • Protocol: JSON-RPC 2.0
  • Transport: stdio (stdin/stdout)
  • Message Delimiter: Newline (\n)
  • Timeout: 30 seconds per request

Message Format

Request:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "methodName",
  "params": {}
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {}
}

Notification (no response expected):

{
  "jsonrpc": "2.0",
  "method": "notificationName",
  "params": {}
}

Error:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32600,
    "message": "Invalid Request"
  }
}

Request Methods

initialize

Initialize the ACP connection.

Request:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "1"
  }
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "1",
    "serverInfo": {
      "name": "probe-acp",
      "version": "1.0.0"
    },
    "capabilities": {
      "tools": [
        { "name": "search", "kind": "search" },
        { "name": "query", "kind": "query" },
        { "name": "extract", "kind": "extract" },
        { "name": "symbols", "kind": "symbols" }
      ],
      "sessionManagement": true,
      "streaming": true,
      "permissions": false
    }
  }
}

newSession

Create a new conversation session.

Request:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "newSession",
  "params": {}
}

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "sessionId": "abc123",
    "mode": "NORMAL",
    "createdAt": "2025-01-15T10:30:00Z"
  }
}

loadSession

Load an existing session.

Request:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "loadSession",
  "params": {
    "sessionId": "abc123"
  }
}

Response:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "sessionId": "abc123",
    "mode": "NORMAL",
    "history": [
      { "role": "user", "content": "Previous message" },
      { "role": "assistant", "content": "Previous response" }
    ]
  }
}

setSessionMode

Change session mode.

Request:

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "setSessionMode",
  "params": {
    "sessionId": "abc123",
    "mode": "PLANNING"
  }
}

Modes:

  • NORMAL - Standard interactive mode
  • PLANNING - Planning/analysis mode

prompt

Send a message and get AI response.

Request:

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "prompt",
  "params": {
    "sessionId": "abc123",
    "message": "How does authentication work in this codebase?"
  }
}

Response:

{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "sessionId": "abc123",
    "content": [
      {
        "type": "text",
        "text": "The authentication system uses JWT tokens..."
      }
    ],
    "timestamp": "2025-01-15T10:31:00Z"
  }
}

cancel

Cancel ongoing operations.

Request:

{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "cancel",
  "params": {
    "sessionId": "abc123"
  }
}

File Operations

readTextFile:

{
  "method": "readTextFile",
  "params": {
    "path": "src/auth.ts"
  }
}

writeTextFile:

{
  "method": "writeTextFile",
  "params": {
    "path": "src/new-file.ts",
    "content": "export const value = 42;"
  }
}

Notification Methods

toolCallProgress

Sent during tool execution.

{
  "jsonrpc": "2.0",
  "method": "toolCallProgress",
  "params": {
    "sessionId": "abc123",
    "toolCall": {
      "id": "tool-1",
      "name": "search",
      "kind": "search",
      "status": "in_progress",
      "startTime": 1705315860000
    }
  }
}

Tool Call Status:

  • pending - Waiting to execute
  • in_progress - Currently executing
  • completed - Successfully completed
  • failed - Execution failed

messageChunk

Streaming message chunks.

{
  "jsonrpc": "2.0",
  "method": "messageChunk",
  "params": {
    "sessionId": "abc123",
    "chunk": "The authentication system",
    "index": 0
  }
}

sessionUpdated

Session state changed.

{
  "jsonrpc": "2.0",
  "method": "sessionUpdated",
  "params": {
    "sessionId": "abc123",
    "mode": "PLANNING",
    "updatedAt": "2025-01-15T10:32:00Z"
  }
}

Tool Definitions

{
  "name": "search",
  "description": "Search for code patterns using semantic search",
  "kind": "search",
  "inputSchema": {
    "properties": {
      "query": { "type": "string" },
      "path": { "type": "string" },
      "max_results": { "type": "number", "default": 10 },
      "allow_tests": { "type": "boolean", "default": true },
      "exact": { "type": "boolean" },
      "session": { "type": "string" },
      "nextPage": { "type": "boolean" }
    },
    "required": ["query"]
  }
}

query

{
  "name": "query",
  "description": "Perform structural queries using AST patterns",
  "kind": "query",
  "inputSchema": {
    "properties": {
      "pattern": { "type": "string" },
      "path": { "type": "string" },
      "language": { "type": "string" },
      "max_results": { "type": "number", "default": 10 },
      "allow_tests": { "type": "boolean", "default": true }
    },
    "required": ["pattern"]
  }
}

extract

{
  "name": "extract",
  "description": "Extract specific code blocks from files",
  "kind": "extract",
  "inputSchema": {
    "properties": {
      "files": { "type": "array", "items": { "type": "string" } },
      "context_lines": { "type": "number" },
      "allow_tests": { "type": "boolean", "default": true },
      "format": { "type": "string", "enum": ["plain", "markdown", "json"] }
    },
    "required": ["files"]
  }
}

symbols

{
  "name": "symbols",
  "description": "List all symbols in a file with line numbers and nesting",
  "kind": "symbols",
  "inputSchema": {
    "properties": {
      "file": { "type": "string", "description": "Path to the file to list symbols from" }
    },
    "required": ["file"]
  }
}

delegate

{
  "name": "delegate",
  "description": "Delegate tasks to specialized subagents",
  "kind": "execute",
  "inputSchema": {
    "properties": {
      "task": { "type": "string" }
    },
    "required": ["task"]
  }
}

Error Codes

CodeNameDescription
-32700PARSE_ERRORInvalid JSON
-32600INVALID_REQUESTInvalid request structure
-32601METHOD_NOT_FOUNDUnknown method
-32602INVALID_PARAMSInvalid parameters
-32603INTERNAL_ERRORInternal server error
-32001UNSUPPORTED_PROTOCOL_VERSIONProtocol version mismatch
-32002SESSION_NOT_FOUNDSession doesn't exist
-32003PERMISSION_DENIEDOperation not permitted
-32004TOOL_EXECUTION_FAILEDTool execution error

Client Implementation

Simple Client Example

import { spawn } from 'child_process';

class SimpleACPClient {
  constructor() {
    this.requestId = 0;
    this.pending = new Map();
  }

  async start() {
    this.server = spawn('node', ['index.js', '--acp'], {
      stdio: ['pipe', 'pipe', 'pipe']
    });

    this.server.stdout.on('data', (data) => {
      const message = JSON.parse(data.toString().trim());
      this.handleMessage(message);
    });
  }

  handleMessage(message) {
    if (message.id && this.pending.has(message.id)) {
      const { resolve, reject } = this.pending.get(message.id);
      this.pending.delete(message.id);

      if (message.error) {
        reject(new Error(message.error.message));
      } else {
        resolve(message.result);
      }
    } else if (!message.id) {
      // Notification
      this.handleNotification(message.method, message.params);
    }
  }

  handleNotification(method, params) {
    console.log(`Notification: ${method}`, params);
  }

  async sendRequest(method, params = {}) {
    const id = ++this.requestId;

    return new Promise((resolve, reject) => {
      this.pending.set(id, { resolve, reject });

      const request = JSON.stringify({
        jsonrpc: '2.0',
        id,
        method,
        params
      }) + '\n';

      this.server.stdin.write(request);
    });
  }

  async initialize() {
    return this.sendRequest('initialize', { protocolVersion: '1' });
  }

  async createSession() {
    return this.sendRequest('newSession', {});
  }

  async sendPrompt(sessionId, message) {
    return this.sendRequest('prompt', { sessionId, message });
  }

  close() {
    this.server.stdin.end();
  }
}

// Usage
const client = new SimpleACPClient();
await client.start();

const { capabilities } = await client.initialize();
console.log('Capabilities:', capabilities);

const { sessionId } = await client.createSession();
console.log('Session:', sessionId);

const response = await client.sendPrompt(sessionId, 'How does auth work?');
console.log('Response:', response.content);

client.close();

Protocol Flow

Client                          Server
  |                                |
  |------ initialize ------------->|
  |<----- capabilities ------------|
  |                                |
  |------ newSession ------------->|
  |<----- sessionId ---------------|
  |                                |
  |------ prompt ----------------->|
  |<----- toolCallProgress --------|  (notification)
  |<----- toolCallProgress --------|  (notification)
  |<----- messageChunk ------------|  (notification)
  |<----- response ----------------|
  |                                |
  |------ cancel ----------------->|
  |<----- acknowledged ------------|
  |                                |
  |------ close connection ------->|

Debugging

Enable debug logging:

DEBUG=1 node index.js --acp

Debug Output:

[ACP] Server started
[ACP] Received: initialize
[ACP] Session created: abc123
[ACP] Tool call: search (in_progress)
[ACP] Tool call: search (completed, 245ms)
[ACP] Response sent