https://github.com/mcp-contracts/mcp-contracts
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.
https://github.com/mcp-contracts/mcp-contracts
api-compatibility breaking-changes cli contract-testing developer-tools diff mcp mcp-server model-context-protocol schema-validation typescript
Last synced: 18 days ago
JSON representation
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.
- Host: GitHub
- URL: https://github.com/mcp-contracts/mcp-contracts
- Owner: mcp-contracts
- License: mit
- Created: 2026-02-20T21:19:16.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-03-28T15:34:16.000Z (29 days ago)
- Last Synced: 2026-03-28T17:48:47.287Z (29 days ago)
- Topics: api-compatibility, breaking-changes, cli, contract-testing, developer-tools, diff, mcp, mcp-server, model-context-protocol, schema-validation, typescript
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/@mcp-contracts/cli
- Size: 377 KB
- Stars: 4
- Watchers: 0
- Forks: 0
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
# 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](https://owasp.org/www-project-mcp-top-10/2025/MCP03-2025%E2%80%93Tool-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](https://owasp.org/www-project-mcp-top-10/2025/MCP03-2025%E2%80%93Tool-Poisoning) — 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
```bash
# 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.
```bash
# 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.
```bash
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.
```bash
# 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.
```bash
# 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.
```bash
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.
```bash
# 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.
```bash
# 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.
```bash
mcpdiff verify-hash snapshot.mcpc.json
# JSON output
mcpdiff verify-hash snapshot.mcpc.json --format json
```
### `mcpdiff inspect`
Summarizes a snapshot file.
```bash
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:
```bash
# 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 ` | Server command to run via stdio transport |
| `--url ` | Server URL for streamable-http or SSE transport |
| `--sse` | Use SSE transport instead of streamable-http (requires `--url`) |
| `--header ` | Custom HTTP headers as `"Key: Value"` (repeatable) |
| `--config ` | Path to `mcp.json` config file |
| `--server ` | 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](https://owasp.org/www-project-mcp-top-10/2025/MCP03-2025%E2%80%93Tool-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:
```yaml
# .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:
```yaml
# .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`](./packages/core) | Snapshot types, diff engine, classification logic |
| [`@mcp-contracts/cli`](./packages/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