{"id":48566941,"url":"https://github.com/mcp-contracts/mcp-contracts","last_synced_at":"2026-04-08T13:03:35.589Z","repository":{"id":342062119,"uuid":"1162917104","full_name":"mcp-contracts/mcp-contracts","owner":"mcp-contracts","description":"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.","archived":false,"fork":false,"pushed_at":"2026-03-28T15:34:16.000Z","size":386,"stargazers_count":4,"open_issues_count":14,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-28T17:48:47.287Z","etag":null,"topics":["api-compatibility","breaking-changes","cli","contract-testing","developer-tools","diff","mcp","mcp-server","model-context-protocol","schema-validation","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@mcp-contracts/cli","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mcp-contracts.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-20T21:19:16.000Z","updated_at":"2026-03-28T15:32:53.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mcp-contracts/mcp-contracts","commit_stats":null,"previous_names":["mcp-contracts/mcp-contracts"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/mcp-contracts/mcp-contracts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcp-contracts%2Fmcp-contracts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcp-contracts%2Fmcp-contracts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcp-contracts%2Fmcp-contracts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcp-contracts%2Fmcp-contracts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mcp-contracts","download_url":"https://codeload.github.com/mcp-contracts/mcp-contracts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcp-contracts%2Fmcp-contracts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31556247,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T10:21:54.569Z","status":"ssl_error","status_checked_at":"2026-04-08T10:21:38.171Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-compatibility","breaking-changes","cli","contract-testing","developer-tools","diff","mcp","mcp-server","model-context-protocol","schema-validation","typescript"],"created_at":"2026-04-08T13:03:35.338Z","updated_at":"2026-04-08T13:03:35.582Z","avatar_url":"https://github.com/mcp-contracts.png","language":"TypeScript","readme":"# mcp-contracts\n\n**Your MCP server updated. Did the tool schemas change? Did descriptions get rewritten with hidden instructions? You'd never know — until now.**\n\n`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.\n\nPin your contracts. Diff your tools. Ship with confidence.\n\n## The Problem\n\nMCP 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:\n\n- **Breaking changes go unnoticed.** A new required parameter silently breaks every agent using the tool.\n- **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.\n- **There's no contract to pin.** Agents trust whatever schema the server serves at runtime, with no way to detect drift.\n\n`mcpdiff` solves this by treating MCP tool schemas as **contracts** — versionable, diffable, and auditable artifacts.\n\n## Quick Start\n\n```bash\n# Capture a baseline snapshot of your MCP server\nnpx @mcp-contracts/cli baseline update --command \"node ./my-server/dist/index.js\"\n# → writes contracts/baseline.mcpc.json\n\n# Later, verify nothing has changed\nnpx @mcp-contracts/cli baseline verify --command \"node ./my-server/dist/index.js\"\n\n# Or diff two snapshots manually\nnpx @mcp-contracts/cli snapshot --command \"node ./my-server/dist/index.js\" -o v1.mcpc.json\n# ... make changes ...\nnpx @mcp-contracts/cli snapshot --command \"node ./my-server/dist/index.js\" -o v2.mcpc.json\nnpx @mcp-contracts/cli diff v1.mcpc.json v2.mcpc.json\n```\n\nOutput:\n```\n  mcp-contracts diff — acme-server v1.0.0 → v1.1.0\n\n  🔴 BREAKING  tool \"create_contact\" — required parameter \"phone\" added\n  🟡 WARNING   tool \"search_contacts\" — description changed\n  🟢 SAFE      tool \"export_csv\" — new tool added\n\n  Summary: 1 breaking · 1 warning · 1 safe\n```\n\n## Commands\n\n### `mcpdiff snapshot`\n\nConnects to an MCP server and captures its complete tool/resource/prompt interface as a `.mcpc.json` file.\n\n```bash\n# Via stdio transport\nmcpdiff snapshot --command \"node server.js\" -o snapshot.mcpc.json\n\n# Via HTTP transport\nmcpdiff snapshot --url http://localhost:3000/mcp -o snapshot.mcpc.json\n\n# From an mcp.json config file\nmcpdiff snapshot --config ./mcp.json --server my-server -o snapshot.mcpc.json\n```\n\n### `mcpdiff diff`\n\nCompares two snapshots and classifies every change as breaking, warning, or safe.\n\n```bash\nmcpdiff diff before.mcpc.json after.mcpc.json\n\n# Diff a baseline against a live server\nmcpdiff diff baseline.mcpc.json --live --command \"node server.js\"\n\n# Fail CI on warnings too (stricter)\nmcpdiff diff before.mcpc.json after.mcpc.json --fail-on warning\n\n# Output as JSON for programmatic use\nmcpdiff diff before.mcpc.json after.mcpc.json --format json\n\n# Send results to a webhook\nmcpdiff diff before.mcpc.json after.mcpc.json --webhook https://example.com/hook\n```\n\n**Exit codes:** `0` = no breaking changes, `1` = breaking changes detected, `2` = error.\n\n### `mcpdiff baseline`\n\nManage contract baselines — capture and verify snapshots against a committed baseline.\n\n```bash\n# Capture a baseline (default: contracts/baseline.mcpc.json)\nmcpdiff baseline update --command \"node server.js\"\n\n# Write to a custom path\nmcpdiff -o custom/path.mcpc.json baseline update --command \"node server.js\"\n\n# Verify the server still matches the baseline\nmcpdiff baseline verify --command \"node server.js\"\nmcpdiff baseline verify --baseline custom/path.mcpc.json --url http://localhost:3000/mcp\n```\n\n### `mcpdiff ci`\n\nAll-in-one CI command: captures a snapshot, diffs against a baseline, outputs the report, and sets the exit code.\n\n```bash\n# Basic usage\nmcpdiff ci --baseline contracts/baseline.mcpc.json --command \"node server.js\"\n\n# Fail on warnings too (stricter)\nmcpdiff ci --baseline contracts/baseline.mcpc.json --command \"node server.js\" --fail-on warning\n\n# Only show breaking changes\nmcpdiff ci --baseline contracts/baseline.mcpc.json --command \"node server.js\" --severity breaking\n\n# Send results to a webhook\nmcpdiff ci --baseline contracts/baseline.mcpc.json --command \"node server.js\" --webhook https://example.com/hook\n```\n\nAuto-detects CI environments (GitHub Actions, GitLab CI, CircleCI) and selects the appropriate output format. Writes to `GITHUB_STEP_SUMMARY` when running in GitHub Actions.\n\n### `mcpdiff watch`\n\nWatch for file changes and re-diff against a baseline on every change. Useful during development.\n\n```bash\nmcpdiff watch --baseline contracts/baseline.mcpc.json --command \"node server.js\"\n\n# Watch specific paths with custom debounce\nmcpdiff watch --baseline contracts/baseline.mcpc.json --command \"node server.js\" \\\n  --watch-paths src lib --debounce 1000\n\n# Send diffs to a webhook on each cycle\nmcpdiff watch --baseline contracts/baseline.mcpc.json --command \"node server.js\" \\\n  --webhook https://example.com/hook\n```\n\n### `mcpdiff sign`\n\nSigns a snapshot with a private key, producing a detached `.mcpc.sig` file.\n\n```bash\n# Sign with Ed25519\nmcpdiff sign contracts/baseline.mcpc.json --key ./private.pem\n\n# Sign with RSA\nmcpdiff sign contracts/baseline.mcpc.json --key ./rsa-private.pem\n\n# Write signature to a custom path\nmcpdiff sign snapshot.mcpc.json --key ./private.pem -o custom/path.mcpc.sig\n```\n\nThe sign command verifies the content hash before signing — it will refuse to sign a snapshot whose content has been tampered with.\n\n### `mcpdiff verify`\n\nVerifies a snapshot's signature using a public key.\n\n```bash\n# Verify (auto-discovers .mcpc.sig file next to the snapshot)\nmcpdiff verify contracts/baseline.mcpc.json --key ./public.pem\n\n# Explicit signature path\nmcpdiff verify snapshot.mcpc.json --key ./public.pem --signature custom/path.mcpc.sig\n```\n\nPerforms three checks: content hash integrity, hash binding (signature matches this snapshot), and cryptographic verification. Exit code 0 on success, 1 on failure.\n\n### `mcpdiff verify-hash`\n\nQuick integrity check — recomputes the content hash and compares to the stored value. No keys needed.\n\n```bash\nmcpdiff verify-hash snapshot.mcpc.json\n\n# JSON output\nmcpdiff verify-hash snapshot.mcpc.json --format json\n```\n\n### `mcpdiff inspect`\n\nSummarizes a snapshot file.\n\n```bash\nmcpdiff inspect snapshot.mcpc.json\nmcpdiff inspect snapshot.mcpc.json --tools\nmcpdiff inspect snapshot.mcpc.json --schema create_contact\n```\n\n## Transport Options\n\nAll commands that connect to a live server accept these transport options:\n\n```bash\n# SSE transport (instead of default streamable-http)\nmcpdiff snapshot --url http://localhost:3000/sse --sse -o snapshot.mcpc.json\n\n# Custom HTTP headers (repeatable)\nmcpdiff snapshot --url http://localhost:3000/mcp \\\n  --header \"Authorization: Bearer token\" \\\n  --header \"X-Custom: value\" \\\n  -o snapshot.mcpc.json\n```\n\n| Flag | Description |\n|------|-------------|\n| `--command \u003ccmd\u003e` | Server command to run via stdio transport |\n| `--url \u003curl\u003e` | Server URL for streamable-http or SSE transport |\n| `--sse` | Use SSE transport instead of streamable-http (requires `--url`) |\n| `--header \u003cheader...\u003e` | Custom HTTP headers as `\"Key: Value\"` (repeatable) |\n| `--config \u003cpath\u003e` | Path to `mcp.json` config file |\n| `--server \u003cname\u003e` | Server name from config file |\n\n## Why Description Changes are Warnings\n\nTool 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).\n\n`mcpdiff` flags **every description change** as a warning and shows you a readable diff of what changed, so you can review it before deploying.\n\n## CI Integration\n\n### GitHub Action\n\nThe easiest way to integrate with GitHub is the official action:\n\n```yaml\n# .github/workflows/mcp-contract.yml\nname: MCP Contract Check\non: [pull_request]\njobs:\n  check:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: mcp-contracts/github-action@v0\n        with:\n          baseline: contracts/baseline.mcpc.json\n          command: node dist/index.js\n          fail-on: breaking        # or \"warning\" / \"safe\"\n          comment-on-pr: true\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          # Optional: verify baseline signature before diffing\n          verify-signature: true\n          signature-key: ${{ secrets.MCP_PUBLIC_KEY }}\n```\n\n**Outputs:** `has-changes`, `has-breaking`, `summary`, `exit-code` — use them in subsequent steps.\n\n### CLI in CI\n\nUse `mcpdiff ci` directly in any CI system:\n\n```yaml\n# .github/workflows/mcp-contract.yml\nname: MCP Contract Check\non: [pull_request]\njobs:\n  check:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - run: npm install -g @mcp-contracts/cli\n      - run: mcpdiff ci --baseline contracts/baseline.mcpc.json --command \"node dist/index.js\"\n\n      # Or with signature verification\n      - run: \u003e\n          mcpdiff ci\n          --baseline contracts/baseline.mcpc.json\n          --command \"node dist/index.js\"\n          --verify-signature\n          --signature-key ./public.pem\n```\n\nThe `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.\n\n## Packages\n\n| Package | Description |\n|---------|-------------|\n| [`@mcp-contracts/core`](./packages/core) | Snapshot types, diff engine, classification logic |\n| [`@mcp-contracts/cli`](./packages/cli) | The `mcpdiff` CLI tool |\n\n---\n\n*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.*\n\n## License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcp-contracts%2Fmcp-contracts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmcp-contracts%2Fmcp-contracts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcp-contracts%2Fmcp-contracts/lists"}