Skip to main content

Contract testing and regression detection for MCP servers.

Project description

mcpact

Contract testing for MCP servers.

CI PyPI License

You build an MCP server. You change something. How do you know the tools still work and the schemas haven't drifted? mcpact gives you a YAML contract, runs it against your running server, and fails CI when something breaks.

Install

pip install mcpact

Requires Python 3.10+.

A minimal contract

# contracts/my-server.yaml
server:
  transport: stdio
  command: python server.py

tools:
  - name: search_files
    description_contains: search
    input_schema:
      required: [query]
      properties:
        query: { type: string }
    assertions:
      - call:
          args: { query: "hello" }
        expect:
          status: success
          max_latency_ms: 1000

Run it:

mcpact run --contract contracts/my-server.yaml
search_files
  ✓ exists
  ✓ description_contains
  ✓ input_schema.required
  ✓ call#1.status [42ms]
  ✓ call#1.max_latency_ms [42ms]

5 checks · 5 passed · 0 failed

Exit code is 0 on success, 1 on any failure, 2 on contract errors.

Detect regressions

Capture the current surface, then compare future runs against it:

mcpact snapshot --contract contracts/my-server.yaml --out .mcpact/baseline.json
mcpact diff     --contract contracts/my-server.yaml --baseline .mcpact/baseline.json
Snapshot diff:
  + get_file_info          (new tool)
  - delete_file            (removed — breaking)
  ✗ search_files
    └─ required removed: limit
    └─ type changed on query: 'string' → 'integer'

diff exits non-zero on breaking changes (removed tools, removed required fields, changed property types) so you can wire it into CI.

Transports

server:
  transport: stdio     # command: python server.py
  transport: http      # url: http://localhost:3000/mcp
  transport: sse       # url: http://localhost:3000/sse

Commands

Command Purpose
mcpact run Run a contract against a server
mcpact watch Re-run the contract on file changes
mcpact snapshot Write the server's tool surface to a JSON file
mcpact diff Compare a live server against a snapshot
mcpact validate Validate a contract file without running it

Reporters for run: console (default), json, junit, html. Output goes to --out when provided, otherwise to stdout.

For a realistic example, see packages/core/examples/notes_server.py and the matching contract contracts/notes.yaml — a tiny notes MCP server exercising list, read, search, and create tools.

GitHub Actions

- run: pip install mcpact
- run: mcpact run --contract contracts/my-server.yaml --reporter junit --out results.xml
- uses: mikepenz/action-junit-report@v4
  if: always()
  with:
    report_paths: results.xml

Python API

import asyncio
from mcpact import build_client, load_contract, run_contract

async def main() -> None:
    contract = load_contract("contracts/my-server.yaml")
    client = build_client(contract.server)
    await client.connect()
    try:
        report = await run_contract(contract, client)
    finally:
        await client.close()
    print(f"{report.passed}/{report.total} passed")

asyncio.run(main())

Contract reference

server:
  transport: stdio | http | sse
  command: <cmd>           # stdio only
  args: [<arg>, ...]       # stdio only
  env: { KEY: value }      # stdio only
  url: <url>               # http/sse only

tools:
  - name: <tool>
    must_exist: true       # default
    description_contains: <str> | [<str>, ...]
    input_schema:
      required: [<field>, ...]
      properties:
        <field>: { type: string|integer|... }
    assertions:
      - call:
          args: { ... }
          timeout_ms: <int>
        expect:
          status: success | error    # default: success
          response_contains: <str> | [<str>, ...]
          max_latency_ms: <int>
          schema: { ... }            # JSON Schema for the response

Status

Pre-1.0. Both packages are functional and tested against a real MCP server. API may still change before 1.0.

Repository layout

packages/core/        Python engine + CLI
packages/sdk-node/    TypeScript SDK
contracts/            Example contracts

Contributing

See CONTRIBUTING.md. Issues and PRs welcome — please open an issue before starting non-trivial work. Security issues: see SECURITY.md.

License

MIT

Project details


Download files

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

Source Distribution

mcpact-0.1.0.tar.gz (18.9 kB view details)

Uploaded Source

Built Distribution

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

mcpact-0.1.0-py3-none-any.whl (22.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mcpact-0.1.0.tar.gz
  • Upload date:
  • Size: 18.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mcpact-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a0ababb1d1f31a38e3f87e9d78f489724834428da6f2af2ed89c2af018ba5eab
MD5 95d5a3b38ec7c07bf2d370ee26bf64de
BLAKE2b-256 da2894fdbeb337f0d0c7193668c128e9de349178de62cab8763d9cbc6590be0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcpact-0.1.0.tar.gz:

Publisher: publish-python.yml on jacquesbagui/mcpact

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: mcpact-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 22.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mcpact-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3d8565bb9cd94662538a34e166e58036c4a318db73385c54d978ef8735785f2c
MD5 9ee84fdc0ea843ad89f3d0ea7a096222
BLAKE2b-256 7a2fbf750c42c4e4c3a6dab36a3a61d686867e2dcf33d167c5d04b236a0ff750

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcpact-0.1.0-py3-none-any.whl:

Publisher: publish-python.yml on jacquesbagui/mcpact

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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