Appearance
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:bashcurl -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-mcpbinary, provided by your Opaline operator.
Configuration
The server reads four environment variables:
| Variable | Purpose |
|---|---|
DATABASE_URL | The engine's Postgres connection. |
OPALINE_PEPPER | Server-side pepper for API-key hashing. |
OPALINE_KMS_FILE | The sealed signing-key file (checkpoint + KEK). |
OPALINE_TENANT_KEY | The 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-mcpYou 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.validityversion1.2.0with 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_KEYbelongs to, with exactly that key's scopes. There's no privilege escalation through MCP. - Every
decidean agent makes writes the trail and meters usage, identical to an HTTP decide. Use anopl_test_key for experimentation (test namespace, unmetered).