Skip to main content
Meerkat exposes a JSON-RPC 2.0 stdio interface for IDE integration, desktop apps, and automation tools. Unlike REST and MCP, the RPC server keeps agents alive between turns for fast multi-turn conversations. The RPC surface is fully runtime-backed:
  • keep_alive is runtime/session behavior
  • session/external_event queues runtime-backed external work
  • committed success is not rewritten to cancellation

Getting started

1

Start the server

rkat-rpc
The server reads newline-delimited JSON (JSONL) from stdin and writes JSONL to stdout. Each line is a complete JSON-RPC 2.0 message.
2

Send the handshake

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

Create a session

{"jsonrpc":"2.0","id":2,"method":"session/create","params":{"prompt":"Hello!"}}
rkat-rpc defaults to a new isolated realm each time. Use --realm <id> to share config/sessions with other surfaces or processes.

Runtime scope

rkat-rpc accepts global scope flags:
rkat-rpc [--realm <id>] [--isolated] [--instance <id>] [--realm-backend <sqlite|redb|jsonl>] [--state-root <path>] [--context-root <path>] [--user-config-root <path>]
  • --realm: explicit sharing/isolation key
  • --instance: optional instance metadata
  • --realm-backend: creation hint only; actual backend is pinned per realm manifest

Method overview

