Metadata-Version: 2.4
Name: mujin-mcpdrift
Version: 0.1.0
Summary: Catch silent MCP server schema/contract drift in CI: snapshot tools/list, then fail the build when a change breaks the contract.
Project-URL: Homepage, https://github.com/mujinlabs/mcpdrift
Project-URL: Issues, https://github.com/mujinlabs/mcpdrift/issues
Author: Mujin Labs
License: MIT
License-File: LICENSE
Keywords: ai-agents,ci,contract-testing,drift,mcp,model-context-protocol,schema
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# mcpdrift

**Catch silent MCP server contract drift in CI.** Snapshot your server's `tools/list`,
commit the baseline, and fail the build when a change breaks the contract — a tool
removed or renamed, a parameter newly required or retyped.

MCP servers are young, fast-moving, and [mostly have no tests](https://rapidclaw.dev/blog/mcp-servers-dead-what-it-means-2026)
(one audit found 52% of servers broken, the median with **zero** CI tests). A refactor
quietly renames a tool or makes a param required, and every agent depending on it breaks —
with no version bump and no warning. mcpdrift is the missing contract test.

```bash
pipx install mujin-mcpdrift

mcpdrift snapshot   # record current tools/list as the baseline (commit it)
mcpdrift check      # exit 1 if the contract broke
```

```
myserver: 3 change(s):
  BREAKING  tool 'echo' was removed
  info      tool 'ping' was added
  info      param 'limit' added to 'search'
  -> breaking changes. If intentional, re-run `mcpdrift snapshot myserver` and bump your version.
```

## How it works

mcpdrift launches your server over stdio, completes the MCP handshake, reads `tools/list`,
and reduces it to the part that's actually a **contract**: which tools exist, and each
tool's parameter names, types, and required-ness. It diffs that against the committed
baseline (`.mcpdrift/<server>.json`) and classifies every change:

| Breaking (fails CI) | Informational (passes) |
|---|---|
| tool removed | tool added |
| parameter removed | optional parameter added |
| parameter now required | parameter now optional |
| parameter type changed | description changed |

When a change is intentional, re-run `snapshot` to bless it (and bump your server's
version) — the baseline diff makes the contract change explicit in code review.

## Configure servers — `.mcpdrift.json`

```json
{
  "servers": {
    "myserver": { "command": ["python", "server.py"] },
    "everything": { "command": ["npx", "-y", "@modelcontextprotocol/server-everything"] }
  }
}
```

Or run ad-hoc without a config:

```bash
mcpdrift snapshot myserver --command "python server.py" --env API_KEY=xxx
mcpdrift check    myserver --command "python server.py" --env API_KEY=xxx
```

## CI gate

```yaml
# .github/workflows/mcp-contract.yml
jobs:
  mcpdrift:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: "3.11" }
      - run: pipx install mujin-mcpdrift
      - run: mcpdrift check     # fails if a PR breaks the tool contract
```

Zero dependencies, stdio transport. `--json` for machine output.

## Part of a set

- [**agentaudit**](https://github.com/mujinlabs/agentaudit) — audit MCP servers / skills / plugins for security & quality.
- [**agentsync**](https://github.com/mujinlabs/agentsync) — keep agent config files in sync.
- [**skillbudget**](https://github.com/mujinlabs/skillbudget) — budget your always-loaded context tokens.

agentaudit checks your MCP server is *safe*; mcpdrift checks it didn't silently *change its contract*.

---

Built by **[Mujin Labs](https://github.com/mujinlabs)** — tooling for the autonomous-agent era. MIT.
