MCP · Guide · New

MCP middleware: gating any MCP server with policy

Every guardrail product on the market lives inside your agent code: import an SDK, wrap your tool handlers, write rules. That works — but it only works for tools you wrote. MCP changed the question. Most production agents now load tools from third-party MCP servers (Stripe, GitHub, Slack, a Linear server your colleague vibe-coded). You did not write those handlers. You cannot wrap them. mcpguard-guard is the meta-MCP-server that sits in front of them.

The claim

mcpguard-guard is an MCP server whose tools are someone else's tools. You point your agent at the guard; the guard advertises the upstream server's tool list verbatim; every tool invocation from the agent is intercepted, evaluated against your MCP Guard policy, and only then forwarded to the upstream. Allow → forward. Deny → return a structured rejection. Review → create a review row, return a structured pending error, the agent surfaces it through its normal channel.

Your agent code does not change. Your upstream MCP server does not change. The middleware is the only new moving part — and it is configured with a single YAML file.

Architecture

Agentclaude / openai / your loopMCP clientmcpguard-guardMCP server façadepolicy + review + auditUpstream MCPstripe-mcp · github-mcpyour real toolstools/callif allowtools/resultresult | deny | reviewaudit chain · review queue · dashboard

The agent thinks it's talking to stripe-mcp. The tool list it sees is identical. The arguments it sends are identical. The difference is that every call now also writes a hash-chained audit row and runs your policy before the upstream sees it.

Wrapping stripe-mcp in 30 seconds

Drop a config file. The guard reads the upstream server's tool list at startup and proxies it forward.

mcp-guard.yamlyaml
# 1. point the guard at your MCP Guard tenant key
api_key_env: MCPGUARD_API_KEY

# 2. declare the upstream MCP server to proxy.
upstream:
  name: stripe-mcp
  # stdio (spawned subprocess) or http transport — both supported.
  transport: stdio
  command: ['npx', '-y', '@stripe/mcp', '--api-key', '$STRIPE_API_KEY']

# 3. map upstream tool names to MCP Guard action_ids.
#    omit a tool to pass it through ungated.
actions:
  create_refund:    billing.refund
  create_charge:    billing.charge
  delete_customer:  billing.delete_customer

Run the guard as your MCP server entry point:

claude_desktop_config.jsonjson
{
  "mcpServers": {
    "stripe-guarded": {
      "command": "npx",
      "args": ["-y", "mcpguard-guard", "--config", "./mcp-guard.yaml"],
      "env": { "MCPGUARD_API_KEY": "mcg_live_…" }
    }
  }
}
That's the whole integration
Your agent now sees the same tools as before. Every call routes through MCP Guard. The audit chain at /dashboard/audit fills up immediately.

Config reference

The full config schema (every key optional unless marked required):

  • api_key_env (required) — env var holding your MCP Guard live key.
  • upstream.name (required) — display name; shown in the audit log.
  • upstream.transportstdio or http. Defaults to stdio.
  • upstream.command — argv array for stdio transport.
  • upstream.url — URL for http transport.
  • actions — map of upstream tool name → MCP Guard action_id. Unmapped tools pass through ungated (this is opt-in by design — gating an unknown tool blind is worse than ungating one explicitly).
  • mode_hintobserve or enforce. The server is still the source of truth; this is forwarded for tenants that A/B by client.
  • review.short_circuit — when true, the middleware long-polls waitForReview before returning to the agent (good for human-in-the-loop UX). When false, it returns a policy_review_required error immediately and the agent retries with the resolved review.

Why this is novel

Every other guardrail product on the market — LangSmith, Guardrails AI, NeMo Guardrails, Lakera, Robust Intelligence, Protect AI — is shaped as a library you import into your agent code. That works fine for the framework they were designed around. It does not work when:

  • You did not write the tools. They live in stripe-mcp, github-mcp, an internal Linear server.
  • The MCP client is Claude Desktop, Cursor, or another IDE that you do not have source access to.
  • You want a single policy across an MCP zoo — Stripe, GitHub, a custom warehouse server — without modifying any of them.

MCP middleware is a deployment shape, not just a code shape. The closest analogue is an HTTP proxy with a WAF — and just like a WAF, the value compounds because one config covers any MCP-speaking client.

License & distribution

mcpguard-guard is MIT-licensed. Use it standalone, fork it, ship it inside another product, vendor the code — the only thing the wrapper does that isn't free is talk to api.mcp-guard.ai for the policy evaluation and audit row. The hosted API is the commercial surface; the wrapper itself is the OSS distribution play.

Self-hosted
The wrapper accepts base_url in its config, so self-hosted MCP Guard customers point it at their own backend and never touch the public API.
Ready to drop this in? Free up to 10k evaluations / month — no card.