MCP
The MCP (Model Context Protocol) adapter intercepts tool calls on an MCP server, records each invocation through a ProofRail chain, and only forwards the call to the underlying handler when the policy engine allows it. If you’re building MCP servers exposing tools to Claude Desktop, Cursor, or any other MCP client, this is how you add governance without changing your tool code.Install
mcp Python SDK if not already present.
Supported MCP Python SDK versions: 1.0.x. The protocol is still evolving — pin the specific version range you’ve tested against.
Quick start
The simplest integration: open a chain, attach the adapter, install it on your MCP server.adapter.install(server), every tool call passes through ProofRail’s policy engine. Denied calls return an MCP-compatible error to the client. Allowed calls execute normally.
Three usage patterns
The MCP adapter supports three integration styles depending on how your server is structured.Pattern 1: install() — wrap an existing server
If you already have a Server instance with @server.call_tool() registered, install() patches the call handler in place. Your existing code keeps working; you just gain governance.
Pattern 2: handle_tool_call() — manual interception
If you don’t want to patch the server, you can route calls through the adapter manually:
Pattern 3: @adapter.tool() decorator — per-tool wrapping
For more granular control, decorate individual tool implementations:
What gets recorded
For each tool invocation:- A
tool_callevent with the tool name asaction_nameand the arguments as the payload agent_nameis the value you passed toProofRailMcpAdapterparent_agent_nameif you supplied one (useful for tracking MCP client identity)
Policy enforcement
When a policy denies a tool call:install(), the adapter handles error conversion automatically — denied calls return an MCP-compatible error response without raising in your server code.
For approval-required decisions, handle_tool_call blocks until the approver responds. The MCP client sees a delayed response (until approval times out, your client may consider the call hung — set reasonable client timeouts).
Identifying the MCP client
If your MCP server knows which client is connected, pass that identity asparent_agent_name:
Session lifetime
A ProofRail chain corresponds to an MCP session. The natural pattern:proofrail/mcp/adapter.py for the underlying primitives.
Edge cases
Server doesn’t have_call_tool_handler registered yet. install() raises RuntimeError. Register at least one @server.call_tool() before calling install, or use Pattern 2 / Pattern 3 instead.
Multiple tools registered. install() wraps the single dispatch function MCP uses internally. All tools are covered.
Tool with no arguments. Works fine — arguments={} is a valid payload.
Streaming tool responses. MCP tools that stream responses are tracked at the request level only. The response stream is forwarded to the client unchanged; ProofRail doesn’t intercept individual stream chunks.
Tool errors. If the underlying handler raises, the exception propagates after the governance event is recorded. The event records the call as “attempted” — the error itself is part of the MCP response.
Where to go next
LangGraph adapter
For LangGraph-orchestrated agent workflows.
LangChain adapter
For LangChain agent executors and chains.
Policies
What decisions get applied to your tool calls.
SDK reference
The complete
ProofRailMcpAdapter API.