Skip to main content
Meerkat’s tool system is trait-based. You implement AgentToolDispatcher, and the engine handles dispatch, parallel execution, and result injection. MCP servers are first-class — register them and their tools appear alongside your custom tools with no code changes.

Mental model

At the concept level, tools answer one question: how does the agent act on the world? The important conceptual layers are:
  • custom tools you own
  • built-in tools Meerkat can compose
  • MCP-provided external tools
  • runtime visibility/scoping rules
The Rust trait example below is an implementation detail of that model, not the model itself.

Custom tools

Implement the AgentToolDispatcher trait:
ToolCallView is a zero-allocation borrowed view ({ id: &str, name: &str, args: &RawValue }). When the model requests multiple tool calls, Meerkat dispatches them in parallel.

MCP servers

Register any MCP server and its tools automatically appear in the agent’s tool set:
Config is stored in .rkat/mcp.toml (project) or ~/.rkat/mcp.toml (user). Supports stdio, streamable HTTP, and SSE transports. OAuth-protected HTTP servers discover auth at connect time; use rkat mcp login <name> or rkat run --mcp-auth interactive when browser login is needed. See the MCP reference for full details.

Built-in tools

Meerkat ships with tool categories resolved per agent. Factory category flags default off; product surfaces may apply their own explicit preset (for example, the CLI defaults to --tools safe). Shell tools support allow/deny list security policies. Runtime tool visibility can also be shaped with mob overlays and turn-boundary tool-scope updates. See the built-in tools reference for parameter details. Image generation and web search are independent category decisions. Enabling either one does not implicitly expose general builtins. Conversely, disabling general builtins does not prevent a runtime-backed build from explicitly enabling one of those capabilities. Explicit enables fail closed when the selected runtime cannot provision the requested capability. The current direct rkat run, REST, and JSON-RPC session builders leave image generation at inherit, which the outer factory treats as hidden; they do not yet expose an image-generation enable switch. --allow-tool generate_image only narrows an already composed surface and cannot enable the category. For nontrivial Meerkat-owned tool families, companion skills provide the agent instruction manual. Tool descriptions stay short and schema-oriented; skills such as workgraph-workflow, schedule-workflow, task-workflow, and shell-patterns explain the operating posture for the tool family.

Execution contracts

Tool visibility and tool execution are separate decisions. A visible tool has an execution contract that declares the modes it supports:
  • fast execution for ordinary request/response calls
  • streaming execution with progress and cancellation policy
  • detached execution backed by a durable job record
The runtime resolves a call to one supported mode, applies the narrowest deadline in the chain, and supervises progress or cancellation through the same tool gateway. Detached execution records its restart class explicitly. For example, a background shell command is non_resumable: its durable job truth survives a host restart, but a lost subprocess becomes worker_lost and is never silently replayed. Tool definitions also carry source provenance, and dispatchers classify calls as read-only, mutating, or unknown. Hooks and policy layers receive those typed facts rather than inferring authority from a tool name.

Tool scoping

Tool visibility can change during a session without restarting the agent. Changes are staged then atomically applied at the turn boundary — the LLM never sees a tool list change mid-stream. External filters. Callers can stage an allow-list or deny-list filter programmatically through ToolScopeHandle. This is distinct from MCP server lifecycle management. Per-turn overlays. Mob flow steps can restrict tools for a single turn via TurnToolOverlay (allow + deny). The overlay is ephemeral — it’s cleared after the turn completes. Live MCP mutation. MCP servers can be added or removed from a running session. Additions connect the server and register its tools; removals drain in-flight calls before finalizing. Both are staged and applied at the next turn boundary. Composition rule: Most-restrictive wins. Multiple allow-lists intersect, multiple deny-lists union, and deny always beats allow. The conversation records a typed tool_config system notice when the tool set changes, and a tool_config_changed event is emitted to the event stream.

Live MCP controls

MCP servers can be added, removed, or reloaded on a running session via JSON-RPC, REST, MCP-server tools, or SDK helpers:
All mutations are staged and applied at the next turn boundary. Set persisted: true to write the change to disk config so it survives restart. See the RPC reference for full parameter details.

