{
  "markdown": "> **⚠️ This repository has moved.** Active development continues at **[ScopeBlind/scopeblind-gateway](https://github.com/ScopeBlind/scopeblind-gateway)**.\n>\n> This personal fork may be behind the canonical repository. Please use the org repo for issues, pull requests, and the latest code.\n\n# protect-mcp\n\nSecurity gateway for MCP servers. Shadow-mode logs by default, per-tool policies, optional local Ed25519 receipts, and verification-friendly audit output.\n\n**Current CLI path:** wrap any stdio MCP server as a transparent proxy. In shadow mode it logs every `tools/call` request and allows everything through. Add a policy file to enforce per-tool rules. Run `protect-mcp init` to generate local signing keys and config so the gateway can also emit signed receipts.\n\n## Quick Start\n\n```bash\n# Wrap an existing OpenClaw / MCP config into a usable pack\nnpx @scopeblind/passport wrap --runtime openclaw --config ./openclaw.json --policy email-safe\n\n# Shadow mode — log every tool call, enforce nothing\nnpx protect-mcp -- node my-server.js\n\n# Generate keys + config template for local signing\nnpx protect-mcp init\n\n# Shadow mode with local signing enabled\nnpx protect-mcp --policy protect-mcp.json -- node my-server.js\n\n# Enforce mode\nnpx protect-mcp --policy protect-mcp.json --enforce -- node my-server.js\n\n# Export an offline-verifiable audit bundle\nnpx protect-mcp bundle --output audit.json\n```\n\n## What It Does\n\nprotect-mcp sits between your MCP client and server as a stdio proxy:\n\n```\nMCP Client ←stdin/stdout→ protect-mcp ←stdin/stdout→ your MCP server\n```\n\nIt intercepts `tools/call` JSON-RPC requests and:\n- **Shadow mode** (default): logs every tool call and allows everything through\n- **Enforce mode**: applies per-tool policy rules such as `block`, `rate_limit`, and `min_tier`\n- **Optional local signing**: when signing is configured, emits an Ed25519-signed receipt alongside the structured log\n\nAll other MCP messages (`initialize`, `tools/list`, notifications) pass through transparently.\n\n## What Ships Today\n\n- **Per-tool policies** — block destructive tools, rate-limit expensive ones, and attach minimum-tier requirements\n- **Structured decision logs** — every decision is emitted to `stderr` with `[PROTECT_MCP]`\n- **Optional local signed receipts** — generated when you run with a policy containing `signing.key_path`, persisted to `.protect-mcp-receipts.jsonl`, and exposed at `http://127.0.0.1:9876/receipts`\n- **Offline verification** — verify receipts or bundles with `npx @veritasacta/verify`\n- **No account required** — local keys, local policy, local process\n\n## Current Capability Boundaries\n\nThese are important before you roll this out or talk to users:\n\n- **Signing is not automatic on the bare `npx protect-mcp -- ...` path.** That path logs decisions in shadow mode. For local signing, run `npx protect-mcp init` and then start the gateway with the generated policy file.\n- **Tier-aware policy checks are live, but manifest admission is not wired into the default CLI/stdio path.** The CLI defaults sessions to `unknown` unless a host integration calls the admission API programmatically.\n- **Credential config currently validates env-backed credential references and records credential labels in logs/receipts.** Generic per-call injection into arbitrary stdio tools is adapter-specific and is not performed by the default proxy path.\n- **External PDP adapters and audit bundle helpers exist as exported utilities.** They are not yet fully wired into the default CLI path.\n\n## Policy File\n\n```json\n{\n  \"default_tier\": \"unknown\",\n  \"tools\": {\n    \"dangerous_tool\": { \"block\": true },\n    \"admin_tool\": { \"min_tier\": \"signed-known\", \"rate_limit\": \"5/hour\" },\n    \"read_tool\": { \"require\": \"any\", \"rate_limit\": \"100/hour\" },\n    \"*\": { \"rate_limit\": \"500/hour\" }\n  },\n  \"signing\": {\n    \"key_path\": \"./keys/gateway.json\",\n    \"issuer\": \"protect-mcp\",\n    \"enabled\": true\n  },\n  \"credentials\": {\n    \"internal_api\": {\n      \"inject\": \"env\",\n      \"name\": \"INTERNAL_API_KEY\",\n      \"value_env\": \"INTERNAL_API_KEY\"\n    }\n  }\n}\n```\n\n### Policy Rules\n\n| Field | Values | Description |\n|-------|--------|-------------|\n| `block` | `true` | Explicitly block this tool |\n| `require` | `\"any\"`, `\"none\"` | Basic access requirement |\n| `min_tier` | `\"unknown\"`, `\"signed-known\"`, `\"evidenced\"`, `\"privileged\"` | Minimum tier required if your host sets admission state |\n| `rate_limit` | `\"N/unit\"` | Rate limit (e.g. `\"5/hour\"`, `\"100/day\"`) |\n\nTool names match exactly, with `\"*\"` as a wildcard fallback.\n\n## MCP Client Configuration\n\n### Claude Desktop\n\nAdd to `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"my-protected-server\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\", \"protect-mcp\",\n        \"--policy\", \"/path/to/protect-mcp.json\",\n        \"--enforce\",\n        \"--\", \"node\", \"my-server.js\"\n      ]\n    }\n  }\n}\n```\n\n### Cursor / VS Code\n\nSame pattern — replace the server command with `protect-mcp` wrapping it.\n\n## CLI Options\n\n```\nprotect-mcp [options] -- <command> [args...]\nprotect-mcp init\n\nCommands:\n  init              Generate Ed25519 keypair + config template\n  status            Show decision stats and local passport identity\n  digest            Generate a local human-readable summary\n  receipts          Show recent persisted signed receipts\n  bundle            Export an offline-verifiable audit bundle\n\nOptions:\n  --policy <path>   Policy/config JSON file\n  --slug <slug>     Service identifier for logs/receipts\n  --enforce         Enable enforcement mode (default: shadow)\n  --verbose         Enable debug logging\n  --help            Show help\n```\n\n## Programmatic Hooks\n\nThe library also exposes the primitives that are not yet wired into the default CLI path:\n\n```typescript\nimport {\n  ProtectGateway,\n  loadPolicy,\n  evaluateTier,\n  meetsMinTier,\n  resolveCredential,\n  initSigning,\n  signDecision,\n  queryExternalPDP,\n  buildDecisionContext,\n  createAuditBundle,\n} from 'protect-mcp';\n```\n\nUse these if you want to add:\n- manifest admission before a session starts\n- an external PDP (OPA, Cerbos, or a generic HTTP webhook)\n- custom credential-brokered integrations\n- audit bundle export around your own receipt store\n\n## Decision Logs and Receipts\n\nEvery tool call emits structured JSON to `stderr`:\n\n```json\n[PROTECT_MCP] {\"v\":2,\"tool\":\"read_file\",\"decision\":\"allow\",\"reason_code\":\"observe_mode\",\"policy_digest\":\"none\",\"mode\":\"shadow\",\"timestamp\":1710000000}\n```\n\nWhen signing is configured, a signed receipt follows:\n\n```json\n[PROTECT_MCP_RECEIPT] {\"v\":2,\"type\":\"decision_receipt\",\"algorithm\":\"ed25519\",\"kid\":\"...\",\"issuer\":\"protect-mcp\",\"issued_at\":\"2026-03-22T00:00:00Z\",\"payload\":{\"tool\":\"read_file\",\"decision\":\"allow\",\"policy_digest\":\"...\",\"mode\":\"shadow\",\"request_id\":\"...\"},\"signature\":\"...\"}\n```\n\nVerify with the CLI: `npx @veritasacta/verify receipt.json`\nVerify in browser: [scopeblind.com/verify](https://scopeblind.com/verify)\n\n## Audit Bundles\n\nThe package exports a helper for self-contained audit bundles:\n\n```json\n{\n  \"format\": \"scopeblind:audit-bundle\",\n  \"version\": 1,\n  \"tenant\": \"my-service\",\n  \"receipts\": [\"...\"],\n  \"verification\": {\n    \"algorithm\": \"ed25519\",\n    \"signing_keys\": [\"...\"]\n  }\n}\n```\n\nUse `createAuditBundle()` around your own collected signed receipts.\n\n## Philosophy\n\n- **Shadow first.** See what agents are doing before you enforce anything.\n- **Receipts beat dashboard-only logs.** Signed artifacts should be independently verifiable.\n- **Keep the claims tight.** The default CLI path does not yet do everything the long-term architecture will support.\n- **Layer on top of existing auth.** Don't rip out your stack just to add control and evidence.\n\n## Incident-Anchored Policy Packs\n\nShip with protect-mcp — each prevents a real attack:\n\n| Policy | Incident | OWASP Categories |\n|--------|----------|-----------------|\n| `clinejection.json` | CVE-2025-6514: MCP OAuth proxy hijack (437K environments) | A01, A03 |\n| `terraform-destroy.json` | Autonomous Terraform agent destroys production | A05, A06 |\n| `github-mcp-hijack.json` | Prompt injection via crafted GitHub issue | A01, A02, A03 |\n| `data-exfiltration.json` | Agent data theft via outbound tool abuse | A02, A04 |\n| `financial-safe.json` | Unauthorized financial transaction | A05, A06 |\n\n```bash\nnpx protect-mcp --policy node_modules/protect-mcp/policies/clinejection.json -- node server.js\n```\n\nFull OWASP Agentic Top 10 mapping: [scopeblind.com/docs/owasp](https://scopeblind.com/docs/owasp)\n\n## BYOPE: External Policy Engines\n\nSupports OPA, Cerbos, Cedar (AWS AgentCore), and generic HTTP endpoints:\n\n```json\n{\n  \"policy_engine\": \"hybrid\",\n  \"external\": {\n    \"endpoint\": \"http://localhost:8181/v1/data/mcp/allow\",\n    \"format\": \"cedar\",\n    \"timeout_ms\": 200,\n    \"fallback\": \"deny\"\n  }\n}\n```\n\n## Standards & IP\n\n- **IETF Internet-Draft**: [draft-farley-acta-signed-receipts-00](https://datatracker.ietf.org/doc/draft-farley-acta-signed-receipts/) — Signed Decision Receipts for Machine-to-Machine Access Control\n- **Patent Status**: 4 Australian provisional patents pending (2025-2026) covering decision receipts with configurable disclosure, tool-calling gateway, agent manifests, and portable identity\n- **Verification**: MIT-licensed — `npx @veritasacta/verify --self-test`\n\n## License\n\nMIT — free to use, modify, distribute, and build upon without restriction.\n\n[scopeblind.com](https://scopeblind.com) · [npm](https://www.npmjs.com/package/protect-mcp) · [GitHub](https://github.com/scopeblind/ScopeBlindD2) · [IETF Draft](https://datatracker.ietf.org/doc/draft-farley-acta-signed-receipts/)\n",
  "bytes": 9593,
  "sha": "ab1e177071010b2a4c0f0c966d4161c27280e828b5612a65087420ea69f48f2b",
  "repo_slug": "tomjwxf/scopeblind-gateway",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_tomjwxf_scopeblind_mcp_a4c73a2a/readme"
}