MethodCategoryDescription
initializeHandshakeReturns server capabilities
session/createSessionCreate session and run first turn
session/listSessionList active sessions
session/readSessionGet session state
session/historySessionGet committed session transcript messages
session/archiveSessionRemove session from runtime
session/external_eventSessionQueue a runtime-backed external event
session/inject_contextSessionAppend runtime-backed system context to the next turn
turn/startTurnStart a new turn on existing session
turn/interruptTurnCancel in-flight turn
runtime/stateRuntimeRead runtime-backed ingress state
runtime/acceptRuntimeAdmit external work directly into runtime ingress
runtime/retireRuntimeRetire runtime-backed ingress
runtime/resetRuntimeReset runtime-backed ingress
input/stateRuntimeRead runtime input lifecycle state
input/listRuntimeList runtime input lifecycle records
mob/prefabsMobList mob prefab templates (mob feature)
session/stream_openSessionOpen a standalone session event stream
session/stream_closeSessionClose a standalone session event stream
mob/createMobCreate a mob from a prefab or definition (mob feature)
mob/listMobList mobs (mob feature)
mob/statusMobGet mob status (mob feature)
mob/membersMobList mob members (mob feature)
mob/spawnMobSpawn a member into a mob (mob feature)
mob/spawn_manyMobSpawn multiple members into a mob (mob feature)
mob/retireMobRetire a mob member (mob feature)
mob/respawnMobRespawn a mob member (mob feature)
mob/wireMobWire two mob members for comms (mob feature)
mob/unwireMobRemove mob comms wiring (mob feature)
mob/lifecycleMobStop, resume, complete, destroy, or reset a mob (mob feature)
mob/sendMobSend work to a mob member (mob feature)
mob/eventsMobRead mob events by cursor (mob feature)
mob/stream_openMobOpen mob or member event stream (mob feature)
mob/stream_closeMobClose mob or member event stream (mob feature)
mob/append_system_contextMobStage system context for a member session (mob feature)
mob/flowsMobList mob flows (mob feature)
mob/flow_runMobStart a mob flow run (mob feature)
mob/flow_statusMobGet flow run status (mob feature)
mob/flow_cancelMobCancel a flow run (mob feature)
mob/spawn_helperMobSpawn a helper member and wait for its result (mob feature)
mob/fork_helperMobFork a helper from an existing member and wait for its result (mob feature)
mob/force_cancelMobForce-cancel a member’s active work (mob feature)
mob/member_statusMobRead canonical status for a specific member (mob feature)
mob/toolsMobCompatibility/escape-hatch mob tool inventory (mob feature)
mob/callMobCompatibility/escape-hatch mob tool call (mob feature)
comms/sendCommsDispatch a comms command to a session
comms/peersCommsList discoverable peers (comms feature)
skills/listSkillsList skills with provenance
skills/inspectSkillsInspect a skill’s full content
tools/registerToolsRegister additional callable tools with the runtime
mcp/addMCPStage live MCP server addition (mcp feature)
mcp/removeMCPStage live MCP server removal (mcp feature)
mcp/reloadMCPReload one or all MCP servers (mcp feature)
models/catalogModelsList available models with capabilities and provider profiles
capabilities/getCapabilitiesRuntime capability report
config/getConfigRead current config
config/setConfigReplace config
config/patchConfigMerge-patch config (RFC 7396)
runtime/* and input/* methods are advertised only when the server is running with the runtime-backed ingress/control-plane surface enabled.
RPC is the canonical typed substrate for the SDKs: use explicit mob/* lifecycle, send, and observation methods from apps. mob/tools and mob/call remain available only as compatibility and escape-hatch surfaces. Inside running sessions, mob capability is still exposed by composing meerkat-mob-mcp (MobMcpState + MobMcpDispatcher) into SessionBuildOptions.external_tools, which provides mob_* tools to the agent.

Protocol

Standard JSON-RPC 2.0 with "jsonrpc": "2.0" on every message. Three message types:
  • Request (client -> server): has id, method, params
  • Response (server -> client): has id, result or error
  • Notification (server -> client): has method, params, no id
Client                          Server
  |                                |
  |-- initialize ----------------->|
  |<-- result { capabilities } ----|
  |-- initialized (notification) ->|
  |                                |
  |-- session/create { prompt } -->|
  |<-- session/event (notif) ------|  // AgentEvent stream
  |<-- session/event (notif) ------|
  |<-- result { session_id, ... } -|
  |                                |
  |-- turn/start { session_id } -->|
  |<-- session/event (notif) ------|
  |<-- result { text, usage } -----|
  |                                |
  |-- turn/interrupt { sid } ----->|
  |<-- result {} ------------------|
  |                                |
  |-- session/archive { sid } ---->|
  |<-- result {} ------------------|

Session methods

initialize

Handshake. Returns server capabilities.
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
server_info.name
string
Server name.
server_info.version
string
Server version.
contract_version
string
Protocol contract version.
methods
array
List of supported method names.

session/create

Create a new session and run the first turn.
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "session/create",
  "params": {
    "prompt": "What is Rust?"
  }
}

session/history

Read committed transcript history for an existing session.
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "session/history",
  "params": {
    "session_id": "01936f8a-7b2c-7000-8000-000000000001",
    "offset": 0,
    "limit": 50
  }
}
Returns oldest-to-newest committed messages plus pagination metadata. This method follows the same owner-resolution rules as session/read, including mob-owned session IDs when mob support is enabled. Only prompt is required. All other fields are optional and fall back to config defaults. During execution, session/event notifications are emitted (see Notifications).

Parameter reference

prompt
string
required
The user prompt to send to the agent.
model
string | null
default:"claude-sonnet-4-5"
Model name (e.g. "claude-opus-4-6", "gpt-5.2").
provider
string | null
default:"inferred from model"
Provider name: "anthropic", "openai", "gemini", "other".
max_tokens
u32 | null
default:"config default"
Max tokens per turn.
system_prompt
string | null
default:"null"
Override system prompt.
output_schema
object | null
default:"null"
JSON schema for structured output extraction (wrapper or raw schema).
structured_output_retries
u32
default:"2"
Max retries for structured output validation.
hooks_override
HookRunOverrides | null
default:"null"
Run-scoped hook overrides (entries to add, hook IDs to disable).
enable_builtins
bool
default:"false"
Enable built-in tools (task management, etc.).
enable_shell
bool
default:"false"
Enable shell tool (requires enable_builtins).
enable_memory
bool
default:"false"
Enable semantic memory (memory_search tool + compaction indexing).
keep_alive
bool | null
default:"null"
Keep session alive after turn for comms. null = inherit persisted session intent, true = enable, false = disable. Requires comms_name when enabled.
comms_name
string | null
default:"null"
Agent name for inter-agent communication.
provider_params
object | null
default:"null"
Provider-specific parameters (e.g., thinking config, reasoning effort).

Response fields

session_id
string
UUID of the created session.
text
string
The agent’s response text.
turns
u32
Number of LLM calls made.
tool_calls
u32
Number of tool calls executed.
usage
WireUsage
Token usage breakdown.
structured_output
object | null
Parsed structured output.
schema_warnings
array | null
Schema compatibility warnings.

session/list

List active sessions.
{"jsonrpc":"2.0","id":3,"method":"session/list"}

session/read

Get session state.
{"jsonrpc":"2.0","id":4,"method":"session/read","params":{"session_id":"01936f8a-..."}}
session_id
string
required
Session ID to read.

session/archive

Remove a session from the runtime.
{"jsonrpc":"2.0","id":5,"method":"session/archive","params":{"session_id":"01936f8a-..."}}
session_id
string
required
Session ID to archive.

Turn methods

turn/start

Start a new turn on an existing session.
{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "turn/start",
  "params": {
    "session_id": "01936f8a-...",
    "prompt": "Can you explain ownership?",
    "skill_references": ["rust-patterns/ownership"]
  }
}
Returns the same result shape as session/create. Fails with error code -32001 (SESSION_BUSY) if a turn is already in progress.
session_id
string
required
Session ID to continue.
prompt
string
required
The follow-up prompt.
model
string | null
default:"from session"
Model override for this turn. On pending (deferred) sessions this sets the model before materialization. On materialized sessions this hot-swaps the LLM client for the remainder of the session.
provider
string | null
default:"from session"
Provider override (e.g. "anthropic", "openai", "gemini"). Typically inferred from model.
provider_params
object | null
default:"from session"
Provider-specific parameters (e.g. {"thinking_budget": 10000}). Applied alongside model/provider override.
max_tokens
u32 | null
default:"from session"
Max tokens override.
skill_references
string[] | null
Skill IDs to resolve and inject for this turn.

turn/interrupt

Cancel an in-flight turn. No-op if the session is idle.
{"jsonrpc":"2.0","id":7,"method":"turn/interrupt","params":{"session_id":"01936f8a-..."}}
session_id
string
required
Session ID to interrupt.

Event methods

session/external_event

Queue a runtime-backed external event for an existing session.
{
  "jsonrpc": "2.0",
  "id": 8,
  "method": "session/external_event",
  "params": {
    "session_id": "01936f8a-...",
    "payload": {"alert": "build failed", "repo": "main"},
    "source": "ci-pipeline"
  }
}
session_id
string
required
Session ID to admit the external event to.
payload
any JSON
required
Any JSON value. Stored as the runtime external-event payload.
source
string
Optional source label. Defaults to "rpc" and becomes the runtime external-event source.
Error -32603 if runtime admission fails, -32602 if the session locator is invalid. This is a queue-only runtime admission path; it does not create a second direct execution loop.

comms/peers

List discoverable peers from configured TrustedPeers and active in-process registrations. Requires the comms feature.
{
  "jsonrpc": "2.0",
  "id": 9,
  "method": "comms/peers",
  "params": {
    "session_id": "01936f8a-..."
  }
}
session_id
string
required
Session ID to query peers for.

skills/list

List all skills with provenance information, including active and shadowed entries.
{"jsonrpc":"2.0","id":12,"method":"skills/list"}
skills
array
List of SkillEntry objects with id, name, description, scope, source, is_active, and optional shadowed_by.
Returns error -32603 if skills are not enabled.

skills/inspect

Inspect a skill’s full content (body).
{
  "jsonrpc": "2.0",
  "id": 13,
  "method": "skills/inspect",
  "params": {
    "id": "task-workflow",
    "source": null
  }
}
id
string
required
Skill ID to inspect (e.g. "task-workflow", "extraction/email").
source
string | null
default:"null"
Load from a specific named source, bypassing first-wins resolution. Useful for inspecting shadowed skills.

MCP methods

mcp/add

Stage a live MCP server addition for a running session. The server is connected at the next turn boundary.
{
  "jsonrpc": "2.0",
  "id": 14,
  "method": "mcp/add",
  "params": {
    "session_id": "01936f8a-...",
    "server_name": "my-tools",
    "server_config": {
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "@my/mcp-server"]
    },
    "persisted": false
  }
}
session_id
string
required
Session ID to add the server to.
server_name
string
required
Name for the MCP server.
server_config
object
required
MCP server configuration (transport, command, args, url, etc.).
persisted
bool
default:"false"
Whether to also write the server to disk config.

mcp/remove

Stage removal of an MCP server from a running session. Active tool calls drain before the server disconnects at the next turn boundary.
{
  "jsonrpc": "2.0",
  "id": 15,
  "method": "mcp/remove",
  "params": {
    "session_id": "01936f8a-...",
    "server_name": "my-tools",
    "persisted": false
  }
}
session_id
string
required
Session ID to remove the server from.
server_name
string
required
Name of the MCP server to remove.
persisted
bool
default:"false"
Whether to also remove from disk config.

mcp/reload

Reload one or all MCP servers for a running session. Useful after config changes.
{
  "jsonrpc": "2.0",
  "id": 16,
  "method": "mcp/reload",
  "params": {
    "session_id": "01936f8a-...",
    "server_name": "my-tools"
  }
}
session_id
string
required
Session ID to reload servers for.
server_name
string | null
default:"null"
Specific server to reload. If null, reloads all servers.

Models

models/catalog

Return the curated model catalog with provider profiles, capability metadata, and parameter schemas.
{"jsonrpc":"2.0","id":17,"method":"models/catalog"}
The catalog is compiled from meerkat-models at build time. No parameters are required.
contract_version
string
Contract version for the catalog response.
providers
array
List of provider entries, each containing provider, default_model_id, and models.
providers[].models[].profile
object
Model profile with capability flags (supports_temperature, supports_thinking, supports_reasoning) and params_schema.

Capabilities

capabilities/get

Return runtime capabilities with status resolved against config. This lists every capability known to Meerkat with its current status (available, disabled by policy, not compiled, etc.).
{"jsonrpc":"2.0","id":8,"method":"capabilities/get"}
Possible status values:
StatusShapeMeaning
Available"Available"Compiled in, config-enabled, protocol supports it
DisabledByPolicy{"DisabledByPolicy": {"description": "..."}}Compiled in but disabled by policy
NotCompiled{"NotCompiled": {"feature": "..."}}Feature flag absent at compile time
NotSupportedByProtocol{"NotSupportedByProtocol": {"reason": "..."}}This protocol surface does not support it

Config methods

config/get

Read current realm config envelope.
{"jsonrpc":"2.0","id":9,"method":"config/get"}

config/set

Replace config, optionally using generation CAS.
{
  "jsonrpc":"2.0",
  "id":10,
  "method":"config/set",
  "params":{
    "config": {"agent":{"model":"gpt-5.2"}},
    "expected_generation": 3
  }
}

config/patch

Merge-patch the config (RFC 7396).
{
  "jsonrpc":"2.0",
  "id":11,
  "method":"config/patch",
  "params":{
    "patch":{"agent":{"max_tokens_per_turn":8192}},
    "expected_generation": 4
  }
}
config/set also accepts a direct config object as params for compatibility. In that mode, no CAS check is applied.

Notifications

During turn execution, the server emits session/event notifications containing serialized AgentEvent payloads:
{
  "jsonrpc": "2.0",
  "method": "session/event",
  "params": {
    "session_id": "01936f8a-...",
    "event": {
      "type": "text_delta",
      "delta": "Rust is"
    }
  }
}
Event types match the AgentEvent enum in meerkat-core:
EventDescription
run_startedAgent execution began
run_completedAgent run finished
run_failedAgent run failed
turn_startedNew LLM call within the turn
text_deltaStreaming text chunk from LLM
text_completeFull text for this turn
tool_call_requestedLLM wants to call a tool
tool_result_receivedTool result processed
turn_completedLLM call finished
tool_execution_startedTool dispatch began
tool_execution_completedTool returned a result
tool_execution_timed_outTool exceeded timeout
compaction_startedContext compaction began
compaction_completedCompaction finished
compaction_failedCompaction failed
budget_warningApproaching resource limits
retryingRetrying after transient error
hook_startedHook execution began
hook_completedHook finished
hook_failedHook execution failed
hook_deniedHook blocked operation
hook_rewrite_appliedHook rewrote content
hook_patch_publishedHook published a patch
skills_resolvedSkills loaded for turn
skill_resolution_failedSkill resolution failed
tool_config_changedTool visibility or MCP config changed
interaction_completeInteraction-scoped stream completed
interaction_failedInteraction-scoped stream failed
stream_truncatedBackpressure dropped intermediate events

session/stream_event notifications

When a session event stream is open (via session/stream_open), the server emits session/stream_event notifications. The notification payload mirrors session/event, but is scoped to the explicit stream handle.
{
  "jsonrpc": "2.0",
  "method": "session/stream_event",
  "params": {
    "stream_id": "550e8400-e29b-41d4-a716-446655440000",
    "sequence": 1,
    "session_id": "sess_123",
    "event": { "...": "..." }
  }
}

mob/stream_event notifications

When a mob event stream is open (via mob/stream_open), the server emits mob/stream_event notifications. Requires the mob feature.
{
  "jsonrpc": "2.0",
  "method": "mob/stream_event",
  "params": {
    "stream_id": "550e8400-e29b-41d4-a716-446655440000",
    "sequence": 1,
    "event": { "...": "..." }
  }
}
For mob-wide streams the event is an AttributedEvent (source + profile + envelope). For per-member streams the event is the raw EventEnvelope<AgentEvent>.

Error codes

Standard JSON-RPC codes plus Meerkat-specific application codes:
CodeNameDescription
-32700Parse errorInvalid JSON
-32600Invalid requestNot a valid JSON-RPC request
-32601Method not foundUnknown method
-32602Invalid paramsMissing or invalid parameters
-32603Internal errorServer error
-32001Session not foundSession ID does not exist
-32002Session busyTurn already in progress
-32003Session not runningSession not in running state
-32010Provider errorLLM provider issue (missing key, auth)
-32011Budget exhaustedResource limits reached
-32012Hook deniedHook blocked the operation
-32013Agent errorInternal agent error
-32020Capability unavailableRequired capability not available
-32021Skill not foundRequested skill does not exist
-32022Skill resolution failedSkill resolution error

Architecture

The RPC server is stateful: agents stay alive between turns. This is the key difference from REST (stateless per-request) and MCP (callback pattern).
Client (IDE, app) <--stdio JSONL--> RpcServer
                                       |
                                  MethodRouter
                                       |
                                  SessionRuntime
                                   /    |    \
                            Session  Session  Session
                             Task    Task     Task
                              |       |        |
                            Agent   Agent    Agent
                         (exclusive ownership)
Each session gets a dedicated tokio task that exclusively owns the Agent. This solves the cancel(&mut self) requirement without mutex. Commands (StartTurn, Interrupt, Shutdown) are sent via channels.
Backpressure: The notification channel is bounded. When the client reads slowly, the agent naturally slows down.

Comparison with other surfaces

CLIRESTMCPRPC
StatefulNoNoNoYes
StreamingstderrSSEOptionalJSONL notifications
Multi-sessionNoNoNoYes
CancellationCtrl+CN/AN/Aturn/interrupt
BidirectionalNoNo (SSE one-way)PartialYes

See also