Skip to main content

mcp-pact

PyPI version Python versions License: MIT CI

Consumer-driven contract testing for MCP servers.

Agents declare the tools and arguments they depend on. CI verifies that a server surface still satisfies those contracts before you deploy.

Why

Most MCP tooling snapshots the provider and diffs schemas. That answers “did the server change?”

mcp-pact answers a different question:

If I ship this MCP server change, which agents break?

Install

pip install mcp-pact

Requires Python 3.10+.

Quickstart

1. Write a consumer contract

# contracts/support_agent.yaml
consumer: support-agent
provider: docs-mcp
interactions:
  - tool: search_docs
    arguments: { query: "refund policy", limit: 5 }
    required_arguments: [query]
  - tool: get_doc
    arguments: { doc_id: "POL-12" }
    required_arguments: [doc_id]

2. Snapshot the provider surface

Export your MCP tools/list result to JSON (see examples/provider_v1.json).

3. Verify in CI

# one consumer
mcp-pact verify \
  --contract examples/consumer_support_agent.yaml \
  --provider examples/provider_v1.json

# all consumers before release
mcp-pact can-deploy \
  --provider examples/provider_v1.json \
  --contracts contracts/*.yaml

# schema diff + consumer impact
mcp-pact diff \
  --old examples/provider_v1.json \
  --new examples/provider_v2_breaking.json \
  --contracts examples/consumer_support_agent.yaml

# generate adversarial argument cases from schemas
mcp-pact fuzz --provider examples/provider_v1.json --out fuzz_cases.json

Exit code 1 means at least one consumer would break.

What is checked?

Check Breaking when
Tool presence Consumer tool is missing on the provider
Required args Consumer needs an argument the provider removed
Provider-required args Provider newly requires an argument the consumer never sends
Types Provider input type no longer accepts what the consumer sends
Description-only Classified as routing (agent selection risk); not a hard fail by default

Python API

from mcp_pact import (
    load_consumer_contract,
    load_provider_surface,
    can_i_deploy,
    generate_fuzz_cases,
)

provider = load_provider_surface("provider.json")
contract = load_consumer_contract("agent.yaml")
decision = can_i_deploy(provider, [contract])
assert decision.ok, decision.to_dict()

Pytest plugin

pytest --mcp-provider-surface=provider.json \
       --mcp-consumer-contracts=contracts/a.yaml,contracts/b.yaml
def test_agents_still_compatible(mcp_can_i_deploy):
    assert mcp_can_i_deploy.ok, mcp_can_i_deploy.to_dict()

Comparison

Library Model
mcp-contract, mcp-diff, … Provider snapshot + schema lockfile
mcp-pact Consumer-driven contracts, can-i-deploy, fuzz case generation

Development

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest

Status

Alpha (0.1.0). Offline-first: works on committed JSON/YAML provider surfaces. Live MCP probing is planned.

License

MIT

Metadata

Release files for mcp-pact 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-pact 0.1.0
File Size Uploaded
mcp_pact-0.1.0.tar.gz 13.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-pact 0.1.0
File Interpreter ABI Platform
mcp_pact-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 28.2 kB

Release files / mcp_pact-0.1.0.tar.gz

Download URL mcp_pact-0.1.0.tar.gz
Size 13.1 kB
Tags Source
SHA-256 checksum
How to use checksums
3b58e19a24b7afa22db929cc383601982b1b37ea5e86f02461c41e0d8d8b496e
BLAKE2b-256 checksum
How to use checksums
b074d75ba20103262c5e35d7ea8be75af810638bdf832077c2b4e0d447318119
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.5

Release files / mcp_pact-0.1.0-py3-none-any.whl

Download URL mcp_pact-0.1.0-py3-none-any.whl
Size 15.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
70221312ee1670a8fba10ff089ba86f179953a1db05f9a7aec8953d9fcd05ba8
BLAKE2b-256 checksum
How to use checksums
07d18f3917aa997c2e67da61bdf69254deb5a69f8daa7215518cf52afbdc27ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.5

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page