CAIN-42 CAIN Studio

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

> cain is the operator CLI that ships with self-hosted MCPGate; it is not installable on its own yet (CLI reference). With only the SDK, use cainstudio or plain curl (see the quickstart).

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.