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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_pact-0.1.0.tar.gz (13.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_pact-0.1.0-py3-none-any.whl (15.1 kB view details)

Uploaded Python 3

File details

Details for the file mcp_pact-0.1.0.tar.gz.

File metadata

  • Download URL: mcp_pact-0.1.0.tar.gz
  • Upload date:
  • Size: 13.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for mcp_pact-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3b58e19a24b7afa22db929cc383601982b1b37ea5e86f02461c41e0d8d8b496e
MD5 b8d57c27c9baadf9b170166d16121db2
BLAKE2b-256 b074d75ba20103262c5e35d7ea8be75af810638bdf832077c2b4e0d447318119

See more details on using hashes here.

File details

Details for the file mcp_pact-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: mcp_pact-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for mcp_pact-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 70221312ee1670a8fba10ff089ba86f179953a1db05f9a7aec8953d9fcd05ba8
MD5 67c8635b427a4d7a5a376884e07574e1
BLAKE2b-256 07d18f3917aa997c2e67da61bdf69254deb5a69f8daa7215518cf52afbdc27ef

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page