Skip to content

MCP trust (toolprint)

AI Workbench both hosts an MCP server (src/mcp/server.ts, exposed at /api/v1/workspaces/{workspaceId}/mcp) and lets agents connect to external MCP servers as tools. In both cases an agent reads each tool's description and input schema to decide what to do — so a server that silently rewrites a tool's description (a "rug-pull") can redirect an agent without anyone noticing. It's the classic tool-poisoning vector.

We guard against this the same way we guard dependency versions: with a committed lockfile. toolprint ("package-lock.json for MCP trust") lists every tool/prompt/resource a server advertises, hashes each definition, and pins them into toolprint.lock. On every change it diffs the live surface against the pin — drift shows up as a reviewable diff and fails CI (.github/workflows/toolprint.yml). toolprint only ever calls tools/list; it never executes a tool.

What's pinned

TargetSourceWhy
Our own MCP serverbooted hermetically — see belowA code change that alters a tool's description/schema is a contract change to every agent that connects. Catch it in review.
Trusted external servers.toolprint/mcp.jsonAn upstream server we depend on could rug-pull between releases. The weekly CI cron catches it even with no PR.

.toolprint/mcp.json is the curated list of external MCP servers this project trusts. Add the servers your team actually uses; each entry's tool surface gets pinned on the next re-pin.

Run it locally

bash
npm run security:mcp            # scan — fails on drift, injection, or leaked secrets
npm run security:mcp -- --pin   # re-pin after an *intended* change, then commit toolprint.lock

The scan boots the runtime hermetically via examples/workbench.toolprint-ci.yaml (memory control plane, one seeded mock workspace, default open-auth posture) on http://localhost:8099, scans, and tears it down. No Astra, secrets, LLM, or network backend required.

When the check fails

  1. Unintended drift — a tool's description/schema changed without you meaning to, or an external server rug-pulled. Investigate before trusting it; this is the case the check exists for.
  2. Intended change — you deliberately edited the MCP surface (added a tool, reworded a description). Re-pin and commit:
    bash
    npm run security:mcp -- --pin && git add toolprint.lock
    The toolprint.lock diff is part of code review, so a reviewer sees exactly which tool definitions changed.

Notes

  • Gate severity. As of toolprint 0.1.1 a rug-pull is classified high, so the scan relies on the default --fail-on high — a drifted tool definition fails the check with no override needed.
  • Auth. The own-server scan runs against the hermetic open-auth instance because the pinned tool surface (names/descriptions/schemas) is identical with or without auth — auth gates access, not definitions. toolprint 0.1.1 added --header/--bearer (and TOOLPRINT_BEARER), so an authenticated remote target can be scanned by passing a token; a throwaway localhost instance doesn't need it. This does not affect the deployed runtime's auth posture.

Released under the MIT license.