MCP Shield
Tool calls and tool results, checked at the edge.
MCP Shield reads the JSON-RPC between AI clients and your own MCP server. It applies method and tool allowlists, inspects tool arguments and tool results for prompt injection and leaked credentials, and limits requests per token. Opt-in per endpoint, and it starts in log mode.
Your MCP server behind the edge, one endpoint at a time
Add an endpoint with kind: mcp to a site. From then on, every JSON-RPC message to it is checked against your method and tool lists and the injection and credential detectors.
How it works
Eight steps between the client and your server
An MCP endpoint is an entry of the site’s Bots and AI agents endpoints with kind: mcp. The site’s Bots and AI agents policy applies first, as to any request; then, for the first endpoint whose path prefix and HTTP methods match:
- 1
Endpoint
The request matches the path prefix of your MCP server, for example
/mcp, and one of its HTTP methods:POST,GETorDELETE. - 2
Rate
With a per-token limit, the request counts per minute first against a per-IP bucket (a /64 in IPv6) of 10 × the limit, then against the normalised
Authorizationheader, or the client IP when there is none. - 3
Size
The
POSTbody is read up tomax_request_kb, 256 KiB by default. - 4
JSON-RPC
The body must be one JSON-RPC 2.0 message or a non-empty batch of them.
- 5
Policy
Each client message with a
methodis checked against the allowed methods, and eachtools/callagainst the denied and allowed tools. - 6
Request inspection
Tool arguments,
resources/readparameters and prompt arguments go through the detectors. - 7
Your server
The request goes on unchanged, except that
Accept-Encodingis removed so the response arrives readable. - 8
Response inspection
JSON responses are checked whole; SSE streams event by event, each event forwarded as soon as it has been checked.
Never changed: Mcp-Session-Id, MCP-Protocol-Version, Last-Event-ID, SSE event ids, DELETE requests, the framing of GET streams and 202 answers. MCP Shield does not authenticate anyone: your server still checks its tokens.
Policy
Method and tool allowlists
Allow only what your server implements and what this endpoint should offer. An endpoint needs only its type and path prefix; every other setting has a default.
- Allowed methods
1 to 64 JSON-RPC methods, exact or a prefix such as
notifications/*. The default is the twelve standard MCP methods, frominitializeandtools/calltologging/setLevel. - Allowed and denied tools
Up to 200 names each, matched exactly against the
nameoftools/call. An empty allowed list means any tool that is not denied. - Size and rate
A request body cap of 1 to 1024 KiB and an optional limit of requests per minute per token. Each edge node counts on its own, so with N nodes a token can reach N times the limit.
The same change works from the dashboard (AI Crawl Control → MCP Shield), the API and the ai_agents_settings tool of the OpenWAF MCP server. The endpoint list is replaced as a whole, and every change is a new, versioned configuration with its reason. Every field is in the settings reference.
Inspection
What is inspected, and what is not
Deterministic patterns, not a model. They stop known shapes of prompt injection and credential leaks; they do not prove a message is safe.
Inspected
inspect_requestsClient to server: the arguments oftools/callandprompts/get, and the parameters ofresources/read.inspect_responsesServer to client: every string inresultanderrorof the responses to requests with an id, tool descriptions oftools/listincluded, and theparamsof the server’s own requests (sampling/createMessage,elicitation/create).
Detector families
pi.*Instruction overrides, system-prompt extraction, jailbreaks, forged system messages, tool calls and turns, approval bypass, orders in HTML comments or encoded text.agent.*Destructive commands such asrm -rf /orDROP TABLE.exfil.*Remote scripts piped to a shell, secret harvesting, exfiltration through a rendered image or link.hidden.*Zero-width characters, Unicode tag characters, CSS-hidden text.dlp.*AWS, GitHub, Stripe, Slack, SendGrid, Mailgun, OpenAI, Anthropic and OpenWAF keys, private keys and database URLs, stored redacted to their first four characters.mcp.*Policy hits: method not allowed, tool denied or not allowed, rate, parse error, invalid request, too large.
The same 27 injection detectors as OpenWAF’s AI-endpoint protection, in English and Spanish. Each runs only when one of its keywords appears in the text.
Not inspected
- Anything a pattern does not describe: paraphrases, other languages and encodings the detectors do not cover. There is no semantic classifier and no language model.
- The content of notifications, in either direction. Client notifications still go through the allowed methods.
- The client’s answers to
sampling/createMessageandelicitation/create. The server’s requests themselves are inspected but only logged, never replaced. - JSON responses and SSE events over 2 MiB, and responses that still arrive compressed. They pass unchanged and are counted as uninspected.
- Request bodies over
max_request_kbin log mode (in enforce they get413). - The parameters of other methods, such as
completion/complete,logging/setLeveland the list methods. - Headers and query strings. Resource URIs and prompt names have no allow or deny list.
- The token itself: MCP Shield never validates it, your server does.
Rollout
Log first, then enforce
The site’s Bots and AI agents mode decides whether the edge acts; each inspection setting, off, log or block, decides what to do with a detection. In log mode nothing is blocked, whatever the inspection settings say.
- 1
Start in log
Mode log and both inspections in log, the defaults. Send real traffic for a few days and read the report, the events and the uninspected count.
- 2
Fit the policy
Remove the methods your server does not implement, deny the tools this endpoint should not offer, and set a per-token limit above your legitimate peak.
- 3
Check the bot policy
In enforce it applies to the endpoint before MCP Shield. MCP clients built on Node.js or Python SDKs usually count as
unverified_automation. - 4
Enforce the policy
Switch the mode to enforce: methods, tools, size and rate are applied. Inspection in
logkeeps only recording. - 5
Block, if you choose
Set inspection to
blockonly after reviewing its events: a tool result that legitimately quotes attack text would be replaced by an error.
The OpenWAF MCP server, mcp.openwaf.dev, is the first endpoint behind MCP Shield. It went through these same steps: log first, then enforce for the method policy, with tool-result inspection kept in log and its events treated as alerts.
JSON-RPC errors
Blocks the client can show, without dropping the session
MCP clients treat an HTTP error as a transport failure. So policy and inspection blocks answer HTTP 200 with a JSON-RPC error carrying the id of the blocked request: the assistant shows it for that one call and the session goes on.
Every answer in enforce
200 · -32601Method not in the allowed methods200 · -32602Tool denied, or missing from a non-empty allowed list200 · -32001Injection or credential in the request, with request inspection onblock-32001Injection or credential in the response, with response inspection onblock: that message, or that SSE event, is replaced with the same id and your server’s status429 · -32000Over the per-token limit, withRetry-After413 · -32600Body overmax_request_kb400 · -32700Body is not JSON (idnull)400 · -32600JSON but not JSON-RPC 2.0, or an empty batch (idnull)202A blocked notification, with an empty body
What the client receives
blocked by OpenWAF MCP Shield: followed by the detection ids. error.data.openwaf repeats the event kind and the ids, so a client can tell a shield block from an error of your server.
{"jsonrpc": "2.0", "id": 7,
"error": {"code": -32602,
"message": "blocked by OpenWAF MCP Shield: mcp.tool_denied",
"data": {"openwaf": {"kind": "mcp_blocked_tool",
"detections": ["mcp.tool_denied"]}}}}Batches: if any message is blocked, the edge answers the whole batch and nothing reaches your server. Blocked messages get their own error; every other request with an id gets -32600 batch rejected by OpenWAF MCP Shield.
In log mode none of these answers are sent: the message passes and its event is recorded with blocked: false. Every code and event kind is on the errors and events page.
Events and docs
See what it would block
Every policy hit and detection is an event and a counter, in log mode as in enforce.
Events and counters
- Each event carries the JSON-RPC method, the tool, the detector ids and a token fingerprint: the first 8 bytes of an HMAC-SHA256 of
Authorizationwith a per-zone key, never the token. - Counters per endpoint (messages, blocked, detections, uninspected) and per tool, for up to 50 tools.
- Live security events under the rule name MCP Shield, and 30 days of history.
- In the dashboard (AI Crawl Control → MCP Shield), the API,
openwaf-cloud ctl ai mcpand theai_agents_reportMCP tool.
Documentation
- OverviewThreats, request path, log and enforce
- Enable MCP ShieldDashboard, CLI, API or your AI assistant
- Settings and modesEvery field and its default
- What is and isn’t detectedInspected text, detectors and gaps
- Errors and eventsAnswers, codes, events and counters
- Launch postWhy an MCP server needs its own checks
- Bots and AI agentsThe protection MCP Shield is part of
Put your MCP server behind the edge.
MCP Shield is part of Bots and AI agents in OpenWAF, free during early access. Add an MCP endpoint in log mode and see what it would block before it blocks anything.


