ShakerScan MCP

Status: shipped and contract-tested as of 2026-08-29.

ShakerScan includes a fail-closed MCP stdio adapter over the REST Command Arsenal and canonical Hunt V2. Arsenal tools remain read-only. Hunt tools wrap /hunts directly and inherit its exact target binding, approval, budget, evidence, and proof enforcement; arbitrary shell is never exposed.

Start it from the source/runtime directory:

./scanner.sh mcp

The same adapter runs without the engine from the shakerscan client (pipx install shakerscan, uv tool install shakerscan, or the Homebrew tap; see client.md):

shakerscan mcp --url https://scanner.example.com --token-file ./token

The scanner API must already be available at http://127.0.0.1:8080. Override the origin with SHAKERSCAN_API_URL. Non-loopback origins are rejected unless SHAKERSCAN_MCP_ALLOW_REMOTE_API=true is explicitly set.

Behind an authenticating gateway (for example a self-hosted Enterprise deployment that fronts the API with service tokens), set SHAKERSCAN_API_TOKEN as well: the adapter sends it as Authorization: Bearer on every call. A token is only ever sent over https://; the adapter refuses to start with a token and a plain-http origin, and it never prints the token. The product CLI (./scanner.sh hunt ..., scripts/v2_cli.py) honours the same variable with the same rule.

SHAKERSCAN_API_URL=https://scanner.example.com \
SHAKERSCAN_MCP_ALLOW_REMOTE_API=true \
SHAKERSCAN_API_TOKEN=<service token> ./scanner.sh mcp

Example client configuration:

{
  "mcpServers": {
    "shakerscan": {
      "command": "/absolute/path/to/shakerscan/scanner.sh",
      "args": ["mcp"]
    }
  }
}

The adapter exposes two deliberately different trust levels:

Read-only Arsenal inspection:

  • shakerscan_targets
  • shakerscan_asm_gaps
  • shakerscan_findings
  • shakerscan_evidence_manifest
  • shakerscan_timeline
  • shakerscan_plans
  • shakerscan_tool_status

Target-bound Hunt V2 (including state-changing and target-facing operations):

  • shakerscan_hunt_skills for catalog metadata and shakerscan_hunt_skill for global detail
  • shakerscan_hunt_skill_suggestions, shakerscan_hunt_skill_read, shakerscan_hunt_skill_bind, shakerscan_hunt_skill_unbind, and shakerscan_hunt_skill_usage for progressive, audited methodology use
  • shakerscan_hunt_start, shakerscan_hunt_get, and shakerscan_hunt_query
  • shakerscan_hunt_capability for capabilities returned by that Hunt's manifest
  • shakerscan_hunt_candidate, shakerscan_hunt_candidate_update, and shakerscan_hunt_candidate_delete
  • shakerscan_hunt_verify, shakerscan_hunt_finish, and shakerscan_hunt_cancel

Arsenal tools read GET /arsenal/commands, require the mapped command to remain read_only risk, and dispatch through the audited Arsenal endpoint. Hunt discovery reads GET /hunts/contract and generates the start schema from the live authority contract. The MCP boundary uses only the canonical goal name and sends the complete V2 body: schema version, target kind, policy, budgets, credential references, capability allowlist, request-collection references, and optional skill_ids. A run normally starts without one. Adaptive suggestions return at most three compact records and no bodies; the planner loads exactly one relevant method through the Hunt-specific read tool before binding it. MCP never auto-binds a methodology or changes authority.

Before capability execution, the adapter reloads GET /hunts/{id}, requires an active or awaiting-planner run, finds the capability in that Hunt's returned manifest, and validates input against its published schema. The client may provide an idempotency_key; if omitted, the adapter generates one and returns it as mcp_idempotency_key so a retry can reuse the exact action identity. The runtime still revalidates target binding, approval, budgets, evidence, and proof contracts. Catalog/contract drift, redirects, oversized responses, unavailable APIs, and unexpected dispatch results fail closed.

Tool annotations reflect these boundaries: Arsenal inspection and Hunt get/query are read-only; capability and verification operations are conservatively marked destructive and open-world; start, candidate create/update/delete, finish, and cancel are state-changing. Candidate updates cannot change identity or proof-owned fields; deletion expires the candidate while retaining its immutable audit record. Raw secrets, target-address overrides, planner argv, and arbitrary shell commands are not representable. Input schemas enforce UUIDs, enums, required/nested fields, patterns, uniqueness, and numeric bounds before dispatch. The transport also caps request and response sizes and rejects redirects.

This page is rendered from docs/mcp.md in the open-source repository at v2.5.4. When documentation and implementation disagree, the code, database schema, and tests at that tag are authoritative.