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.

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!"}}

Method overview

MethodCategoryDescription
initializeHandshakeReturns server capabilities
session/createSessionCreate session and run first turn
session/listSessionList active sessions
session/readSessionGet session state
session/archiveSessionRemove session from runtime
turn/startTurnStart a new turn on existing session
turn/interruptTurnCancel in-flight turn
capabilities/getCapabilitiesRuntime capability report
config/getConfigRead current config
config/setConfigReplace config
config/patchConfigMerge-patch config (RFC 7396)

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?"
  }
}
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_subagents
bool
default:"false"
Enable sub-agent tools (fork, spawn).
enable_memory
bool
default:"false"
Enable semantic memory (memory_search tool + compaction indexing).
host_mode
bool
default:"false"
Run in host mode for inter-agent comms (requires comms_name).
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.

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.

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 config.
{"jsonrpc":"2.0","id":9,"method":"config/get"}

config/set

Replace the config.
{"jsonrpc":"2.0","id":10,"method":"config/set","params":{"agent":{"model":"gpt-5.2"}}}

config/patch

Merge-patch the config (RFC 7396).
{"jsonrpc":"2.0","id":11,"method":"config/patch","params":{"max_tokens":8192}}

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_startedTurn execution began
text_deltaStreaming text chunk from LLM
text_completeFull text for this turn
tool_call_requestedLLM wants to call a tool
tool_execution_startedTool dispatch began
tool_execution_completedTool returned a result
turn_startedNew LLM call within the turn
turn_completedLLM call finished
run_completedTurn execution finished successfully
run_failedTurn execution failed
budget_warningApproaching resource limits
retryingRetrying after transient error

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
-32000Session not foundSession ID does not exist
-32001Session busyTurn already in progress
-32002Provider errorLLM provider issue (missing key, auth)
-32003Budget exhaustedResource limits reached
-32004Hook deniedHook blocked the operation

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