MCP tool verification
An agent that talks to MCP servers, governed end-to-end: approved servers flow, unknown ones are blocked and scored, and every call is chained.
1 · Approve the servers you trust
curl -X POST https://www.proofledger.dev/api/tools \
-H "authorization: Bearer $PROOFLEDGER_API_KEY" \
-H "content-type: application/json" \
-d '{ "name": "github_mcp", "type": "mcp",
"mcpServerUrl": "mcp://github-mcp.internal",
"approved": true, "riskLevel": "medium",
"allowedAgents": ["ci-agent", "release-agent"] }'2 · Log every MCP call before it runs
import { ProofLedger, PolicyBlockedError } from "@proofledger/sdk";
ProofLedger.enable({
apiKey: process.env.PROOFLEDGER_API_KEY,
agentName: "ci-agent",
framework: "custom",
policyMode: "enforce",
});
await ProofLedger.registerAgent();
/** Gate any MCP tool invocation through ProofLedger. */
async function callMcpTool(server: string, tool: string, args: unknown) {
try {
await ProofLedger.logToolCall({
toolName: tool,
toolType: "mcp",
mcpServer: server,
inputSummary: JSON.stringify(args).slice(0, 300),
});
} catch (err) {
if (err instanceof PolicyBlockedError) {
// Unknown/unapproved server: blocked, security event raised,
// trust score reduced, entry auto-registered for operator review.
console.warn(`MCP call blocked: ${err.evaluation.reason}`);
return null;
}
throw err;
}
return mcpClient.call(server, tool, args);
}
await callMcpTool("mcp://github-mcp.internal", "create_pr", { title: "…" }); // allowed
await callMcpTool("mcp://random-scraper.example", "scrape", { url: "…" }); // blocked3 · Review in the dashboard
The blocked server appears under Tools & MCP as unapproved (high risk) with its usage count; the block lands on the Security page and in the agent's timeline; the agent's trust score drops with a written reason. Approving the entry turns future calls into allow — no code change.
Note
Registered-but-unapproved MCP servers get a warn instead of a block — useful for a staged rollout where you observe first and approve after.