Gate every agent tool call.
mcpguard-sdk wraps any tool handler with a deterministic policy check before it runs. Allow, deny, or route to a human review queue — with a tamper-evident audit trail. Works with OpenAI, Anthropic, LangGraph, MCP, and your own loop.
# 1. install the SDK
npm install mcpguard-sdk
# 2. set your key (get one at mcp-guard.ai/dashboard/keys)
export MCPGUARD_API_KEY=mcg_live_…import { MCPGuard } from 'mcpguard-sdk'
const guard = new MCPGuard({ apiKey: process.env.MCPGUARD_API_KEY! })
// Drop-in gate. Throws on deny / review in enforce mode.
await guard.enforce({
action_id: 'billing.refund',
params: { invoice_id, amount_cents },
user_context: { user_id, plan },
})
await stripe.refunds.create({ charge, amount: amount_cents })packages/sdk/src/index.ts — real signature, not pseudocode.
Start here
Five guides cover the most common paths. Pick the one that matches your stack and you'll be in production in under an hour.
The two-mode contract, the AAL2 + reason gate to flip a tenant, and how to ramp without a Friday-night incident.
What requires_action gives you, what it doesn’t, and how withMCPGuardOpenAI fills the gap.
LangGraph’s interrupt is the easy part. The queue, the UI, the audit, the observe ramp are the hard part.
Wrap stripe-mcp, github-mcp, or your own server. Every tool call gets policy + review + audit. MIT-licensed.
An honest comparison. LangSmith wins on LangChain depth; MCP Guard wins on framework-agnosticism + counsel-reviewed packs.
The full TypeScript SDK surface: MCPGuard, enforce, evaluate, waitForReview, the typed errors. Python is identical.
What MCP Guard actually does
Every tool call your agent attempts is a potential incident waiting to happen: an unbounded refund, a DROP TABLE, a public-facing email, a wire transfer to an unverified account. The standard reaction is to read the model output before executing — but the standard reaction does not scale, and the model is wrong often enough that "just review the output" turns into "just don't ship the agent."
MCP Guard intercepts at the tool boundary. You wrap your handlers with guard.enforce(...); we evaluate the intended call against a YAML + CEL policy you author; we return one of three answers:
- allow — the tool call proceeds.
- review — a human is paged into a review queue; the call resumes on approve, is skipped on reject.
- deny — the call never executes; the model receives a structured error so it can re-plan.
Everything is audited. Every decision — even in observe mode, where we coerce deny → allow — is hash-chained into a tamper-evident log your auditor can export as a bundle.
Pick your adapter
You can call guard.enforce() directly anywhere in your code. For the popular framework loops, we ship adapters that handle the dispatch quirks for you:
withMCPGuardOpenAI + executeToolCalls — drop-in for Chat Completions / Assistants tool_calls.
withMCPGuardAnthropic + executeToolUseBlocks — mirrors the tool_use / tool_result block shape.
guardMCPTool + withMCPGuardMCP — wrap any handler registered with @modelcontextprotocol/sdk.