I spent a morning looking at MCP security tooling. Cisco has a scanner, there are three or four audit CLIs, all of them read your tool descriptions and report sketchy ones. Useful, but they share a blind spot: nothing sits between the agent and the server when the call actually happens.

The failure mode that keeps showing up (the 159-point HN thread on MCP vulnerabilities is mostly this) is boring: the agent calls read_file with ../../etc/passwd, or fetch on http://169.254.169.254, or a get_env tool that politely returns your AWS keys. A scanner that read the tool description last week does nothing here.

So I built mcp-bouncer. It wraps any stdio MCP server as a JSON-RPC proxy:

  • tools/list responses get filtered, so unapproved tools are invisible to the agent
  • path args are normalized (dot segments resolved, separators unified) before allow/deny globs match, which kills traversal and most encoding games
  • url args refuse private IPs, 169.254.169.254, *.internal, localhost, and any scheme you did not list
  • per-tool rate limits, a response size cap, call timeouts
  • every decision appended to a local JSONL audit file, with a sha256 digest of the args rather than the args themselves (args hold secrets; digests still let you correlate)

The embarrassing bug

First working version blocked every single call. The reason: my "contains a null byte" check compared against what was supposed to be a literal NUL and was actually an empty string, and everything includes the empty string. Test suite caught it because I assert the allowed path actually passes, which is the whole point of writing tests that check the happy path and not just the blocks.

Limits, honestly

  • This is protocol-level enforcement. The wrapped server still runs as your user; a hostile binary can read whatever it wants. For that you want a container or a real sandbox.
  • Stdio transport only. Remote HTTP MCP servers are not covered yet.
  • A policy you wrote wrong is still wrong. mcp-bouncer scan gives you a starting draft, not a guarantee.

About 500 lines, zero dependencies, MIT.

repo: https://github.com/princejain756/mcp-bouncer

What is the ugliest thing an MCP server has done in your setup?