ExMCP.ACP.Types (ex_mcp v0.9.0)

View Source

Type specifications and builder functions for the Agent Client Protocol (ACP).

ACP uses JSON-RPC 2.0 as its wire format (same as MCP). All types are plain maps matching the ex_mcp convention — no structs for protocol types.

Content Blocks

ACP supports text and image content blocks in prompts and responses:

text_block("Hello, world!")
image_block("image/png", "base64data...")

Session Management

Sessions track agent conversations. Create with new_session_params/2, send prompts with prompt_params/2.

Summary

Functions

Creates an audio content block.

Error code indicating authentication is required.

Creates client info for the initialize handshake.

Creates an image content block.

Creates params for a new session request.

Creates a plan_update session update.

Creates params for a prompt request.

Creates a resource content block.

Creates a resource link content block.

Error code indicating a resource was not found.

Creates a text content block.

Types

agent_capabilities()

@type agent_capabilities() :: %{
  optional(:loadSession) => boolean(),
  optional(:promptCapabilities) => %{
    optional(:image) => boolean(),
    optional(:audio) => boolean(),
    optional(:embeddedContext) => boolean()
  },
  optional(:mcpCapabilities) => %{
    optional(:http) => boolean(),
    optional(:sse) => boolean()
  },
  optional(:sessionCapabilities) => %{
    optional(:list) => session_list_capabilities() | nil
  }
}

agent_info()

@type agent_info() :: %{name: String.t(), version: String.t()}

agent_message_chunk_update()

@type agent_message_chunk_update() :: %{
  sessionUpdate: :agent_message_chunk,
  content: content_block()
}

audio_block()

@type audio_block() :: %{type: :audio, mimeType: String.t(), data: String.t()}

available_commands_update()

@type available_commands_update() :: %{
  sessionUpdate: :available_commands_update,
  commands: [map()]
}

client_capabilities()

@type client_capabilities() :: %{
  optional(:fs) => %{
    optional(:readTextFile) => boolean(),
    optional(:writeTextFile) => boolean()
  },
  optional(:terminal) => boolean()
}

client_info()

@type client_info() :: %{name: String.t(), version: String.t()}

config_option()

@type config_option() :: %{
  :id => String.t(),
  :name => String.t(),
  optional(:description) => String.t(),
  optional(:type) => String.t(),
  optional(:default) => any()
}

config_option_update()

@type config_option_update() :: %{
  sessionUpdate: :config_option_update,
  configId: String.t(),
  value: any()
}

content_block()

@type content_block() ::
  text_block()
  | image_block()
  | audio_block()
  | resource_link_block()
  | resource_block()

current_mode_update()

@type current_mode_update() :: %{
  sessionUpdate: :current_mode_update,
  modeId: String.t()
}

file_range()

@type file_range() :: %{
  optional(:start) => non_neg_integer(),
  optional(:end) => non_neg_integer()
}

file_read_request()

@type file_read_request() :: %{
  :sessionId => String.t(),
  :path => String.t(),
  optional(:range) => file_range()
}

file_write_request()

@type file_write_request() :: %{
  sessionId: String.t(),
  path: String.t(),
  content: String.t()
}

image_block()

@type image_block() :: %{type: :image, mimeType: String.t(), data: String.t()}

initialize_request()

@type initialize_request() :: %{
  :clientInfo => client_info(),
  optional(:clientCapabilities) => client_capabilities(),
  optional(:protocolVersion) => pos_integer()
}

initialize_response()

@type initialize_response() :: %{
  :agentInfo => agent_info(),
  optional(:agentCapabilities) => agent_capabilities(),
  optional(:protocolVersion) => pos_integer()
}

list_sessions_request()

@type list_sessions_request() :: %{optional(:cursor) => String.t()}

list_sessions_response()

@type list_sessions_response() :: %{
  :sessions => [session_info()],
  optional(:nextCursor) => String.t()
}

load_session_request()

@type load_session_request() :: %{
  :sessionId => String.t(),
  optional(:cwd) => String.t(),
  optional(:mcpServers) => [mcp_server()]
}

mcp_server()

@type mcp_server() :: %{:uri => String.t(), optional(:name) => String.t()}

mode()

@type mode() :: %{
  :id => String.t(),
  :name => String.t(),
  optional(:description) => String.t()
}

