MCP server
Connect Shotoku to any MCP-compatible agent host — Claude, Cursor, Windsurf, or a custom agent — so that authorization happens automatically, mid-task, before your agent acts.
What is MCP?
MCP (Model Context Protocol) is an open standard that lets AI agents call external tools through a consistent interface. Instead of each agent needing custom integration code, MCP defines how tools are discovered, described, and called — so the same server works across Claude, Cursor, Windsurf, and any other MCP-compatible host.
When you add Shotoku as an MCP server, your agent gains direct access to its authorization tools. Before spending money, calling an API, or executing code, the agent can call authorize_action and let Shotoku make the call — automatically, inline, without you writing any integration glue.
The CLI is for you. The MCP server is for your agent.
Setup
1. Build the MCP server
From the repo root:
This produces mcp/dist/index.js — the file your agent host will run.
2. Register Shotoku with your agent host
Most MCP hosts accept a JSON config file. Add a shotoku entry:
Use absolute paths. Relative paths are resolved from the working directory where the server starts, which may differ by host.
For Claude Desktop, add this to ~/Library/Application Support/Claude/claude_desktop_config.json then restart the app.
3. Create the ledger directory
Verifying the connection
In Claude Desktop, click the tools icon (hammer) in a new conversation and look for the shotoku section. You should see five tools:
authorize_actionget_decisionget_pending_approvalsapprove_decisiondeny_decision
The tools
authorize_action
The main gate. The agent calls this before performing any action — spending money, calling an API, running code, sending a message.
| Field | Required | What it means |
|---|---|---|
| actor | yes | Who is acting — the agent's name or ID |
| action | yes | What the agent wants to do (purchase, api_call, execute_code, send_email, mcp_tool, custom) |
| resource | yes | What it's acting on — a domain, service name, or endpoint |
| amount | no | How much it costs in USD, if applicable |
| context | no | Any extra details you want recorded with the decision (must be JSON-serializable, max 16 KB) |
get_decision
Looks up a single past decision by ID. Returns the full record — original request, outcome, and reasons. Useful when the agent wants to reference what was decided earlier in a session.
get_pending_approvals
Returns every decision currently waiting for human review. The agent can surface this naturally: “You have 2 pending approvals — want to review them?” Returns an empty message when the queue is clear.
approve_decision
Approves a pending decision. Shotoku appends a new approval record to the ledger — it never mutates the original decision. Both the decision and the human approval are preserved in the audit trail.
deny_decision
Denies a pending decision. Same append-only behavior as approval.
Walkthrough
What a typical exchange looks like once Shotoku is connected:
If your policy requires human approval:
Environment variables
| Variable | Default | What it controls |
|---|---|---|
| SHOTOKU_CONFIG | shotoku.config.json | Path to the Shotoku config file |
| SHOTOKU_POLICY | policy.yaml | Path to your policy file (overrides config) |
| SHOTOKU_LEDGER | data/decisions.jsonl | Path to the local decision ledger (overrides config) |
If SHOTOKU_POLICY or SHOTOKU_LEDGER are set they take precedence. Otherwise the server reads shotoku.config.json. If no config file exists it falls back to the defaults above.