---
title: "MCP"
description: "Use Meerkat as an MCP client to call external tools, or expose Meerkat as MCP tools for other clients."
icon: "plug"
---

Model Context Protocol (MCP) is the tool protocol Meerkat uses in two ways: as a **client** calling external MCP servers for tools, and as a **server** exposing itself as MCP tools for other clients.

## Getting started as a client

<Steps>
  <Step title="Add an MCP server">
    ```bash
    rkat mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /tmp
    ```
  </Step>
  <Step title="Verify it's registered">
    ```bash
    rkat mcp list
    ```
  </Step>
  <Step title="Use it in a session">
    The agent will automatically discover and use tools from registered MCP servers.
  </Step>
</Steps>

## Tool overview (server mode)

The `meerkat-mcp-server` crate exposes Meerkat as MCP tools that other clients can call.

`meerkat_run` and `meerkat_resume` keep the same public MCP tool contract, but
their execution path is runtime-backed: `meerkat_run` allocates a session
through the shared session service and waits for that admitted turn to finish,
and `meerkat_resume` re-enters the same `session_id` instead of starting a
second surface-local execution loop.

| Tool | Description |
|------|-------------|
| `meerkat_run` | Start a new agent session |
| `meerkat_resume` | Continue a session or provide tool results |
| `meerkat_help` | Ask Meerkat usage help with the embedded platform skill |
| `meerkat_read` | Read a session's state |
| `meerkat_history` | Read a session's committed history |
| `meerkat_sessions` | List sessions in the active realm |
| `meerkat_blob_get` | Fetch a blob payload by id |
| `meerkat_interrupt` | Interrupt an in-flight turn |
| `meerkat_archive` | Archive (remove) a session |
| `meerkat_config` | Get or update server config |
| `meerkat_capabilities` | Query runtime capabilities |
| `meerkat_models_catalog` | List available models with provider profiles and capabilities |
| `meerkat_skills` | List or inspect available skills |
| `meerkat_schedule_*` tools | Agent-facing schedule create/get/list/update/pause/resume/delete/occurrences tools |
| `meerkat_mcp_add` | Stage a live MCP server addition on an active session |
| `meerkat_mcp_remove` | Stage a live MCP server removal on an active session |
| `meerkat_mcp_reload` | Stage a live MCP server reload on an active session |
| `meerkat_event_stream_open` | Open a session-level agent event stream |
| `meerkat_event_stream_read` | Read the next item from an open event stream |
| `meerkat_event_stream_close` | Close a previously opened event stream |
| `meerkat_mob_create` | Create a mob from a typed public definition (mob feature) |
| `meerkat_mob_list` | List active mobs (mob feature) |
| `meerkat_mob_status` | Get lifecycle status for one mob (mob feature) |
| `meerkat_mob_lifecycle` | Apply a lifecycle action to a mob (mob feature) |
| `meerkat_mob_spawn` | Spawn a member into a mob (mob feature) |
| `meerkat_mob_spawn_many` | Spawn multiple members into a mob (mob feature) |
| `meerkat_mob_retire` | Retire a mob member (mob feature) |
| `meerkat_mob_respawn` | Respawn a mob member with topology restore (mob feature) |
| `meerkat_mob_wire` | Wire two mob members or an external peer (mob feature) |
| `meerkat_mob_unwire` | Remove mob comms wiring (mob feature) |
| `meerkat_mob_member_send` | Deliver host-owned work to a specific mob member (mob feature) |
| `meerkat_mob_append_system_context` | Stage system context for a member session (mob feature) |
| `meerkat_mob_events` | Read mob event history (mob feature) |
| `meerkat_mob_flows` | List flows defined for a mob (mob feature) |
| `meerkat_mob_flow_run` | Start a mob flow run (mob feature) |
| `meerkat_mob_flow_status` | Get flow run status (mob feature) |
| `meerkat_mob_flow_cancel` | Cancel a flow run (mob feature) |
| `meerkat_mob_force_cancel` | Force-cancel a member's active work (mob feature) |
| `meerkat_mob_wait_kickoff` | Wait for autonomous kickoff completion (mob feature) |
| `meerkat_mob_wait_ready` | Wait for mob startup readiness (mob feature) |
| `meerkat_mob_profile_*` tools | Realm-scoped mob profile create/get/list/update/delete (mob feature) |
| `meerkat_mob_event_stream_open` | Open a mob-level event stream (mob feature) |
| `meerkat_mob_event_stream_read` | Read the next event from an open mob stream (mob feature) |
| `meerkat_mob_event_stream_close` | Close a previously opened mob event stream (mob feature) |
| `meerkat_comms_send` | Send a canonical comms command to a session (comms feature) |
| `meerkat_comms_peers` | List peers visible to a session (comms feature) |

