Code and dense tables are folded away. Open any of them on demand.
Example check
Generated code, after fetching a web page, calls an HTTP tool to post customer records to an external URL.
Show it as a curl commandHide technical details· shell
Why code mode changes the picture
Cloudflare’s "Code Mode" and Anthropic’s "Code execution with MCP" describe the same pattern: instead of calling tools one by one through the model, the model writes code against a typed API for the tools, and a sandbox runs it. That saves context and round trips, and it means a single turn can issue many tool calls in loops and branches.
The trade-off is visibility. With direct tool calling, a client can show each call to a user. In code mode, the calls happen inside running code. A loop that deletes "stale" records, or a step that posts data to an external API, runs without anyone seeing the individual calls. See guarding code-mode agents.
Where the guard sits
The sandbox has no direct network or credentials. Its only way to reach your tools is the tool proxy: a binding or RPC layer that forwards each call to the real MCP server or API. That makes the proxy the one place every call passes through.
In the proxy, before forwarding a call:
- Build a check with
actionset to the tool and arguments,intentset to the user’s original request, andcontextdescribing the environment. - Set
triggertotool_resultwhen earlier calls in the same run returned external content, since the generated code may be acting on it. - Call
POST /v1/guard, orPOST /v1/guard/batch(up to 64 checks) when the code issues several calls at once. - Forward on allow, pause the run for approval on ask, and return an error to the code on block.
Acting on the verdict
By default the server returns block when P(unsafe) is at least 0.8 or the approval_policy head says reject, ask when P(unsafe) is at least 0.3, the policy head says require_human, or args_grounded is below 0.5, and allow otherwise. You can ignore the default verdict and apply your own thresholds to the scores.
Because nobody watches individual calls, the policy for code mode is usually stricter than for interactive agents. Pay attention to blast_radius (reads are cheap to allow; production writes are not), exfiltration (data leaving via an HTTP or messaging tool), injected (code acting on fetched content) and args_grounded (ids or recipients the user never mentioned). Returning a clear error on block lets the generated code handle the refusal instead of crashing silently.
A check takes about 15 ms on our GPU (RTX 4090, batch 1, p95 about 23 ms); a batch counts as one request against the free allowance, and each check in it is billed as one credit.
Controls to keep alongside the guard
The sandbox is itself a deterministic control; keep it tight:
- No direct network access from the sandbox; only the tool proxy.
- Credentials live in the proxy, never in the sandbox.
- Per-run limits on the number of tool calls and on runtime.
- An allowlist of tools each run may use.
The sandbox constrains what code can do. The guard judges whether each tool call makes sense for the request. Neither is sufficient alone, and the guard reduces risk without guaranteeing safety.
Frequently asked questions
Should I check every call, even reads?
Can I use the MCP server instead of the REST API?
Sources
Last updated . MCP Guard reduces the risk of harmful agent actions; it does not guarantee safety. Keep deterministic controls in place alongside it. Third-party names are used only to describe their products; we are not affiliated with them.