Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

RiffDB MCP Agent Cookbook

RiffDB exposes policy-filtered database operations through MCP. Use tools/list after initialization to discover the commands authorized for the current credential and database. Tool names contain lowercase letters, digits, and underscores only.

Deployed Application Guide

When an active contract is visible, resources/list also exposes riffdb://application/guide. Reading it performs fresh authorization and renders the exact same-fence application catalog: active contract identity, visible generated operation names, schema and command links, and visible consistency surfaces. It is non-subscribable and never contains credentials, source text, hidden-operation counts, or inferred permissions. Hosted HTTP and stdio use the same renderer.

Values

  • Send signed or unsigned integers as ordinary JSON integers when the generated schema says integer; RiffDB resolves signedness after selecting the operation schema. Tagged {"$i64":"2"} and {"$u64":"2"} remain accepted compatibility forms.
  • Send fixed-scale decimals with the generated exact decimal object. Do not send a JSON floating-point number.
  • Send UUID values as canonical lowercase strings, for example "01900000-0000-7000-8000-000000000001".
  • Send enum variants as their declared strings, for example "Linear".
  • Follow each tool’s inputSchema; undeclared properties are rejected.

Mutating Commands

Choose a fresh caller-owned idempotency_key for each logical command. Preserve that key until the result is known. Never generate a new key merely because a connection was interrupted.

A declared business rejection is a successful MCP tool call with a typed outcome. Branch on its declared outcome field rather than parsing text or treating it as a protocol failure.

If a connection fails after submission, the command may have committed. Retry the same command with the same input and idempotency key, or resolve the returned outcome URI. Reusing a key with different canonical input fails closed.

Discovery and Documentation

tools/list is the authorized catalog for the selected database and current credential. A missing command may be absent, stale, or unauthorized; do not infer which.

Use riffdb_application_catalog when an agent needs bounded symbolic introspection beyond the immediately callable tool list. It returns only authorized names, public types, source-relative spans, and closed feature availability. Page with its opaque lowercase cursor; do not decode it or retry an invalid cursor as a first-page request. The catalog intentionally never returns numeric compiler IDs, raw plans, capability details, storage keys, or hidden totals.

For a command resource:

  • riffdb://command/<lineage>/<command-id>/docs is the invocation guide with inputs, a complete MCP call example, declared outcomes, and retry guidance.
  • riffdb://command/<lineage>/<command-id>/plan is the compiler-oriented executable plan and generated schema detail.

Use /docs to call a command. Use /plan when inspecting exact compiler or dependency behavior.

Input Errors

Invalid tool arguments return one redacted riffdb.mcp.input-error/v1 diagnostic. Its path is a JSON Pointer, code classifies the first deterministic violation, and expected describes public schema shape. The error never echoes the submitted value.

Database Selection

Each MCP connection is bound to one configured database alias. Stdio selects it in mcp.toml; hosted MCP uses the riffdb-database header. Credentials are database-bound and cannot authorize another database.

Authenticated server_health and active-contract responses include the selected database alias; health also includes the configured authentication audience. Check these before deploying or mutating. To validate an stdio configuration without starting an MCP session, run:

riffdb-mcp doctor --config ~/.config/riffdb/mcp-ea.toml

doctor first uses authenticated health when the role permits it. A narrow application role need not gain health authority: the generated application MCP config retains the expected audience, and doctor instead proves the credential and database route through capability-filtered tool discovery.

The bootstrap MCP credential is an authoring identity: validation, catalog, deployment, and health. A separately bound application-role credential is the runtime identity for named queries and commands. Register a second MCP process with that application credential rather than widening the bootstrap identity.

Application-tool discovery is deliberately not an execution proof. It shows a compiled command only for an exact InvokeCommand permission and a named query only for an exact contract-lineage, query-module-hash, and query-name ExecuteNamedQuery permission. Tenant and partition scoping do not hide the operation because its actual partition is derived from invocation inputs. Each call resolves the tool again and performs fresh current-policy authorization against those inputs; revocation, scope, module substitution, and query-name substitution therefore fail closed after an earlier successful tool listing.

Deployed named-query tools use the compiler-owned <module_snake>_<query_snake> name, advertise the generated parameter and result schemas, and execute one named query in one snapshot. They never submit ad-hoc RiffQL or gain raw entity/index authority.

A named query with a compiler-declared Cursor or Cursor? uses the generated pagination result profile:

{"result":{"outcome":"Found","items":[]},"page":{"next_cursor":null}}

Read business fields only below result. When page.next_cursor is a string, pass that exact opaque 22-character value back in the cursor parameter named by the tool’s input schema (commonly after). A null cursor is the final page. Do not decode, modify, log, or substitute this value, and do not confuse it with the lowercase 32-character cursors used by MCP discovery and resources. Generated catalog V5 identifies this result profile. Older exact V2–V4 catalogs keep their unpaged flat results byte-for-byte; callers that select V5 must understand the envelope and fail locally on version skew. Invalid, stale, expired, mismatched, or denied continuations fail without structured content and without echoing the cursor.

Reactive operations

Reactive application roles may discover riffdb_event_next, riffdb_event_ack, riffdb_event_nack, riffdb_event_seek, riffdb_event_status, and riffdb_query_watch, filtered by their exact permissions. Tool names contain underscores rather than dots for broad MCP host compatibility.

Reactive parameters use the exact tagged scalar objects advertised by each tool schema. This prevents JSON number precision loss and preserves durable type identity. For example, UUID and signed-integer parameters are written as:

{
  "parameters": {
    "workspace_id": {
      "type": "uuid",
      "value": "01900000-0000-7000-8000-000000000001"
    },
    "after_sequence": { "type": "i64", "value": "42" }
  },
  "consumer_name": "Worker_1"
}

Decimals include their fixed precision and scale; enums include the compiler-pinned type_id, variant_id, and display name. Use the generated schema rather than guessing these identities.

Treat event delivery as at least once. Perform the intended idempotent work, then acknowledge with the exact event ID, lease token, and history incarnation returned by riffdb_event_next. A lease token is not authority and may be stale after retry, restore, or expiry. Seek requires separate administrative authority.

Persist the cursor from each applied riffdb_query_watch update. Snapshot and reset replace local state; patch applies its ordered closed operations; checkpoint advances the cursor without changing state; terminal requires the agent or application to clear retained query data and stop.

Subscribe to riffdb://reactive/wakeup for reactive work hints. Its resource body contains one opaque generation and notifications/resources/updated contains only that URI. Both are coalescible hints, never an event delivery, work count, commit sequence, or acknowledgement. Retrieve work through an authorized reactive tool and rely on the durable checkpoint or cursor for correctness. Fetch once immediately after subscribing; the first notification represents a later change, not the current queue state. See Reactive Application Clients.

Contextual work and reactions

Use riffdb_contextual_next for an agent subscription. One call returns at most one leased event, fresh named-query hydrations sharing one context_head, and the currently authorized declared reactions. Use only a reaction returned in that item.

Call riffdb_contextual_react with the exact reaction name and causation token from the item. RiffDB derives and binds the command idempotency value, validates the live lease and current authority, and records the causing event with the command provenance. If the response is uncertain, repeat the same reaction; do not invent a replacement command identity. An expired token can resolve an already committed exact reaction but cannot admit a new command.

After durable success, call riffdb_contextual_ack with the event ID, lease token, and history incarnation. Use riffdb_contextual_nack for a bounded retry and riffdb_contextual_status to inspect durable progress. A redelivered item has freshly recomputed context and may expose a different authorized reaction set. MCP notifications remain payload-free hints; they never consume or acknowledge contextual work.