Surface availability

See the built-in tools reference for the mechanical details of factory flags and per-build overrides.

Multimodal tool results

Tools can return rich content beyond plain text. The injected runtime shape is ToolResult.content: Vec<ContentBlock>, with helper constructors for text-only or multimodal output.
  • ToolResult::new(...) — the standard text-only path. The string becomes a single text content block.
  • ToolResult::with_blocks(...) — returns one or more content blocks directly, including images and video.
  • Built-in tools that expose richer output may internally use ToolOutput::Blocks(...), but the persisted/runtime-facing result shape is still ToolResult.content.
ContentBlock is non-exhaustive and currently has five variants:
  • ContentBlock::Text { text } — plain text content.
  • ContentBlock::Image { media_type, ... } — inline or blob-backed image content.
  • ContentBlock::Video { media_type, duration_ms, ... } — inline or URI-referenced video content. Video blocks are accepted only on Gemini user-message input paths and are rejected in tool results. Vertex Gemini can consume gs:// references directly; Gemini API sessions can consume public or already-registered file URIs, and register gs:// references first when the session has Google bearer auth.
  • ContentBlock::Structured { data } — canonical opaque JSON returned by a tool without first stringifying it into text.
  • ContentBlock::SkillContext { skill_key, text } — runtime-authored skill activation context with its canonical source identity preserved.
The built-in view_image tool reads an image file from disk and returns a result containing image content blocks. It supports PNG, JPEG, GIF, WebP, and SVG formats up to 5 MB. The tool is automatically hidden from models that lack vision support via capability-aware tool visibility. The built-in generate_image tool is session-owned runtime dispatch. It lets a model request generated or edited images through universal fields plus provider-owned provider_params. Generated image bytes are stored as blobs and committed as AssistantBlock::Image transcript blocks, so every surface reads the same image_id/blob_ref history and fetches bytes through blob/get or model-facing blob_save_file. The blob file bridge tools are registered only when the session has a blob store. blob_save_file writes decoded blob bytes to a file inside the project root, blob_load_file reads a project file into the blob store, and blob_inspect returns blob metadata without raw payload bytes. They do not expose blob listing or deletion. Custom tools can return text, image, or structured content through ToolResult::with_blocks(...). Video tool results are rejected, and SkillContext is reserved for the runtime skill-injection path.

Image generation

generate_image is a session-owned tool for creating or editing assistant images. It is registered when the runtime-backed surface supplies the image-generation machine, provider executor, planner, and blob store. In the normal composite dispatcher, Inherit is visible once that substrate is wired. The category can also be enabled independently from general builtins through a Mob profile or an in-process override_image_generation: Enable. The tool accepts a typed request under request, routes it to OpenAI or Gemini image backends, stores generated image bytes in the realm blob store, and returns structured ImageGenerationToolResult JSON with durable images[].blob_ref values. A model can then call blob_save_file to materialize that blob as a project file, for example top-news-infographic.png. For setup, provider parameters, result fields, and troubleshooting, see Image generation.

Composition

Tools from different sources (custom, MCP, built-in) are composed into a single dispatcher. The agent sees one flat tool list regardless of where each tool comes from. Hooks can observe tool calls before and after execution, and guardrails can deny unsafe calls before dispatch.

Mob tools (meerkat-mob-mcp)

Mob tools (mob_*) are provided by the meerkat-mob-mcp dispatcher and composed through the late-bound SessionBuildOptions.mob_tools factory slot.
  • CLI run composes this dispatcher when the full tool preset is selected (--tools full or --yolo).
  • rkat mob ... remains the explicit direct lifecycle surface.
  • Other session-driven surfaces can grant the same agent-side mob_* capability by installing AgentMobToolSurfaceFactory into their session build path.
  • Public host APIs should not re-export that raw dispatcher. They use typed control planes instead: mob/* on RPC/SDK surfaces and meerkat_mob_* on public MCP surfaces.