<Note>
Default `rkat-mcp` builds are driven by the crate feature set. The base/default
tool surface includes core session/config/history/blob/skills tools and
schedule tools. Mob tools appear when the `mob` feature is compiled in.
</Note>

<Note>
When the `mob` feature is enabled, the public MCP host surface uses typed
`meerkat_mob_*` control-plane tools. Inside running sessions, mob capability is
still agent-side and comes from composing a mob tools factory into
`SessionBuildOptions.mob_tools`, which provides `mob_*` tools to the
model. Public host MCP surfaces should not re-export that raw dispatcher.
</Note>

## Use MCP servers as tools (client)

### CLI configuration (recommended)

Use the `rkat mcp` commands to manage MCP servers:

```bash
# Add a stdio server
rkat mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /tmp

# Add a streamable HTTP server
rkat mcp add api --transport http --url https://mcp.example.com/api

# List servers
rkat mcp list

# Remove a server
rkat mcp remove filesystem
```

### Config file format

MCP servers are stored in TOML in two scopes:

- **Project**: `.rkat/mcp.toml`
- **User**: `~/.rkat/mcp.toml`

Project config wins on name collisions.

<Accordion title="Config file examples">
  ```toml
  # Stdio server (local process)
  [[servers]]
  name = "filesystem"
  command = "npx"
  args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"]

  # Stdio server with env
  [[servers]]
  name = "database"
  command = "python"
  args = ["-m", "db_mcp_server"]
  env = { DATABASE_URL = "${DATABASE_URL}" }

  # HTTP server (streamable HTTP is default for URLs)
  [[servers]]
  name = "remote-api"
  url = "https://mcp.example.com/api"
  headers = { Authorization = "Bearer ${MCP_API_TOKEN}" }

  # Legacy SSE server
  [[servers]]
  name = "legacy-sse"
  url = "https://old.example.com/sse"
  transport = "sse"
  ```
</Accordion>

<Note>
Supported transports: **stdio**, **streamable HTTP** (default for URLs), and **SSE**.
Environment variables in config use `${VAR_NAME}` syntax.
</Note>

## Meerkat as an MCP server

### Connecting other clients

You can connect any MCP-capable client to a Meerkat MCP server. Run a server process that exposes the `meerkat_*` tools (stdio or HTTP), then point the client at it.

<Tabs>
  <Tab title="Claude Code">
    Claude Code reads MCP servers from a `.mcp.json` file in your project root.
    Example stdio config:

    ```json
    {
      "mcpServers": {
        "meerkat": {
          "command": "rkat-mcp",
          "args": [],
          "env": {
            "ANTHROPIC_API_KEY": "your-key"
          }
        }
      }
    }
    ```
  </Tab>
  <Tab title="Codex CLI">
    Codex CLI supports MCP servers via a command and also via config. Example:

    ```bash
    codex mcp add meerkat --env ANTHROPIC_API_KEY=your-key -- rkat-mcp
    ```

    You can also configure MCP servers in `~/.codex/config.toml` under
    `[mcp_servers.<name>]`.
  </Tab>
  <Tab title="Gemini CLI">
    Gemini CLI can add MCP servers via CLI or config. Example:

    ```bash
    # HTTP/streamable HTTP
    gemini mcp add --scope=project --transport=http meerkat https://your-mcp-server.example.com
    ```

    Or configure in `.gemini/settings.json` (project-scoped) with an `mcpServers`
    map that points to your server URL.
  </Tab>
