{"_id":"@curatedmcp/sentinel","_rev":"4-02a9fab475cb9113c5461fd41f9502ef","name":"@curatedmcp/sentinel","dist-tags":{"latest":"2.0.0"},"versions":{"0.1.0":{"name":"@curatedmcp/sentinel","version":"0.1.0","keywords":["mcp","security","firewall","policy","curatedmcp"],"author":{"name":"CuratedMCP"},"license":"MIT","_id":"@curatedmcp/sentinel@0.1.0","maintainers":[{"name":"curatedmcp","email":"curatedmcp@gmail.com"}],"bin":{"sentinel":"dist/cli.js"},"dist":{"shasum":"07d4e37c6c59e01c0f11b97e031fc1716b68eab0","tarball":"https://registry.npmjs.org/@curatedmcp/sentinel/-/sentinel-0.1.0.tgz","fileCount":23,"integrity":"sha512-W18X5m1YJTNUSnGjy0xEHrdMA0sZtIROnTc91rTRHXOhSh8fnL2TJK3LYOQG4jM7dMklxdEWRnQEPwdl9PvhIA==","signatures":[{"sig":"MEYCIQCBfjHH3WOsvhkLm72Wu28qfVcO6dK+xEqJhdXDjgvxHAIhANKirqgoPaiqMy+X7IshVNhJ/xH2h6hlbFzcf5XtTsbn","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76376},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":"./dist/index.js","./proxy":"./dist/proxy.js","./logger":"./dist/logger.js","./policy":"./dist/policy.js"},"gitHead":"f50eae2cbd7f78d8e76a2e8f21544b3e8afa14d4","scripts":{"dev":"tsc --watch","test":"node --test dist/**/*.spec.js","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"curatedmcp","email":"curatedmcp@gmail.com"},"_npmVersion":"10.8.2","description":"CuratedMCP's local-first action firewall for MCP servers","directories":{},"_nodeVersion":"20.20.2","dependencies":{"sql.js":"^1.14.1","express":"^4.18.0","commander":"^11.0.0","minimatch":"^9.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.0","@types/node":"^20.0.0","@types/express":"^4.17.0","@types/better-sqlite3":"^7.6.0"},"_npmOperationalInternal":{"tmp":"tmp/sentinel_0.1.0_1775532013594_0.07961165997471098","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@curatedmcp/sentinel","version":"0.2.0","keywords":["mcp","mcp-server","mcp-firewall","mcp-proxy","security","firewall","policy","model-context-protocol","claude","claude-desktop","cursor","windsurf","ai-agent","curatedmcp"],"author":{"name":"CuratedMCP"},"license":"MIT","_id":"@curatedmcp/sentinel@0.2.0","maintainers":[{"name":"curatedmcp","email":"curatedmcp@gmail.com"}],"homepage":"https://curatedmcp.com/sentinel","bugs":{"url":"https://github.com/curatedmcp/sentinel/issues"},"bin":{"sentinel":"dist/cli.js"},"dist":{"shasum":"a8918b0c2006e208f89a8456031c937db0eb998a","tarball":"https://registry.npmjs.org/@curatedmcp/sentinel/-/sentinel-0.2.0.tgz","fileCount":23,"integrity":"sha512-CySIcQEZ4JOTL2zt7DwwWMG15FyQkr3Rc9hXfxJ53AOvJoIbCMwNnYsg4/OaMul63vS3HWZmVdUes6bOQZfwbg==","signatures":[{"sig":"MEQCIDmLuxzV5javF8KCC6gJFnXyfolJAWug2Rqzj5aUp0rIAiBnRZrz1vmMpri5o9AE2LiuNDujM2QqNK28Ahl8o4oIcw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76686},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":"./dist/index.js","./proxy":"./dist/proxy.js","./logger":"./dist/logger.js","./policy":"./dist/policy.js"},"gitHead":"ec6f3f9b419f86cb0517f4f2b135578714bb7f0a","scripts":{"dev":"tsc --watch","test":"node --test dist/**/*.spec.js","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"curatedmcp","email":"curatedmcp@gmail.com"},"repository":{"url":"git+https://github.com/curatedmcp/sentinel.git","type":"git"},"_npmVersion":"10.8.2","description":"CuratedMCP's local-first action firewall for MCP servers","directories":{},"_nodeVersion":"20.20.2","dependencies":{"sql.js":"^1.14.1","express":"^4.18.0","commander":"^11.0.0","minimatch":"^9.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.0","@types/node":"^20.0.0","@types/express":"^4.17.0","@types/better-sqlite3":"^7.6.0"},"_npmOperationalInternal":{"tmp":"tmp/sentinel_0.2.0_1777236677690_0.45971998249391377","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@curatedmcp/sentinel","version":"1.0.0","keywords":["mcp","mcp-server","mcp-firewall","mcp-proxy","security","firewall","policy","model-context-protocol","claude","claude-desktop","cursor","windsurf","ai-agent","curatedmcp"],"author":{"name":"CuratedMCP"},"license":"MIT","_id":"@curatedmcp/sentinel@1.0.0","maintainers":[{"name":"curatedmcp","email":"curatedmcp@gmail.com"}],"homepage":"https://curatedmcp.com/sentinel","bugs":{"url":"https://github.com/curatedmcp/sentinel/issues"},"bin":{"sentinel":"dist/cli.js"},"dist":{"shasum":"68f411603bc9d719ad0dd379d10db4de299a3516","tarball":"https://registry.npmjs.org/@curatedmcp/sentinel/-/sentinel-1.0.0.tgz","fileCount":23,"integrity":"sha512-U1Gt03g42b3tFNodIzJpfSQ805+t6TBCWIV4EUzlJmyFc5lZWxGY4nc9zGgJKb9yvZ8W2Emi/2iOsGDyUiET6g==","signatures":[{"sig":"MEUCIG0as5c1+E0+ujVk2nOfFf7/WuO/ecKs/PpQa7Z0zj4OAiEAzdEIKPnXXzNDxa59vvQ/8XztSUhZDau9kwAS6d1Ae8U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76686},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":"./dist/index.js","./proxy":"./dist/proxy.js","./logger":"./dist/logger.js","./policy":"./dist/policy.js"},"gitHead":"29151f18e201c67e6db5d3dfd5d7c35ae2541022","scripts":{"dev":"tsc --watch","test":"node --test dist/**/*.spec.js","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"curatedmcp","email":"curatedmcp@gmail.com"},"repository":{"url":"git+https://github.com/curatedmcp/sentinel.git","type":"git"},"_npmVersion":"10.8.2","description":"CuratedMCP's local-first action firewall for MCP servers","directories":{},"_nodeVersion":"20.20.2","dependencies":{"sql.js":"^1.14.1","express":"^4.18.0","commander":"^11.0.0","minimatch":"^9.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.0","@types/node":"^20.0.0","@types/express":"^4.17.0","@types/better-sqlite3":"^7.6.0"},"_npmOperationalInternal":{"tmp":"tmp/sentinel_1.0.0_1777237018168_0.6849821717989788","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@curatedmcp/sentinel","version":"2.0.0","description":"CuratedMCP's local-first action firewall for MCP servers","type":"module","main":"./dist/index.js","bin":{"sentinel":"dist/cli.js"},"exports":{".":"./dist/index.js","./proxy":"./dist/proxy.js","./policy":"./dist/policy.js","./logger":"./dist/logger.js"},"scripts":{"build":"tsc","dev":"tsc --watch","test":"node --test dist/**/*.spec.js","prepublishOnly":"npm run build"},"keywords":["mcp","mcp-server","mcp-firewall","mcp-proxy","security","firewall","policy","model-context-protocol","claude","claude-desktop","cursor","windsurf","ai-agent","curatedmcp"],"author":{"name":"CuratedMCP"},"homepage":"https://curatedmcp.com/sentinel","repository":{"type":"git","url":"git+https://github.com/curatedmcp/sentinel.git"},"license":"MIT","dependencies":{"@modelcontextprotocol/sdk":"^1.0.0","commander":"^11.0.0","express":"^4.18.0","minimatch":"^9.0.0","sql.js":"^1.14.1"},"devDependencies":{"@types/better-sqlite3":"^7.6.0","@types/express":"^4.17.0","@types/node":"^20.0.0","typescript":"^5.3.0"},"engines":{"node":">=18.0.0"},"_id":"@curatedmcp/sentinel@2.0.0","gitHead":"3a506b2adbba94e01aeac73c328765c1d66f1ec6","types":"./dist/index.d.ts","bugs":{"url":"https://github.com/curatedmcp/sentinel/issues"},"_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-2ai3Ct3/hi+7XEdewfWaCXdcbzNJ9rs82zZojz6Jg7dAR5YENRMD6EWTbRnhrJ9a9Z7DO0aGTsOmYc9mFgchNA==","shasum":"36d6d749b23d13fa0e9a3b4115b5f8c66e779b4a","tarball":"https://registry.npmjs.org/@curatedmcp/sentinel/-/sentinel-2.0.0.tgz","fileCount":25,"unpackedSize":89994,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBYg2cn3H1P4DnLjrKl/Pl5cxx+H5j/SLpiSxUKh5d+KAiEAxtcBNQdVAw/xHM1ns+Zgg/f5un/u3qw6v3fQHln3wOU="}]},"_npmUser":{"name":"curatedmcp","email":"curatedmcp@gmail.com"},"directories":{},"maintainers":[{"name":"curatedmcp","email":"curatedmcp@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sentinel_2.0.0_1778718683074_0.10573723813633218"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-07T03:20:13.482Z","modified":"2026-05-14T00:31:23.340Z","0.1.0":"2026-04-07T03:20:13.732Z","0.2.0":"2026-04-26T20:51:17.834Z","1.0.0":"2026-04-26T20:56:58.308Z","2.0.0":"2026-05-14T00:31:23.228Z"},"bugs":{"url":"https://github.com/curatedmcp/sentinel/issues"},"author":{"name":"CuratedMCP"},"license":"MIT","homepage":"https://curatedmcp.com/sentinel","keywords":["mcp","mcp-server","mcp-firewall","mcp-proxy","security","firewall","policy","model-context-protocol","claude","claude-desktop","cursor","windsurf","ai-agent","curatedmcp"],"repository":{"type":"git","url":"git+https://github.com/curatedmcp/sentinel.git"},"description":"CuratedMCP's local-first action firewall for MCP servers","maintainers":[{"name":"curatedmcp","email":"curatedmcp@gmail.com"}],"readme":"# CuratedMCP Sentinel\n\n**Local-first action firewall for MCP servers.**\n\nSentinel intercepts MCP tool calls before execution, evaluates them against JSON policy rules, logs all actions locally in SQLite, and optionally requires approval before continuing.\n\n**No account or API key required.** Local mode works out of the box. Cloud identity and audit features are opt-in for teams using the [CuratedMCP Governance Control Plane](https://curatedmcp.com/registry).\n\n## Installation\n\n```bash\nnpm install -g @curatedmcp/sentinel\n```\n\n## Quick Start\n\n### 1. Run as a Proxy\n\n```bash\nsentinel proxy -- npx some-mcp-server\n```\n\nThis wraps your MCP server and starts the dashboard at http://localhost:4242.\n\n### 2. Visit the Dashboard\n\nOpen **http://localhost:4242** in your browser to:\n- View recent actions\n- Approve/reject pending tool calls\n- Manage policy rules\n- See blocked actions\n\n## CLI Commands\n\n### Policy Management\n\n```bash\n# List all active policies\nsentinel policy list\n\n# Add a blocking rule\nsentinel policy add --name \"Block Dangerous Tools\" --tool \"*exec*\" --action BLOCK --severity CRITICAL\n\n# Remove a rule\nsentinel policy remove rule-id-here\n```\n\n### Configuration\n\n```bash\n# Set log retention (in minutes)\nsentinel retention 1440  # 24 hours\n\n# Open dashboard standalone\nsentinel dashboard --port 4242\n```\n\n## Policy Rules\n\nPolicies match on three criteria:\n\n- **serverName** — Glob pattern (e.g., `*stripe*`, `exact-name`)\n- **toolName** — Glob pattern (e.g., `*delete*`, `run_*`)\n- **argumentContains** — String array (optional, block if any match in args)\n\n### Actions\n\n- **ALLOW** — Pass through immediately\n- **BLOCK** — Reject with error message\n- **REQUIRE_APPROVAL** — Pause and wait for dashboard approval\n\n### Severity Levels\n\n- **CRITICAL** — Security-sensitive action\n- **WARNING** — Elevated permission action\n- **INFO** — Informational only\n\n## Example Policies\n\n```bash\n# Block shell tool\nsentinel policy add --name \"No Shell\" --tool \"*shell*\" --action BLOCK\n\n# Require approval for file operations\nsentinel policy add --name \"File Ops Approval\" --tool \"*file*\" --action REQUIRE_APPROVAL --severity WARNING\n\n# Allow verified stripe tool\nsentinel policy add --name \"Stripe Allowed\" --server stripe-mcp --tool \"*\" --action ALLOW\n```\n\n## Local Storage\n\nAll data remains local by default:\n\n- **~/.sentinel/policy.json** — Policy rules\n- **~/.sentinel/actions.db** — SQLite action log\n- **~/.sentinel/config.json** — Configuration\n\n## Cloud Identity & Audit (Control Plane)\n\n> **No key? No problem.** Sentinel runs fully offline with no configuration at all. Cloud mode is optional — skip this section if you just want local policy enforcement.\n\nConnect Sentinel to your org's [CuratedMCP registry](https://curatedmcp.com/registry) to get:\n\n- **Per-agent identity** — each Sentinel instance registers a stable identity with your org\n- **JIT scoped tokens** — short-lived (1hr) credentials replace long-lived secrets in `.env` files\n- **Cloud audit log** — every tool call logged with `(agent, server, tool, argsHash, outcome)` — args stored as a hash only, no PII leaves your machine\n- **Cross-IDE enforcement** — same allowlist applies across Claude Code, Cursor, Windsurf, Copilot\n\n### Getting a Registry Key\n\nEmail **admin@curatedmcp.com** to request access to the Control Plane, or visit [curatedmcp.com/registry](https://curatedmcp.com/registry) to sign up.\n\n### Setup\n\n```bash\n# 1. Get your API key from the CuratedMCP registry dashboard\n#    → https://curatedmcp.com/registry/<your-slug>/settings\n#    (or email admin@curatedmcp.com to request access)\n\n# 2. Set env vars (or use CLI flags)\nexport CURATED_REGISTRY_KEY=\"cmcp_reg_...\"\nexport CURATED_REGISTRY_SLUG=\"acme-corp\"\n\n# 3. Run Sentinel — it auto-registers on first start\nsentinel proxy -- npx @modelcontextprotocol/server-github\n```\n\nOr pass flags directly:\n\n```bash\nsentinel proxy \\\n  --registry-key cmcp_reg_... \\\n  --registry-slug acme-corp \\\n  -- npx @modelcontextprotocol/server-github\n```\n\n### Environment Variables\n\n| Variable | Required | Default | Description |\n|---|---|---|---|\n| `CURATED_REGISTRY_KEY` | Yes* | — | API key from registry dashboard (`cmcp_reg_…`) |\n| `CURATED_REGISTRY_SLUG` | Yes* | — | Your org's slug, e.g. `acme-corp` |\n| `CURATED_REGISTRY_URL` | No | `https://curatedmcp.com` | Override for self-hosted control plane |\n| `CURATED_MACHINE_ID` | No | auto | Stable ID for this machine (used to derive agent fingerprint) |\n\n*Required only for cloud mode. Omit both to run in local-only mode.\n\n### How it works\n\n```\nClaude Code / Cursor / Windsurf\n    ↓\nSentinel Proxy\n    ├── Local PolicyEngine  (always runs, fast)\n    │       ↓ BLOCK → throws immediately\n    │       ↓ ALLOW → continue\n    └── CuratedMCP Broker   (when CURATED_REGISTRY_KEY is set)\n            ├── POST /identity      → register machine on startup\n            ├── POST /jit-token     → get 1hr scoped token per server\n            ├── POST /jit-token/verify → verify before each tool call\n            └── POST /tool-invocations → log outcome (fire-and-forget)\n    ↓\nMCP Server\n```\n\nLocal policy always takes precedence. If the broker is unreachable, Sentinel falls back to local-only mode automatically (fail-open).\n\n### What's Always Free\n\n- Local policy enforcement\n- SQLite action log\n- Approval workflows\n- Local dashboard\n\n### What Requires a Registry Plan\n\n- Cloud audit log (searchable, exportable)\n- Cross-IDE allowlist push\n- Per-agent identity & JIT tokens\n- SSO / RBAC for teams\n\nSee [curatedmcp.com/registry](https://curatedmcp.com/registry) for pricing.\n\n## Architecture\n\n```\nClient (Claude, Cursor, etc.)\n    ↓\nSentinel Proxy ← Local PolicyEngine\n    ↓               ↕ (optional)\nMCP Server      CuratedMCP Control Plane\n```\n\nEvery `CallToolRequest` is:\n1. Intercepted by Sentinel\n2. Evaluated against local policies (fast, offline)\n3. Verified against the cloud registry (when connected)\n4. Logged locally to SQLite + cloud audit log\n5. Either allowed, blocked, or held for approval\n6. Forwarded to downstream server (if allowed)\n\n## License\n\nMIT\n\n---\n\n**Made with ❤️ by CuratedMCP**  \n[Visit CuratedMCP](https://curatedmcp.com) | [Join Community](https://discord.gg/curatedmcp) | Questions: admin@curatedmcp.com\n","readmeFilename":"README.md"}