
Company News
Free Business Plan Upgrades for Open Source Maintainers
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.
mcp-tool-guard
Advanced tools
Wrap an MCP client so a silently-skipped or discarded tool call throws instead of letting the agent report success on nothing.
An agent calls a tool over MCP, the spawn or transport hiccups, the call never actually runs — and the agent reports "done" anyway, because nothing in the loop threw. That's not hypothetical: it's a reproduced bug in NanoClaw #2968 (a discarded write the agent claimed succeeded), a Cursor forum thread where MCP tool calls silently stopped firing across models, and Codex #31374. A 2026 study of 11,755 agent trajectories found false-success reporting made up 45-78% of failures depending on the benchmark (arXiv:2606.09863).
mcp-tool-guard wraps your MCP client's callTool so a call that returns
nothing, times out, or reports isError throws immediately instead of
letting execution continue past it. It also keeps a ledger you can check
right before the agent reports success, so a spawn failure that swallowed
the whole call — not just a bad response — still gets caught.
npm install mcp-tool-guard
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { guard } from "mcp-tool-guard";
const raw = new Client({ name: "my-agent", version: "1.0.0" });
await raw.connect(transport);
const { client, ledger } = guard(raw, { timeoutMs: 15_000 });
// use `client` exactly like you'd use `raw` — same callTool signature
await client.callTool({ name: "write_file", arguments: { path: "out.txt" } });
// right before the agent reports success on this turn:
ledger.assertAllSucceeded(["write_file"]); // throws if it never ran, errored, or timed out
If the write silently didn't happen, assertAllSucceeded throws instead of
letting your agent loop tell the user it's done.
A call can return a well-formed, non-error response and still not have done
anything — run_migration that reports success on 0 rows changed, say. Pass
a postcondition to check the result, not just its shape:
const { client } = guard(raw, {
postcondition: (toolName, args, result) => {
if (toolName === "run_migration") {
return !result.content[0].text.includes("0 rows");
}
return true;
},
});
isError: true responsesledger.assertAllSucceeded(expectedNames)It's a runtime guard around calls you make, not a static analyzer or a
security scanner (see mcp-conform
for spec-conformance linting instead). It can't infer what a tool call was
supposed to do — the postcondition and expectedToolNames are how you tell
it. If you need call-order assertions or full session recording, this is a
narrower, dependency-free complement to tools like mcp-assert and
Agentprobe, not a replacement.
MIT
Built autonomously by an AI agent.
FAQs
Wrap an MCP client so a silently-skipped or discarded tool call throws instead of letting the agent report success on nothing.
We found that mcp-tool-guard demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.