Skip to content

MCP setup

Opaline ships a Model Context Protocol server so an AI agent (Claude Desktop, Cursor, or any MCP client) can drive the engine directly (decide, simulate, inspect packs, and verify the trail) through the exact same logic as the HTTP API.

What it is

The MCP server (opaline-mcp) is a stdio JSON-RPC server whose tools dispatch through the engine's in-process router. Authentication, scopes, rate limits, quota, idempotency, and tenant isolation are the same code as the HTTP surface. The MCP interface is structurally the HTTP surface, not a separate implementation.

  • Transport: stdio, newline-delimited JSON (MCP protocol 2024-11-05).
  • Auth: a tenant data-plane key (opl_live_ / opl_test_).
  • Tools: decide, simulate, pack_list, pack_get, trail_query, trail_verify, usage_summary, tools_list. (Admin operations are deliberately not exposed to the agent surface.)

Operator-run, co-located

The MCP server runs co-located with the engine. It builds the engine state in process, so it needs the database and signing-key file, not just an API key. That makes it operator-side: it runs wherever Opaline runs. A remote MCP client (an agent connecting to api.opaline.dev with just a tenant key) is on the roadmap; today's server is co-located.

Prerequisites

  • Operator access to a running Opaline engine (Postgres + the sealed signing-key file).
  • A tenant data-plane key with the scopes you want the agent to use (at minimum decide). Mint one with your master key:
    bash
    curl -X POST "https://api.opaline.dev/v1/keys" \
      -H "Authorization: Bearer opl_admin_…" \
      -H "Content-Type: application/json" \
      -d '{ "scopes": ["decide", "simulate", "manage_packs"] }'
  • The opaline-mcp binary, provided by your Opaline operator.

Configuration

The server reads four environment variables:

VariablePurpose
DATABASE_URLThe engine's Postgres connection.
OPALINE_PEPPERServer-side pepper for API-key hashing.
OPALINE_KMS_FILEThe sealed signing-key file (checkpoint + KEK).
OPALINE_TENANT_KEYThe tenant data-plane key the agent acts as.

Connect an MCP client

Claude Desktop

Edit claude_desktop_config.json (Settings → Developer → Edit Config) and add:

json
{
  "mcpServers": {
    "opaline": {
      "command": "/path/to/opaline-mcp",
      "env": {
        "DATABASE_URL": "postgres://opaline:…@localhost/opaline",
        "OPALINE_PEPPER": "…",
        "OPALINE_KMS_FILE": "/path/to/kms.key",
        "OPALINE_TENANT_KEY": "opl_live_…"
      }
    }
  }
}

Restart Claude Desktop; "opaline" appears in the tools menu.

Cursor / other clients

Any MCP client that launches a stdio server works. Point its command at the opaline-mcp binary with the same env. In Cursor: Settings → MCP → Add, with command = the binary path and the four env vars above.

Verify it

A quick manual smoke (the server reads JSON-RPC from stdin, one message per line):

bash
printf '%s\n%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
  | OPALINE_TENANT_KEY=opl_live_… \
    DATABASE_URL=… OPALINE_PEPPER=… OPALINE_KMS_FILE=… \
    opaline-mcp

You should see the server info and the eight tools. From the agent, ask it to evaluate something. For example:

"Use opaline to decide pack acme.bill.validity version 1.2.0 with facts { vat_rate: 0.1, total: 1250 }."

The agent calls the decide tool and gets back the full decision (status, score, per-rule outcomes), the same result the HTTP API returns, recorded in the same trail.

Notes

  • The agent acts as the tenant the OPALINE_TENANT_KEY belongs to, with exactly that key's scopes. There's no privilege escalation through MCP.
  • Every decide an agent makes writes the trail and meters usage, identical to an HTTP decide. Use an opl_test_ key for experimentation (test namespace, unmetered).