Your MCP server updated. Did the tool schemas change? Did descriptions get rewritten with hidden instructions? You'd never know — until now.
mcpdiff captures versioned snapshots of MCP server tool schemas and detects breaking changes, drift, and potential tool poisoning vectors.
Pin your contracts. Diff your tools. Ship with confidence.
MCP servers expose tools, resources, and prompts to AI agents. These interfaces are defined by JSON schemas — but there's no mechanism to version, diff, or validate them. When a server updates:
- Breaking changes go unnoticed. A new required parameter silently breaks every agent using the tool.
- Description changes are invisible. Tool descriptions are the primary vector for tool poisoning attacks — and nobody reviews them.
- There's no contract to pin. Agents trust whatever schema the server serves at runtime, with no way to detect drift.
mcpdiff solves this by treating MCP tool schemas as contracts — versionable, diffable, and auditable artifacts.
# Capture a baseline snapshot of your MCP server
npx mcpdiff baseline update --command "node ./my-server/dist/index.js"
# → writes contracts/baseline.mcpc.json
# Later, verify nothing has changed
npx mcpdiff baseline verify --command "node ./my-server/dist/index.js"
# Or diff two snapshots manually
npx mcpdiff snapshot --command "node ./my-server/dist/index.js" -o v1.mcpc.json
# ... make changes ...
npx mcpdiff snapshot --command "node ./my-server/dist/index.js" -o v2.mcpc.json
npx mcpdiff diff v1.mcpc.json v2.mcpc.jsonOutput:
mcp-contracts diff — acme-server v1.0.0 → v1.1.0
🔴 BREAKING tool "create_contact" — required parameter "phone" added
🟡 WARNING tool "search_contacts" — description changed
🟢 SAFE tool "export_csv" — new tool added
Summary: 1 breaking · 1 warning · 1 safe
Connects to an MCP server and captures its complete tool/resource/prompt interface as a .mcpc.json file.
# Via stdio transport
mcpdiff snapshot --command "node server.js" -o snapshot.mcpc.json
# Via HTTP transport
mcpdiff snapshot --url http://localhost:3000/mcp -o snapshot.mcpc.json
# From an mcp.json config file
mcpdiff snapshot --config ./mcp.json --server my-server -o snapshot.mcpc.jsonCompares two snapshots and classifies every change as breaking, warning, or safe.
mcpdiff diff before.mcpc.json after.mcpc.json
# Fail CI on warnings too (stricter)
mcpdiff diff before.mcpc.json after.mcpc.json --fail-on warning
# Output as JSON for programmatic use
mcpdiff diff before.mcpc.json after.mcpc.json --format jsonExit codes: 0 = no breaking changes, 1 = breaking changes detected, 2 = error.
Manage contract baselines — capture and verify snapshots against a committed baseline.
# Capture a baseline (default: contracts/baseline.mcpc.json)
mcpdiff baseline update --command "node server.js"
# Write to a custom path
mcpdiff -o custom/path.mcpc.json baseline update --command "node server.js"
# Verify the server still matches the baseline
mcpdiff baseline verify --command "node server.js"
mcpdiff baseline verify --baseline custom/path.mcpc.json --url http://localhost:3000/mcpAll-in-one CI command: captures a snapshot, diffs against a baseline, outputs the report, and sets the exit code.
# Basic usage
mcpdiff ci --baseline contracts/baseline.mcpc.json --command "node server.js"
# Fail on warnings too (stricter)
mcpdiff ci --baseline contracts/baseline.mcpc.json --command "node server.js" --fail-on warning
# Only show breaking changes
mcpdiff ci --baseline contracts/baseline.mcpc.json --command "node server.js" --severity breakingAuto-detects CI environments (GitHub Actions, GitLab CI, CircleCI) and selects the appropriate output format. Writes to GITHUB_STEP_SUMMARY when running in GitHub Actions.
Summarizes a snapshot file.
mcpdiff inspect snapshot.mcpc.json
mcpdiff inspect snapshot.mcpc.json --tools
mcpdiff inspect snapshot.mcpc.json --schema create_contactTool descriptions aren't just documentation — they're instructions to the model. A changed description can embed hidden prompt injections that alter how an agent uses the tool, without changing the schema at all. This is OWASP MCP03:2025 — Tool Poisoning.
mcpdiff flags every description change as a warning and shows you a readable diff of what changed, so you can review it before deploying.
The easiest way to integrate with GitHub is the official action:
# .github/workflows/mcp-contract.yml
name: MCP Contract Check
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: mcp-contracts/github-action@v0
with:
baseline: contracts/baseline.mcpc.json
command: node dist/index.js
fail-on: breaking # or "warning" / "safe"
comment-on-pr: true
github-token: ${{ secrets.GITHUB_TOKEN }}Outputs: has-changes, has-breaking, summary, exit-code — use them in subsequent steps.
Use mcpdiff ci directly in any CI system:
# .github/workflows/mcp-contract.yml
name: MCP Contract Check
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install -g @mcp-contracts/cli
- run: mcpdiff ci --baseline contracts/baseline.mcpc.json --command "node dist/index.js"The ci command auto-detects the CI environment and selects the right output format (markdown for GitHub Actions, JSON otherwise). It also writes to GITHUB_STEP_SUMMARY automatically.
| Package | Description |
|---|---|
@mcp-contracts/core |
Snapshot types, diff engine, classification logic |
@mcp-contracts/cli |
The mcpdiff CLI tool |
@mcp-contracts/github-action |
GitHub Action for CI integration |
mcp-contracts is an open-source project (MIT license). It's community tooling for the MCP ecosystem, not affiliated with Anthropic or the MCP project. Contributions and feedback are welcome.
MIT