</Tabs>

### Hosting the MCP server

`meerkat-mcp-server` is a library crate that provides tool schemas and handlers.
If you need a full public MCP host, embed its `tools_list()` and
`handle_tools_call*` entrypoints or run the bundled `rkat-mcp` binary. If you
need a mob-only MCP host, `meerkat-mob-mcp` exposes `public_tools_list()` and
`handle_public_tools_call()` for the typed `meerkat_mob_*` control plane.

`meerkat-mob-mcp::tools_list()` and `handle_tools_call()` remain the internal
agent-side `mob_*` dispatcher helpers; they are not the public host contract.

The bundled `rkat-mcp` binary supports realm scope flags:

```bash
rkat-mcp --realm team-alpha --instance worker-1 --realm-backend sqlite
```

If `--realm` is omitted, the server creates a new isolated realm by default.
`--realm-backend` is a creation hint only; after the first open, the manifest-pinned backend is authoritative.

## Tool reference

### meerkat_run

Start a new Meerkat agent session with the given prompt.

<CodeGroup>
```json Request (minimal)
{
  "prompt": "Write a haiku about Rust"
}
```

```json Request (full)
{
  "prompt": "Analyze this code for bugs",
  "system_prompt": "You are a senior code reviewer.",
  "model": "claude-opus-4-6",
  "max_tokens": 4096,
  "provider": "anthropic",
  "output_schema": {
    "type": "object",
    "properties": {
      "bugs": {"type": "array", "items": {"type": "string"}},
      "severity": {"type": "string"}
    },
    "required": ["bugs", "severity"]
  },
  "structured_output_retries": 2,
  "stream": false,
  "verbose": false,
  "tools": [
    {
      "name": "read_file",
      "description": "Read a file from disk",
      "input_schema": {
        "type": "object",
        "properties": {"path": {"type": "string"}},
        "required": ["path"]
      },
      "handler": "callback"
    }
  ],
  "enable_builtins": false,
  "builtin_config": {
    "enable_shell": false,
    "shell_timeout_secs": 30
  },
  "keep_alive": null,
  "comms_name": null,
  "hooks_override": null
}
```

```json Response (success)
{
  "content": [{
    "type": "text",
    "text": "{\"content\":[{\"type\":\"text\",\"text\":\"Agent response here\"}],\"session_id\":\"01936f8a-...\",\"turns\":1,\"tool_calls\":0,\"structured_output\":null,\"schema_warnings\":null}"
  }]
}
```
</CodeGroup>

#### Parameter reference

<ParamField body="prompt" type="string" required>
  User prompt for the agent.
</ParamField>

<ParamField body="system_prompt" type="string | null" default="null">
  Override system prompt.
</ParamField>

<ParamField body="model" type="string | null" default="config default">
  Model name (e.g. `"claude-opus-4-6"`, `"gpt-5.5"`).
</ParamField>

<ParamField body="max_tokens" type="u32 | null" default="config default">
  Max tokens per turn.
</ParamField>

<ParamField body="provider" type="string | null" default="inferred">
  Provider: `"anthropic"`, `"openai"`, `"gemini"`, `"self_hosted"`, `"other"`.
</ParamField>

<ParamField body="output_schema" type="object | null" default="null">
  JSON schema for structured output (wrapper or raw schema).
</ParamField>

<ParamField body="structured_output_retries" type="u32 | null" default="null">
  Max retries for structured output validation. Omit / `null` to use the product default on run or inherit the persisted session value on resume.
</ParamField>

<ParamField body="stream" type="bool" default="false">
  Stream agent events via MCP notifications.
</ParamField>

<ParamField body="verbose" type="bool" default="false">
  Enable verbose event logging (server-side).
</ParamField>

