TypeScript + PythonCEL · YAML policyMIT-licensed SDK

Gate every agent
tool call in 5 minutes.

mcpguard-sdk wraps any tool handler with a deterministic policy check before it runs. CEL-based rules. Observe-first ramp. Framework-agnostic — OpenAI, Anthropic, LangChain, MCP, your own loop.

Read the docs →
3-lineinstallwrap your existing tool handlers
0vendor lock-inCEL subset · YAML policy · plain HTTP
10kfree evals / monthno card, no quota games
agent.tsts
import { MCPGuard } from 'mcpguard-sdk'

const guard = new MCPGuard({ apiKey: process.env.MCPGUARD_API_KEY! })

// Drop-in gate. Throws MCPGuardDeniedError on policy deny.
await guard.enforce({
  action_id: 'billing.refund',
  params: { invoice_id, amount_cents },
  user_context: { user_id, plan },
})

// → allow: continue.   → review: human in the loop.
// → deny:  thrown, the tool call is skipped.

await stripe.refunds.create({ charge, amount: amount_cents })

packages/sdk/src/index.ts — real signature, not pseudocode.

The three-line install

Wrap your tool handlers. Keep your loop.

One MCPGuard instance, one adapter import, one handler-map transform. Your dispatch code doesn't change — every tool call now flows through policy before it runs.

OpenAImcpguard-sdk/openai
openai-loop.tsts
import { withMCPGuardOpenAI } from 'mcpguard-sdk/openai'

const handlers = withMCPGuardOpenAI(guard, {
  'billing.refund': refundHandler,
  'db.query':      queryHandler,
})

// existing dispatch — unchanged
await handlers[call.function.name](args)
Anthropicmcpguard-sdk/anthropic
claude-loop.tsts
import { executeToolUseBlocks } from 'mcpguard-sdk/anthropic'

const results = await executeToolUseBlocks(
  guard,
  message.content.filter(b => b.type === 'tool_use'),
  { refund: refundHandler, query: queryHandler },
)

// feed `results` back as the next user turn
Anything elsemcpguard-sdk
custom-loop.tsts
import { MCPGuard, MCPGuardDeniedError } from 'mcpguard-sdk'

try {
  await guard.enforce({ action_id, params })
  await runMyTool(params)
} catch (e) {
  if (e instanceof MCPGuardDeniedError)
    return { skipped: true, rule: e.matched_rule }
  throw e
}

Works with LangChain, LangGraph, OpenAI Assistants, Anthropic tool use, MCP servers, Vercel AI SDK — anything that hands you a tool name and a params object. The SDK has no framework dependency; the adapters are structural duck-types.

Local MCP tools

Try it in Cursor.
No signup. No network.

The free-tier MCP server ships four tools that run fully local — no API key, no telemetry, no round-trip. Drop the snippet into your MCP client and your editor can author, validate, and test policy without leaving the buffer.

~/.config/claude/claude_desktop_config.jsonjson
{
  "mcpServers": {
    "mcp-guard": {
      "command": "npx",
      "args": ["-y", "mcpguard-server"]
    }
  }
}

Same shape works in Cursor, Claude Desktop, Continue, and any other MCP host. No env: block — the free tier is keyless on purpose.

  • Free · local
    mcpguard.policy_validate

    Parse policy.yaml, walk the AST, lint against the DSL spec — before you ever ship a rule.

  • Free · local
    mcpguard.cel_test

    Evaluate a CEL predicate against a sample event payload. Same engine the gate uses in prod.

  • Free · local
    mcpguard.risk_pack_browse

    Browse Healthcare / Fintech / Ops/IT risk packs with per-action rationale teasers.

  • Free · local
    mcpguard.schema_docs

    Action / policy / review schema documentation, bundled. No round-trip to a docs site.

cursor — agent chatprompt
> validate ./policy.yaml and tell me which rules would block billing.refund > $500

mcp-guard → calling mcpguard.policy_validate
    ✓ policy parses (3 rules)
 → calling mcpguard.cel_test
    matched_rule: refund.large_amount → review
Observe → enforce

Roll out without breaking prod.

The SDK ships with two policy modes and a clean transition between them. Same code, same call site — the only thing that changes is whether enforce() throws.

  1. Day 1mode: observe

    Drop in. Nothing breaks.

    Install the SDK in observe mode. Every tool call is logged with the decision the policy would have made — allow, deny, review — but the call still runs.

  2. Week 1mode: review

    Watch what would have blocked.

    The dashboard shows "if enforcing now, X% of refund.create calls would route to review." You tune rules against real traffic, not synthetic test cases.

  3. When you’re readymode: enforce

    Flip per-action.

    Move `billing.refund` to enforce. Leave `db.query` in observe another week. Mode is per-action and per-environment — no big-bang rollout.

// observe mode: deny → allow + log. enforce mode: deny → throws MCPGuardDeniedError.

Pricing for devs

Free until a non-engineer logs in.

The SDK is free up to 10,000 evaluations / month on self-hosted or via the hosted free tier. Team plan is when you bring on the first reviewer — the dashboard, the review queue, the Slack approval bot.

Free
$0forever

For the dev evaluating, prototyping, or shipping a side project.

  • Full SDK (TS + Python)
  • 10k evaluations / month
  • Local MCP tools (no key)
  • Risk pack indexes
  • Community Discord
Start free
When you ship to prod
Team
$799/ month

When the first reviewer — a PM, a comms lead, a support manager — needs to see the queue.

  • Everything in Free
  • Managed REST /evaluate
  • Hosted review queue UI
  • Observation rollup analytics
  • Slack approval bot
Try Team

Business and Enterprise tiers add SSO, dedicated review queues, BAA, on-prem, and managed policy authoring. See the full pricing grid →