Your Agent Has Tools Now: Why MCP Tool Calls Need Runtime Verification A developer warns that Model Context Protocol (MCP) tool calls in AI agents introduce new security risks, including remote code execution, SSRF, credential exfiltration, and prompt injection. Static configuration scanning is insufficient; runtime verification is needed to assess the safety of each specific tool call based on context. For most of the short history of LLM applications, model risk was text risk. A model could output bad advice, leak something from its prompt, or produce a convincing phishing draft — but it couldn't touch your machine. The worst case ended at the screen. Wire a few tools into that model — a shell, an HTTP fetcher, a filesystem client, a cloud SDK — and the equation changes. With the Model Context Protocol https://modelcontextprotocol.io , agents don't just suggest operations anymore; they perform them, with your credentials, on your infrastructure. The attack surface moves from "text the model wrote" to "actions the model took." A prompt that used to produce a paragraph can now produce a process. If you're shipping agents with tool access, configuration hygiene is necessary but not sufficient. Here's why, and what runtime verification adds. The abuse patterns below are well-known categories — described generically, without reference to any specific project's incidents. 1. Code execution tools → remote code execution. Shell, exec , and interpreter tools exist because agents genuinely need them: running tests, scaffolding projects, transforming data. But any string that reaches a shell is a command. Content fetched from a web page, a filename, an error message, or a dependency's metadata can carry shell metacharacters. The model doesn't need to be "hacked" in the classic sense — it just needs to faithfully pass attacker-influenced text into an execution tool. 2. Fetch / HTTP tools → SSRF. Agents love to fetch URLs: docs, APIs, "read this link the user pasted." A URL is also a network destination. Point a fetcher at a cloud metadata endpoint 169.254.169.254 , a private RFC1918 address, or localhost:port and the agent becomes an SSRF primitive — reading internal services from inside your network perimeter and helpfully summarizing what it found. 3. Credential and environment-variable exfiltration. Agent processes inherit environment: AWS , GITHUB TOKEN , database URLs, API keys. Tools often accept arbitrary key/value or arguments. A two-step chain — read a sensitive file or env var, then POST it somewhere via the HTTP tool — turns a "helpful agent" into an exfiltration channel. Neither step looks dramatic on its own. 4. Prompt injection → unauthorized tool calls. Untrusted content in the model's context a web page, an email, a file, a tool result can contain instructions aimed at the model. The model is the one holding the tool handles, and it can't always tell your instructions apart from instructions embedded in data. The outcome is a tool call you never authorized, performed with your authority. Scanning your MCP configuration is the right first move. A static scanner catches real, fixable problems: plain-HTTP transports, disabled TLS verification, credentials pasted directly into config JSON, missing timeouts, over-broad permissions, unpinned server versions. The open-source correctover-scan https://www.npmjs.com/package/correctover-scan runs .cursor/mcp.json , claude desktop config.json , .claude/mcp.json , mcp.json , and a few more.But a config file is static, and the dangerous part is dynamic. Your mcp.json will never contain the argument the model constructs at 3 a.m. — the URL it decided to fetch, the command string it assembled from a tool result, the env var name it placed into an HTTP body. Static analysis answers "is this setup reasonable?"; it cannot answer "is this specific call safe?" The tempting shortcut is a keyword blacklist: block calls containing exec , block URLs containing 169.254 , block arguments containing AWS SECRET . It doesn't work, because safety is contextual: exec as its normal, declared function is exec string passed to a shell is Same tokens, different verdicts — because the tool , the caller , the arguments , and the chain of preceding calls differ. That judgment has to happen at call time, with the actual arguments in hand. A runtime verifier sits in front of tool execution and evaluates every call before it runs. For security, five layers matter most: payments.send call with amount as a string fails before it reaches the API.Two non-negotiable properties: Step 1 — scan your configs locally. Zero dependencies, no network needed: Auto-discovers .cursor/mcp.json, claude desktop config.json, .claude/mcp.json, mcp.json and friends in the current directory npx correctover-scan Or point it at a file / directory, with SARIF output for CI npx correctover-scan mcp.json -f sarif report.sarif npx correctover-scan -d ./my-project Step 2 — add the runtime verifier as an MCP server. ccs-mcp-server https://www.npmjs.com/package/ccs-mcp-server is a zero-dependency stdio MCP server. Drop this into your client config Claude Desktop, Cursor, or any other stdio-compatible MCP client : { "mcpServers": { "ccs-runtime-evidence": { "command": "npx", "args": "-y", "ccs-mcp-server" } } } It exposes verify tool call the checks above, blocking unsafe calls by default , issue evidence Ed25519-signed receipts for every decision, allow and deny , and config-audit and receipt-verification tools. The signing keypair is generated automatically on first run; set the CCS KEY DIR environment variable only if you want to control where it persists. Step 3 — wrap an existing server optional . If you'd rather verify calls transparently around a server you already run, the compatibility package forwards to the verification gateway: npx -y correctover-mcp-server --stdio -- npx -y