<ParamField body="tools" type="array" default="[]">
  Tool definitions for the agent (see [McpToolDef schema](#mcptooldef-schema) below).
</ParamField>

<ParamField body="enable_builtins" type="bool | null" default="null">
  Builtins override. Omit / `null` to use the default on run or inherit the persisted session value on resume.
</ParamField>

<ParamField body="builtin_config" type="object | null" default="null">
  Config for builtins (only used when `enable_builtins` is true).
</ParamField>

<ParamField body="builtin_config.enable_shell" type="bool | null" default="null">
  Shell-tools override. Omit / `null` to use the default on run or inherit the persisted session value on resume.
</ParamField>

<ParamField body="builtin_config.shell_timeout_secs" type="u64 | null" default="30">
  Default shell command timeout.
</ParamField>

<ParamField body="keep_alive" type="bool | null" default="null">
  Keep session alive after turn for comms. On `meerkat_run`, `null`/omitted uses the run default (`false`), `true` enables, and `false` explicitly disables. Requires `comms_name` when enabled.
</ParamField>

<ParamField body="comms_name" type="string | null" default="null">
  Agent name for comms.
</ParamField>

<ParamField body="hooks_override" type="HookRunOverrides | null" default="null">
  Run-scoped hook overrides.
</ParamField>

#### McpToolDef schema

<ParamField body="name" type="string" required>
  Tool name.
</ParamField>

<ParamField body="description" type="string" required>
  Tool description.
</ParamField>

<ParamField body="input_schema" type="object" required>
  JSON Schema for tool input.
</ParamField>

<ParamField body="handler" type="string | null" default="callback">
  Handler type (`"callback"` = result provided via `meerkat_resume`).
</ParamField>

When tools with `handler: "callback"` are provided and the agent requests a tool call, the response includes `pending_tool_calls`. The MCP client must execute the tool and provide results via `meerkat_resume`.

### meerkat_resume

Resume an existing runtime-backed session or provide tool results for pending
tool calls. The call waits for the resumed turn to complete and returns the same
`session_id` that `meerkat_run` originally materialized.

<CodeGroup>
```json Request (minimal)
{
  "session_id": "01936f8a-7b2c-7000-8000-000000000001",
  "prompt": "Continue with this"
}
```

```json Request (with tool results)
{
  "session_id": "01936f8a-7b2c-7000-8000-000000000001",
  "prompt": "",
  "stream": false,
  "verbose": false,
  "tools": [],
  "tool_results": [
    {
      "tool_use_id": "tc_abc123",
      "content": "File contents here...",
      "is_error": false
    }
  ],
  "enable_builtins": false,
  "builtin_config": null,
  "keep_alive": null,
  "comms_name": null,
  "model": null,
  "max_tokens": null,
  "provider": null,
  "hooks_override": null
}
```

```json Response (pending tool call)
{
  "content": [{
    "type": "text",
    "text": "{\"content\":[{\"type\":\"text\",\"text\":\"Agent is waiting for tool results\"}],\"session_id\":\"01936f8a-...\",\"status\":\"pending_tool_call\",\"pending_tool_calls\":[{\"tool_name\":\"read_file\",\"args\":{\"path\":\"/tmp/data.txt\"}}]}"
  }]
}
```
</CodeGroup>

#### Parameter reference

<ParamField body="session_id" type="string" required>
  Session ID to resume.
</ParamField>

<ParamField body="prompt" type="string" required>
  Follow-up prompt (can be empty when providing tool results).
</ParamField>

<ParamField body="stream" type="bool" default="false">
  Stream agent events via MCP notifications.
</ParamField>

<ParamField body="verbose" type="bool" default="false">
  Enable verbose event logging.
</ParamField>

<ParamField body="tools" type="array" default="[]">
  Tool definitions (should match the original run).
</ParamField>

<ParamField body="tool_results" type="array" default="[]">
  Tool results for pending tool calls.
</ParamField>

<ParamField body="tool_results[].tool_use_id" type="string" required>
  ID of the tool call.
</ParamField>

<ParamField body="tool_results[].content" type="string" required>
  Result content (or error message).
</ParamField>

<ParamField body="tool_results[].is_error" type="bool" default="false">
  Whether this is an error result.
</ParamField>

<ParamField body="enable_builtins" type="bool | null" default="null">
  Builtins override. Omit / `null` to inherit the persisted session value.
</ParamField>

<ParamField body="builtin_config" type="object | null" default="null">
  Builtin tool config.
</ParamField>

<ParamField body="builtin_config.enable_shell" type="bool | null" default="null">
  Shell-tools override. Omit / `null` to inherit the persisted session value.
</ParamField>

<ParamField body="keep_alive" type="bool | null" default="null">
  Keep-alive override for this resume. `null` = inherit persisted session intent, `true` = enable, `false` = disable.
</ParamField>

<Note>
`meerkat_run` and `meerkat_resume` follow the same commit/cancel rule as the other interactive surfaces: committed success is not rewritten to cancellation, and post-commit create failure returns session identity so the session can be resumed.
</Note>

<ParamField body="comms_name" type="string | null" default="from session">
  Agent name for comms.
</ParamField>

<ParamField body="model" type="string | null" default="from session">
  Model override. On materialized sessions this hot-swaps the LLM client for the remainder of the session.
</ParamField>

<ParamField body="max_tokens" type="u32 | null" default="from session">
  Max tokens override.
</ParamField>

<ParamField body="provider" type="string | null" default="from session">
  Provider override. Typically inferred from `model`. Used with `model` for mid-session provider switching.
</ParamField>

<ParamField body="hooks_override" type="HookRunOverrides | null" default="null">
  Run-scoped hook overrides.
</ParamField>

### Response format

Both `meerkat_run` and `meerkat_resume` return MCP-standard tool results. The inner `text` field is a JSON-encoded payload containing:

<ResponseField name="content" type="array">
  MCP content blocks with the agent's text.
</ResponseField>

<ResponseField name="session_id" type="string">
  Session ID (save for `meerkat_resume`).
</ResponseField>

<ResponseField name="turns" type="u32">
  Number of LLM calls made.
</ResponseField>

<ResponseField name="tool_calls" type="u32">
  Number of tool calls executed.
</ResponseField>

<ResponseField name="structured_output" type="object | null">
  Parsed structured output.
</ResponseField>

<ResponseField name="schema_warnings" type="array | null">
  Schema compatibility warnings.
</ResponseField>

### meerkat_config

Get or update realm config for this MCP server instance.

<CodeGroup>
```json Get
{ "action": "get" }
```

```json Set
{
  "action": "set",
  "config": { "agent": { "model": "gpt-5.5" } },
  "expected_generation": 3
}
```

```json Patch
{
  "action": "patch",
  "patch": { "agent": { "max_tokens_per_turn": 8192 } },
  "expected_generation": 4
}
```
</CodeGroup>

<ParamField body="action" type="string" required>
  One of `"get"`, `"set"`, `"patch"`.
</ParamField>

<ParamField body="config" type="object | null">
  Full config to replace (for `set` action).
</ParamField>

<ParamField body="patch" type="object | null">
  RFC 7396 merge-patch delta (for `patch` action).
</ParamField>

<ParamField body="expected_generation" type="u64 | null">
  Optional optimistic concurrency check for `set` and `patch`.
</ParamField>

Response includes config envelope fields:

- `config`
- `generation`
- `realm_id`
- `instance_id`
- `backend`
- `resolved_paths`

### meerkat_capabilities

Returns the runtime capability set with status resolved against config.

<CodeGroup>
```json Request
{}
```

```json Response
{
  "contract_version": {"major": 0, "minor": 6, "patch": 6},
  "capabilities": [
    {
      "id": "sessions",
      "description": "Session lifecycle management",
      "status": "Available"
    },
    {
      "id": "structured_output",
      "description": "Structured output extraction with JSON schema",
      "status": "Available"
    },
    {
      "id": "hooks",
      "description": "Lifecycle hooks for tool and turn events",
      "status": "Available"
    },
    {
      "id": "builtins",
      "description": "Built-in tools (task management)",
      "status": {"DisabledByPolicy": {"description": "Disabled by config"}}
    },
    {
      "id": "shell",
      "description": "Shell command execution",
      "status": {"DisabledByPolicy": {"description": "Disabled by config"}}
    },
    {
      "id": "comms",
      "description": "Inter-agent communication",
      "status": {"NotCompiled": {"feature": "comms"}}
    },
    {
      "id": "memory_store",
      "description": "Semantic memory indexing",
      "status": "Available"
    },
    {
      "id": "skills",
      "description": "Skill loading and injection",
      "status": "Available"
    }
  ]
}
```
</CodeGroup>

Possible `status` values:

| Status | Shape | Meaning |
|--------|-------|---------|
| `Available` | `"Available"` | Compiled in, config-enabled |
| `DisabledByPolicy` | `{"DisabledByPolicy": {"description": "..."}}` | Compiled in but disabled |
| `NotCompiled` | `{"NotCompiled": {"feature": "..."}}` | Feature flag absent |
| `NotSupportedByProtocol` | `{"NotSupportedByProtocol": {"reason": "..."}}` | Protocol does not support it |

### meerkat_models_catalog

Return the curated model catalog with provider profiles, capability metadata, and parameter schemas.

<CodeGroup>
```json Request
{}
```

```json Response
{
  "contract_version": "0.6.19",
  "providers": [
    {
      "provider": "anthropic",
      "default_model_id": "claude-opus-4-7",
      "models": [
        {
          "id": "claude-opus-4-7",
          "display_name": "Claude Opus 4.7",
          "tier": "recommended",
          "context_window": 1000000,
          "max_output_tokens": 128000,
          "profile": {
            "model_family": "claude-opus-4",
            "supports_temperature": false,
            "supports_thinking": true,
            "supports_reasoning": false,
            "params_schema": {}
          }
        }
      ]
    }
  ]
}
```
</CodeGroup>

No parameters required. The catalog is resolved from built-in model metadata plus config-backed provider/server entries.

### meerkat_skills

List available skills with provenance information, or inspect one skill's full
body by typed `SkillKey`.

<CodeGroup>
```json List all skills
{ "action": "list" }
```

```json Inspect a skill
{
  "action": "inspect",
  "skill_key": {
    "source_uuid": "00000000-0000-4b11-8111-000000000001",
    "skill_name": "task-workflow"
  }
}
```

```json Inspect a specific source
{
  "action": "inspect",
  "skill_key": {
    "source_uuid": "00000000-0000-4b11-8111-000000000001",
    "skill_name": "task-workflow"
  },
  "source": "00000000-0000-4b11-8111-000000000001"
}
```

```json List response
{
  "skills": [
    {
      "key": {
        "source_uuid": "00000000-0000-4b11-8111-000000000001",
        "skill_name": "task-workflow"
      },
      "name": "Task Workflow",
      "description": "How to use task tools",
      "scope": "builtin",
      "source": {
        "source_uuid": "00000000-0000-4b11-8111-000000000001",
        "display_name": "embedded",
        "transport_kind": "embedded",
        "fingerprint": "embedded:inventory",
        "status": "active"
      },
      "is_active": true
    }
  ]
}
```

```json Inspect response
{
  "key": {
    "source_uuid": "00000000-0000-4b11-8111-000000000001",
    "skill_name": "task-workflow"
  },
  "name": "Task Workflow",
  "description": "How to use task tools",
  "scope": "builtin",
  "source": {
    "source_uuid": "00000000-0000-4b11-8111-000000000001",
    "display_name": "embedded",
    "transport_kind": "embedded",
    "fingerprint": "embedded:inventory",
    "status": "active"
  },
  "body": "# Task Workflow\n\n..."
}
```
</CodeGroup>

<ParamField body="action" type="string" required>
  `"list"` to list all skills, or `"inspect"` to load one skill's full body.
</ParamField>

<ParamField body="skill_key" type="object">
  Required for `inspect`. The typed skill identity with `source_uuid` and
  `skill_name` fields.
</ParamField>

<ParamField body="source" type="string">
  Optional source UUID selector for `inspect`; omit it to load the canonical
  source for `skill_key`.
</ParamField>

The list response includes both active and shadowed skills. Shadowed skills have
`is_active: false` and a `shadowed_by` field indicating which source has
precedence. Inspect canonicalizes `skill_key` through the identity registry
before loading the body.
