mcp-contracts

mcp
Security Audit
Fail
Health Warn
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Fail
  • rm -rf — Recursive force deletion command in examples/contacts-server/demo.sh
Permissions Pass
  • Permissions — No dangerous permissions requested
Purpose
This tool provides version control and diffing capabilities for Model Context Protocol (MCP) schemas. It helps developers catch breaking changes, detect API drift, and identify potential tool-poisoning attacks before deploying updates to production.

Security Assessment
Overall risk: Low. The server itself does not request dangerous permissions or access sensitive user data. It operates primarily as an auditing utility for local or remote schemas via standard CLI commands. However, there is one notable code flag: a recursive force deletion command (`rm -rf`) was found inside a demonstration script (`examples/contacts-server/demo.sh`). While this is likely just boilerplate cleanup code for an example environment, developers should be aware of it and ensure they do not blindly execute example scripts without reviewing them first. No hardcoded secrets or malicious network behaviors were detected.

Quality Assessment
The project is relatively new and has very low community visibility, currently sitting at only 5 GitHub stars. Despite the small user base, the repository is under active development, with its most recent push occurring today. It uses the permissive and standard MIT license, making it highly accessible for integration. The core concept is highly relevant and addresses a real gap in MCP security by monitoring tool descriptions for unauthorized modifications.

Verdict
Use with caution — the tool is actively maintained and serves a valuable security purpose, but its low community adoption and the `rm -rf` flag in the demo scripts warrant a quick code review before integrating it into your environment.
SUMMARY

Snapshot, diff, and validate MCP (Model Context Protocol) tool schemas. Brings OpenAPI-level contract safety to the MCP ecosystem — catch breaking changes before they hit production.

README.md

mcp-contracts

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.

The Problem

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.

Quick Start

# Capture a baseline snapshot of your MCP server
npx @mcp-contracts/cli baseline update --command "node ./my-server/dist/index.js"
# → writes contracts/baseline.mcpc.json

# Later, verify nothing has changed
npx @mcp-contracts/cli baseline verify --command "node ./my-server/dist/index.js"

# Or diff two snapshots manually
npx @mcp-contracts/cli snapshot --command "node ./my-server/dist/index.js" -o v1.mcpc.json
# ... make changes ...
npx @mcp-contracts/cli snapshot --command "node ./my-server/dist/index.js" -o v2.mcpc.json
npx @mcp-contracts/cli diff v1.mcpc.json v2.mcpc.json

Output:

  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

Commands

mcpdiff snapshot

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.json

mcpdiff diff

Compares two snapshots and classifies every change as breaking, warning, or safe.

mcpdiff diff before.mcpc.json after.mcpc.json

# Diff a baseline against a live server
mcpdiff diff baseline.mcpc.json --live --command "node server.js"

# 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 json

# Send results to a webhook
mcpdiff diff before.mcpc.json after.mcpc.json --webhook https://example.com/hook

Exit codes: 0 = no breaking changes, 1 = breaking changes detected, 2 = error.

mcpdiff baseline

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/mcp

mcpdiff ci

All-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 breaking

# Send results to a webhook
mcpdiff ci --baseline contracts/baseline.mcpc.json --command "node server.js" --webhook https://example.com/hook

Auto-detects CI environments (GitHub Actions, GitLab CI, CircleCI) and selects the appropriate output format. Writes to GITHUB_STEP_SUMMARY when running in GitHub Actions.

mcpdiff watch

Watch for file changes and re-diff against a baseline on every change. Useful during development.

mcpdiff watch --baseline contracts/baseline.mcpc.json --command "node server.js"

# Watch specific paths with custom debounce
mcpdiff watch --baseline contracts/baseline.mcpc.json --command "node server.js" \
  --watch-paths src lib --debounce 1000

# Send diffs to a webhook on each cycle
mcpdiff watch --baseline contracts/baseline.mcpc.json --command "node server.js" \
  --webhook https://example.com/hook

mcpdiff sign

Signs a snapshot with a private key, producing a detached .mcpc.sig file.

# Sign with Ed25519
mcpdiff sign contracts/baseline.mcpc.json --key ./private.pem

# Sign with RSA
mcpdiff sign contracts/baseline.mcpc.json --key ./rsa-private.pem

# Write signature to a custom path
mcpdiff sign snapshot.mcpc.json --key ./private.pem -o custom/path.mcpc.sig

The sign command verifies the content hash before signing — it will refuse to sign a snapshot whose content has been tampered with.

mcpdiff verify

Verifies a snapshot's signature using a public key.

# Verify (auto-discovers .mcpc.sig file next to the snapshot)
mcpdiff verify contracts/baseline.mcpc.json --key ./public.pem

# Explicit signature path
mcpdiff verify snapshot.mcpc.json --key ./public.pem --signature custom/path.mcpc.sig

Performs three checks: content hash integrity, hash binding (signature matches this snapshot), and cryptographic verification. Exit code 0 on success, 1 on failure.

mcpdiff verify-hash

Quick integrity check — recomputes the content hash and compares to the stored value. No keys needed.

mcpdiff verify-hash snapshot.mcpc.json

# JSON output
mcpdiff verify-hash snapshot.mcpc.json --format json

mcpdiff inspect

Summarizes a snapshot file.

mcpdiff inspect snapshot.mcpc.json
mcpdiff inspect snapshot.mcpc.json --tools
mcpdiff inspect snapshot.mcpc.json --schema create_contact

Transport Options

All commands that connect to a live server accept these transport options:

# SSE transport (instead of default streamable-http)
mcpdiff snapshot --url http://localhost:3000/sse --sse -o snapshot.mcpc.json

# Custom HTTP headers (repeatable)
mcpdiff snapshot --url http://localhost:3000/mcp \
  --header "Authorization: Bearer token" \
  --header "X-Custom: value" \
  -o snapshot.mcpc.json
Flag Description
--command <cmd> Server command to run via stdio transport
--url <url> Server URL for streamable-http or SSE transport
--sse Use SSE transport instead of streamable-http (requires --url)
--header <header...> Custom HTTP headers as "Key: Value" (repeatable)
--config <path> Path to mcp.json config file
--server <name> Server name from config file

Why Description Changes are Warnings

Tool 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.

CI Integration

GitHub Action

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 }}
          # Optional: verify baseline signature before diffing
          verify-signature: true
          signature-key: ${{ secrets.MCP_PUBLIC_KEY }}

Outputs: has-changes, has-breaking, summary, exit-code — use them in subsequent steps.

CLI in CI

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"

      # Or with signature verification
      - run: >
          mcpdiff ci
          --baseline contracts/baseline.mcpc.json
          --command "node dist/index.js"
          --verify-signature
          --signature-key ./public.pem

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.

Packages

Package Description
@mcp-contracts/core Snapshot types, diff engine, classification logic
@mcp-contracts/cli The mcpdiff CLI tool

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.

License

MIT

Reviews (0)

No results found