Developer documentation
MCP
Last reviewed 31 August 2026
All docs
Protecting an MCP server#
MCP is where an agent actually reaches the world, so it is the highest-value thing to put a decision in front of.
The shape of it#
Instead of your client talking to your MCP server directly, it talks to MCPGate, which decides and then forwards:
MCP client -> MCPGate (decides, enforces) -> your MCP server -> tool runs
One command#
cain protect mcp ./my-server
That inspects the target and prints what to change. It does not rewrite your MCP client configuration -- reconfiguring a developer's environment unprompted is the kind of surprise that loses trust, so the change is shown and applied only with --apply.
It reports what it found: whether the target exists, whether it is a local directory or a remote URL, and how many tools appear to be declared. The tool count is derived by reading source files, not by executing the server -- a security tool that runs an unknown MCP server to enumerate its tools would be a remarkable thing.
Then prove the path#
cain test --mcp
This is the check that matters, because "I pointed my client at the gateway" and "calls are actually being decided" are different claims. Note that the client-side suite reports MCP path enforcement as SKIP when it cannot observe it directly -- a skip is not a pass, and it withholds the conformance claim.
Declaring servers#
mcp:
servers:
- ./my-server
- https://tools.internal/mcp
cain test checks these are declared. With none listed, the MCP suite skips rather than passing vacuously.
What is protected, and what is not#
Protected: the decision to allow a tool call, made before the call reaches your server, recorded as evidence.
Not protected by this alone: anything that talks to your MCP server without going through the gateway. If the server is still reachable directly, a client that skips the gateway skips the decision. Bind it to localhost, or put it on a network only the gateway can reach. cain doctor cannot see this for you, and does not claim to.