Quickstart
Put an approval step between your AI agent and the MCP servers it uses. About ten minutes from nothing to a held call in your inbox.
Install
SpotAgentIQ is one static binary with no runtime dependencies. Pick whichever is easiest:
# With Go 1.24 or newer
go install github.com/mckoy-labs/spotagentiq/cmd/spotagentiq@latest
# Or download a release binary for Linux, macOS or Windows
# https://github.com/mckoy-labs/spotagentiq/releases
spotagentiq version
There's also a Docker image for running it on a server.
See it work first
spotagentiq demo
This starts SpotAgentIQ with a fake CRM tool server and a scripted agent. Open http://localhost:8484 and use the token demo-token. The agent will:
- look up a customer, which is allowed,
- try to charge a card number it was given, which is denied,
- send the customer an email, which is held until you approve it,
- delete the customer record, which is held so you can reject it.
When it finishes, check the log it wrote and then edit any character in the file and check again:
spotagentiq verify --log /tmp/spotagentiq-demo-*/audit.jsonl
# OK: 9 entries, chain intact.
Write a config
spotagentiq init > spotagentiq.json
export SPOTAGENTIQ_TOKEN=$(openssl rand -hex 16)
Edit the file. A sensible starting point for an agent that talks to customers:
{
"agent": "support-bot",
"listen": ":8484",
"token": "${SPOTAGENTIQ_TOKEN}",
"log_path": "audit.jsonl",
"approval_timeout": "10m",
"default_action": "allow",
"upstreams": [
{ "name": "crm", "command": "npx", "args": ["-y", "@acme/crm-mcp"] }
],
"rules": [
{ "match": "*", "action": "deny", "if_args_match": "\\b\\d{13,19}\\b", "reason": "Looks like a card number" },
{ "match": "send_*", "action": "require_approval", "reason": "Outbound communication" },
{ "match": "delete_*", "action": "require_approval", "reason": "Destructive" },
{ "match": "pay_*", "action": "require_approval", "reason": "Moves money" }
],
"redact": ["password", "token", "ssn", "card_number"]
}
Upstreams are the MCP servers you were running directly before. Copy their command, args and env from your client config. SpotAgentIQ starts them as child processes.
Rules are checked from top to bottom and the first match wins. Policies covers matching in detail.
Connect your MCP client
Replace the entries for the servers you moved into upstreams with a single entry for SpotAgentIQ. The agent sees the same tools with the same names.
Claude Desktop and Cursor
Claude Desktop reads claude_desktop_config.json (Settings, Developer, Edit Config). Cursor reads ~/.cursor/mcp.json or .cursor/mcp.json in a project. Both use this shape:
{
"mcpServers": {
"spotagentiq": {
"command": "/usr/local/bin/spotagentiq",
"args": ["serve", "--config", "/path/to/spotagentiq.json"],
"env": { "SPOTAGENTIQ_TOKEN": "..." }
}
}
}
Claude Code
Add it to .mcp.json in the same shape, or from the command line:
claude mcp add spotagentiq -- spotagentiq serve --config /path/to/spotagentiq.json
Use absolute paths. MCP clients often start servers from a different working directory than your shell.
Approve calls in the inbox
Open http://localhost:8484, paste the token, and type your name. Held calls appear within two seconds, with the full arguments (after redaction) and the rule that caught them.
- Approve runs the call and returns the real result to the agent.
- Reject returns a readable refusal the agent can explain. Add a note and the agent sees it.
- Do nothing and the call times out after
approval_timeout, which counts as a rejection.
The token is a shared secret, not a login system. Keep the inbox on localhost, a VPN or behind a reverse proxy with TLS. Never give the agent the token or network access to the inbox.
Get held calls in Slack
Create an incoming webhook and add it to the config. Every held call is posted with a link straight to it in the inbox.
"slack_webhook": "${SLACK_WEBHOOK_URL}",
"public_url": "https://spotagentiq.internal.example.com"
Approving from the Slack message itself is part of SpotAgentIQ Cloud.