SentinelMCP

SentinelMCP

Stateless enterprise policy firewall & token-cost proxy for MCP. It enforces identity, policy, and budget on every tool call.

Category
Visit Server

README

SentinelMCP

Stateless enterprise policy firewall & token-cost proxy for MCP.

Drop it in front of any Model Context Protocol server. Every tool call gets checked for identity, policy, and budget before it reaches your infrastructure — no database, no sticky sessions, nothing new to operate at 3am.

CI License: MIT Node


The 2-minute problem

MCP made it trivial to wire an LLM agent up to real tools — databases, payment APIs, internal services. It did not ship a policy layer. If you've run an MCP server in production, you've probably already hit one of these:

Runaway loops. An agent gets stuck retrying a failing call, or a bad prompt sends it into a call-and-recall spiral. Nothing in the MCP spec stops it. You find out from the bill, not an alert.

Token budgets that don't exist until they explode. Nothing in a typical agent loop stops it from calling the same expensive tool hundreds of times in an hour. The common failure mode: a $40/day budget quietly becomes a $40k/month bill, and the first signal anyone gets is the invoice.

DNS-rebinding and confused-deputy risk. The Streamable HTTP transport spec requires Origin validation for exactly this reason — a malicious page can rebind DNS to reach a local MCP server your browser would otherwise block. Most self-hosted servers don't implement it. Stack a compromised or injected tool result on top, and "just add an MCP server" is a bigger attack surface than most teams have budgeted time to secure.

SentinelMCP won't stop a model from being tricked — no proxy can. What it does is make sure a tricked or runaway agent can't reach a tool it isn't allowed to call, blow through a budget nobody approved, or keep running once the numbers look wrong — without a human getting a say.


Key features

Zero-trust security

  • Origin validation on every request — the DNS-rebinding mitigation the Streamable HTTP spec requires and most self-hosted servers skip. Loopback-only by default; explicit allowlist for anything else, override not extend.
  • ID-JAG identity enforcement — real JWKS-backed JWT verification, asymmetric algorithms only (no HMAC-downgrade path), including the resource claim binding that closes the confused-deputy hole: a token issued for one MCP server can't be replayed against another.

Token economics

  • Structural token estimation — walks the actual JSON-RPC payload instead of length / 4, pricing natural-language content and JSON structure at different, calibrated rates. Input measured exactly; output projected from a per-tool rolling average and trued up against the real response after every call.
  • 7-day sliding-window budgets per team, enforced against a fixed-memory circular buffer (168 hourly buckets) — bounded, no per-request log to prune, no unbounded growth under load.
  • Spike detection independent of the hard cap — a sudden burst against a team's own recent baseline gets caught even while the cumulative total is nowhere near the limit. Catches the exponential-growth pattern before the raw budget does.

Human-in-the-loop, not hard failure

  • A budget breach doesn't 500 the call. It returns InputRequiredResult — a normal JSON-RPC success — carrying the projected overrun, the run-rate spike, and an HMAC-signed, request-bound resumeToken.
  • POST /mcp/resume with { resumeToken, decision: "APPROVE" | "DENY", originalRequest } lets a human clear it. The token is bound to the exact call via a canonical-JSON hash of the request — approve this wire transfer, not whatever an agent decides to substitute next.
  • Delivery is transport-aware: the pause notice reaches the client over whichever channel the original call used.

Protocol support

  • Streamable HTTP — the current MCP standard (spec 2025-03-26+), and the primary path.
  • Legacy HTTP+SSE (spec 2024-11-05) for backward compatibility with clients that haven't migrated. Not the default; don't build new integrations against it.

Quickstart

git clone https://github.com/your-org/sentinelmcp.git
cd sentinelmcp
npm install
cp .env.example .env

Six required values in .env — everything else ships with a sane default:

Variable What it is
MCP_UPSTREAM_URL The real MCP server SentinelMCP forwards allowed calls to
JWKS_URI Your IdP's JWKS endpoint (Okta, Auth0, Azure AD, …)
ID_JAG_ISSUER Expected iss claim on incoming ID-JAG tokens
ID_JAG_AUDIENCE Expected aud claim
ID_JAG_RESOURCE This gateway's resource identifier — the anti-confused-deputy binding
HMAC_SECRET 32+ random chars signing resume tokens — openssl rand -base64 32. Must be identical across every replica, or resume verification breaks depending on which one handles a given call.
npm run build && npm start   # production
# or, for local iteration:
npm run dev                  # tsx watch

Confirm it's alive:

curl http://localhost:8080/healthz

How it fits

flowchart LR
    Client(["MCP Client<br/>Claude Desktop · Cursor · custom agent"])

    subgraph Sentinel["SentinelMCP — stateless gateway"]
        direction TB
        Origin["Origin Guard<br/>DNS-rebinding check"]
        Policy["Policy Gate<br/>tool denylist"]
        Identity["Identity Gate<br/>ID-JAG · JWKS verify"]
        Budget["Budget Gate<br/>sliding window + spike detect"]
        Origin --> Policy --> Identity --> Budget
    end

    Upstream["Upstream MCP Server(s)"]
    Resume["POST /mcp/resume<br/>HMAC-signed resumeToken"]

    Client -->|"POST /mcp"| Origin
    Budget -->|"allowed → forward"| Upstream
    Upstream -->|"result"| Client
    Budget -.->|"denied → paused<br/>InputRequiredResult"| Client
    Client -.->|"human decides,<br/>out of band"| Resume
    Resume -->|"APPROVE<br/>budget bypassed only —<br/>identity + policy still enforced"| Upstream

SentinelMCP sits in front of one or more upstream MCP servers as a reverse proxy. Every gate runs on every request; a denial short-circuits before the call ever reaches your tools. Only the budget gate can be bypassed, and only by an explicit, signed, single-call human approval — identity and policy are re-checked even on resume.

Two of the five subsystems keep state in memory (SSE session tracking and the budget ledger) — the request/response path itself is stateless and horizontally scalable behind a plain load balancer. See docs/ENGINEERING.md for exactly which pieces, and what that means for running more than one replica.


Quality

  • 63 tests, 19 suitesnpm test. Unit coverage for the token estimator, the sliding-window budget algorithm (spike detection included, verified with an injectable clock rather than waiting real days), and the HMAC token service (round-trip, tampering, forged secrets, canonical-hash binding). Integration coverage runs the full request pipeline through fastify.inject() against a real, ephemeral-port mock identity provider and mock upstream — no stubbed JWT verification, no mocked crypto.
  • Strict TypeScriptstrict, noUncheckedIndexedAccess, noImplicitOverride. No any in the source tree.
  • Zero test-framework dependencies — built on Node's own node:test.
  • CI runs typecheck, the full suite, and a production build on every push, against Node 20 and 22.

The full engineering log — what's verified, every bug found during development and how it was fixed, and every known limitation stated plainly rather than glossed over — lives in docs/ENGINEERING.md.

License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured