MCP Integration
CapFence provides a transparent stdio-proxying gateway for any MCP server. It evaluates every tools/call request against your policy before forwarding it to the upstream server.
How it works
The gateway intercepts JSON-RPC messages on stdin, extracts params.arguments from tools/call requests, evaluates them against the gate, and either forwards the message or returns a standardized −32000 error to the client. The upstream MCP server never receives blocked calls.
Setup
from capfence.mcp.gateway import MCPGatewayServer
gateway = MCPGatewayServer(
upstream_command=["python", "-m", "mcp_server_filesystem", "/data"],
policy_path="policies/mcp.yaml",
agent_id="mcp-agent"
)
gateway.run()Client configuration
Run the gateway as the process your MCP client connects to. If you need a CLI wrapper for a specific desktop client, create a small Python entrypoint that constructs MCPGatewayServer with your upstream command and policy path.
from capfence.mcp.gateway import MCPGatewayServer
MCPGatewayServer(
upstream_command=["python", "-m", "mcp_server_filesystem", "/data"],
policy_path="policies/mcp.yaml",
agent_id="desktop-agent",
).run()Policy for MCP
# policies/mcp.yaml
deny:
- capability: mcp.tool.execute
tool_name: "delete_*"
- capability: mcp.tool.execute
tool_name: "shell_*"
require_approval:
- capability: mcp.tool.execute
tool_name: "write_*"
path_prefix: "/data/prod"
allow:
- capability: mcp.tool.executeBlocked call response
When a call is blocked, the client receives a JSON-RPC error:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32000,
"message": "CapFence blocked this tool call"
}
}Audit trail
All MCP tool calls are logged with the full JSON-RPC payload hash:
capfence logs --agent mcp-agent