new_session_request()

@type new_session_request() :: %{
  optional(:cwd) => String.t(),
  optional(:mcpServers) => [mcp_server()]
}

new_session_response()

@type new_session_response() :: %{sessionId: String.t()}

permission_option()

@type permission_option() :: %{
  :optionId => String.t(),
  :name => String.t(),
  :kind => String.t(),
  optional(:description) => String.t()
}

permission_outcome()

@type permission_outcome() :: %{
  :outcome => String.t(),
  optional(:optionId) => String.t()
}

permission_request()

@type permission_request() :: %{
  sessionId: String.t(),
  toolCall: tool_call_info(),
  options: [permission_option()]
}

plan_entry()

@type plan_entry() :: %{
  content: String.t(),
  priority: :high | :medium | :low,
  status: :pending | :in_progress | :completed
}

plan_update()

@type plan_update() :: %{sessionUpdate: :plan_update, entries: [plan_entry()]}

prompt_request()

@type prompt_request() :: %{sessionId: String.t(), prompt: [content_block()]}

prompt_response()

@type prompt_response() :: %{stopReason: String.t()}

resource_block()

@type resource_block() :: %{
  :type => :resource,
  :uri => String.t(),
  optional(:name) => String.t(),
  optional(:mimeType) => String.t(),
  optional(:text) => String.t(),
  optional(:blob) => String.t()
}

session_info()

@type session_info() :: %{
  :sessionId => String.t(),
  optional(:name) => String.t(),
  optional(:createdAt) => String.t()
}

session_info_update()

@type session_info_update() :: %{
  :sessionUpdate => :session_info_update,
  optional(:sessionName) => String.t(),
  optional(:metadata) => map()
}

session_list_capabilities()

@type session_list_capabilities() :: %{optional(:supportsNameFilter) => boolean()}

session_update()

session_update_params()

@type session_update_params() :: %{sessionId: String.t(), update: session_update()}

status_update()

@type status_update() :: %{
  :sessionUpdate => :status,
  :status => String.t(),
  optional(:message) => String.t()
}

text_block()

@type text_block() :: %{type: :text, text: String.t()}

thinking_update()

@type thinking_update() :: %{sessionUpdate: :thinking, content: String.t()}

tool_call_info()

@type tool_call_info() :: %{
  :toolName => String.t(),
  optional(:toolCallId) => String.t(),
  optional(:arguments) => map()
}

tool_call_update()

@type tool_call_update() :: %{
  :sessionUpdate => :tool_call_update,
  :toolCallId => String.t(),
  :title => String.t(),
  :status => String.t(),
  optional(:content) => [content_block()]
}

user_message_chunk_update()

@type user_message_chunk_update() :: %{
  sessionUpdate: :user_message_chunk,
  content: content_block()
}

Functions

audio_block(mime_type, data)

@spec audio_block(String.t(), String.t()) :: map()

Creates an audio content block.

auth_required_code()

@spec auth_required_code() :: integer()

Error code indicating authentication is required.

client_info(name, version)

@spec client_info(String.t(), String.t()) :: map()

Creates client info for the initialize handshake.

image_block(mime_type, data)

@spec image_block(String.t(), String.t()) :: map()

Creates an image content block.

new_session_params(cwd \\ nil, opts \\ [])

@spec new_session_params(
  String.t() | nil,
  keyword()
) :: map()

Creates params for a new session request.

Options

  • :mcp_servers - list of MCP server maps with :uri and optional :name

plan_entry(content, priority \\ "medium", status \\ "pending")

@spec plan_entry(String.t(), String.t(), String.t()) :: map()

Creates a plan entry.

plan_update(session_id, entries)

@spec plan_update(String.t(), [map()]) :: map()

Creates a plan_update session update.

prompt_params(session_id, content)

@spec prompt_params(String.t(), String.t() | [map()]) :: map()

Creates params for a prompt request.

Content can be a string (auto-wrapped as text block) or a list of content block maps.

resource_block(uri, opts \\ [])

@spec resource_block(
  String.t(),
  keyword()
) :: map()

Creates a resource content block.

resource_not_found_code()

@spec resource_not_found_code() :: integer()

Error code indicating a resource was not found.

text_block(text)

@spec text_block(String.t()) :: map()

Creates a text content block.