api-contract-qa
Reads contract files from Git refs such as origin/main:openapi.yaml or origin/main:proto/orders.proto, allowing pull-request specs to be compared against a base branch, including imports from the same ref.
Integrates with GitHub Actions through contract-ci: writes contract-report.md and contract-report.json, sets outputs such as verdict, breaking, consumers_affected, needs_human, and report, supports configurable fail-on thresholds, and can comment on pull requests with affected consumers and reasons.
Supports GraphQL SDL and introspection JSON contracts, including GraphQL-specific breaking-change rules, deployed introspection drift checks, and parsing consumer GraphQL queries to identify the exact fields read.
Generates REST contract tests for pytest + httpx, covering status codes and JSON schema validation against the spec, and writes generated files under tests/.
Supports Swagger 2.0 API contracts by auto-detecting the format and converting it to OpenAPI 3 on load, then applying the same diff, consumer-impact, drift, conformance, and test-generation workflows.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@api-contract-qa check if my order-service API change breaks any consumers"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
k11 API Contract QA — MCP server & Claude Code plugin
Know which services an API change breaks before you merge it, and why. REST, GraphQL, gRPC, events and SOAP.
A pull request renames a field or tightens a request body. Its own tests pass. Three other services break in production. Spec-diff tools can tell you a change is "breaking", but not who it breaks, so teams either ignore the warnings or block every change. This MCP server answers the real question:
Breaking-change detection for OpenAPI 3.x, Swagger 2.0, GraphQL, gRPC/protobuf, AsyncAPI 2.x/3.x and SOAP/WSDL 1.1, including
$refs, nested fields and array items, with the rule each change broke.Consumer-aware impact. It knows which services call which endpoints, and which fields they read or send. A removed field only counts against the consumers that use it.
A verdict with evidence: breaking, breaking but no known consumer uses it, or compatible. When 2 or more consumers break, or a critical one does, it says a person should decide before merge.
Deployed-contract drift: compares what a running service publishes (GraphQL introspection,
?wsdl,/v3/api-docs) with your spec file.Live conformance checks for REST: status codes, content type and the JSON body validated against the schema.
Consumer discovery that scans a consumer's source code (Python, Java, TypeScript, Go, …) for calls to your API, with file and line. For GraphQL it parses the consumer's actual queries, so it knows exactly which fields they read.
Contract test generation for pytest + httpx or Java REST Assured.
contract-ci: a pull-request comment that lists every affected consumer and the reason.
Deterministic rules, no LLM calls, the same result every run. Works with Claude Code (as a plugin with /check-api-change and /api-contract-tests), Claude Desktop and any MCP client. Listed in the official MCP Registry as io.github.K11-Software-Solutions/api-contract-qa.
See it in a pull request
In the demo, Order Service v2 changes total from a number to a string, drops customer.email, adds a required channel to POST /orders and removes DELETE /orders/{id}. Four services consume it. contract-ci posted:
Related MCP server: swagger-mcp
API contract check: 🔴 Breaking for known consumers
Order Service:
main→ this PR. 11 changes, 6 breaking (worst: critical); 4 known consumers, 3 affected.Needs a person before merge: 3 consumers break (threshold 2); high-criticality consumers break: notification-svc, billing-svc, checkout-web.
Consumer
Owner
Criticality
Breaking change
Why it affects them
billing-svc
@team-billing
critical
GET /orders/{id}: Response field 'total' changed type from number to stringreads 'total'
checkout-web
@team-web
high
POST /orders: New required request field 'channel'doesn't send the now-required 'channel'
notification-svc
@team-notify
high
GET /orders/{id}: Response field 'customer.email' was removedreads 'customer.email'
Breaking, no known consumer:
DELETE /orders/{orderId}was removed, plus two response changes onPOST /ordersthat checkout-web doesn't read.
analytics-svc calls GET /orders too, but it reads only id and status, so it isn't flagged.
Supported contracts
The format is detected automatically from the file. Every format goes through the same rules, consumer impact, report and contract-ci, plus rules specific to it.
Format | Operations are named | Format-specific rules | Deployed drift check |
OpenAPI 3.x |
| parameters, request bodies, success responses, auth |
|
Swagger 2.0 |
| converted to OpenAPI 3 on load (body/formData, definitions, basePath) |
|
GraphQL (SDL or introspection JSON) |
| removing any argument breaks (unknown arguments are errors); non-null → nullable breaks readers | introspection query |
gRPC / protobuf ( |
| field number changed or reused, field renamed (wire-safe but breaks JSON and generated code), removed numbers not reserved, streaming changed, message replaced | not yet (needs server reflection) |
AsyncAPI 2.x / 3.x |
| emitted messages follow reader rules; received messages follow writer rules |
|
SOAP / WSDL 1.1 |
| XSD |
|
Consumer discovery finds HTTP paths, GraphQL query documents (exact fields read), gRPC stub calls, SOAP client calls (zeep, JAX-WS, .NET) and AsyncAPI topic names. Live response checks and test generation are for REST (OpenAPI and Swagger).
Tools
Tool | What it does |
| Lists a contract's operations and its detected format. |
| Classifies every change between two versions of a contract: rule, field path, before/after, severity. |
| Which consumers a change breaks and why; the verdict and whether a person should decide. Optionally writes the report. |
| Finds a consumer's calls to your API in its source code and drafts its |
| Compares what a running service publishes with the spec: |
| Calls a running REST endpoint and checks the response against the spec. Header values can use |
| REST contract tests (status + JSON schema) for pytest + httpx or REST Assured. |
| Writes generated files under |
Specs are files in the project or git refs: origin/main:openapi.yaml, origin/main:proto/orders.proto (imports are read from the same ref).
Tell it who your consumers are
.qa-mcp/consumers.yaml:
consumers:
- name: billing-svc
repo: acme/billing-svc
owner: "@team-billing"
criticality: critical # critical | high | medium | low
uses:
- endpoint: GET /orders/{id}
reads: [id, total, currency] # leave out to mean "any field"
- name: checkout-web
owner: "@team-web"
criticality: high
uses:
- endpoint: POST /orders
sends: [customerId, items]
reads: [id]Endpoints use the operation names from the table above (QUERY order, RPC shop.v1.OrderService/GetOrder, EMITS order.created, …). Field lists are what make the verdict precise. Without them, any breaking change on an endpoint counts against everyone who calls it. Start with discover_consumer_usage on each consumer's code, then add the fields.
In CI
k11-api-contract-qa-mcp contract-ci --spec openapi.yaml --base origin/mainIt compares the spec in the pull request with origin/main, writes contract-report.md (the PR comment) and contract-report.json, sets GitHub Actions outputs (verdict, breaking, consumers_affected, needs_human, report) and exits non-zero according to --fail-on:
| Fails when |
| a known consumer breaks |
| 2+ consumers or a critical/high one break |
| any breaking change, used or not |
| report only |
Copy docs/contract-check.yml to .github/workflows/ to comment on every pull request that touches the spec.
Install
Requires Python 3.10+.
Claude Code: plugin (recommended)
Needs uv:
/plugin marketplace add K11-Software-Solutions/k11techlab-api-contract-qa-mcp
/plugin install api-contract-qa@k11-api-contract-qaClaude Code: MCP server only
claude mcp add api-contract-qa -- uvx k11-api-contract-qa-mcpClaude Desktop and other MCP clients
{
"mcpServers": {
"api-contract-qa": {
"command": "uvx",
"args": ["k11-api-contract-qa-mcp"],
"env": { "QA_MCP_ROOT": "/path/to/your/service" }
}
}
}Or pip install k11-api-contract-qa-mcp.
Try the demo
cd demo/order-service
k11-api-contract-qa-mcp contract-ci --spec openapi.yaml --base-spec openapi.v1.yaml
python server.py --port 8080 # v2 implementation with one deliberate contract bugThen ask Claude to check_live_conformance on GET /orders/{id} with id 1001. It finds that total is still sent as a number.
demo/formats/ has a v1 and v2 contract for each other format (Swagger 2.0, GraphQL, protobuf with an import, AsyncAPI 2.x → 3.x, WSDL) and a small consumer for each, for example:
k11-api-contract-qa-mcp contract-ci --spec demo/formats/graphql/schema.graphql --base-spec demo/formats/graphql/schema.v1.graphql --fail-on neverRules
These apply to every format (with each format's names for inputs and outputs):
Rule | Breaking? |
Endpoint removed | yes (critical) |
Response field removed, type changed, became nullable, no longer guaranteed | yes |
Success response or JSON media type removed | yes |
New required request field / parameter, field or parameter became required | yes |
Request enum value removed, request field newly restricted to an enum | yes |
New authentication requirement | yes (critical) |
Required request field removed (any removed input for GraphQL and SOAP) | yes |
New endpoint, optional field or parameter; response enum value added | no (enum additions flagged for exhaustive switches) |
Path parameter renamed, endpoint deprecated | no |
protobuf: field number changed, message replaced, streaming changed | yes |
protobuf: field renamed with the same number | yes (medium: wire-safe, breaks JSON and generated code) |
The rules extend the K11 research on cross-repository contract testing and change impact analysis (IJECS, 2026), whose reference system is k11techlab-microservice-qa-system. This server adds $ref, nested and array-item rules and field-level consumer matching.
How it compares
Spec diff tools (e.g. oasdiff) | Consumer-driven contracts (e.g. Pact) | k11 API Contract QA | |
Knows who breaks | No | Yes | Yes, field-level |
Setup per consumer | None | Contract tests in every consumer | One YAML entry; discovery drafts it |
Explains why | Rule only | Failing interaction | Rule, field, and what the consumer reads or sends |
Formats | Usually one | HTTP and messages | OpenAPI, Swagger, GraphQL, gRPC, AsyncAPI, SOAP |
Usable by an AI agent | No | No | Yes, over MCP |
Safety
Specs, consumer folders and reports must be inside the project folder; git refs are read with
git show, never a shell.write_testwrites only undertests/orsrc/test/, and won't overwrite without asking.Tokens for live checks are read from the environment (
${ENV:NAME}) and never echoed.
Development
python -m venv .venv && .venv/Scripts/pip install -e ".[dev]" # bin/pip on macOS/Linux
pytest # rules for all formats, consumer impact, discovery, drift, conformance, generated tests, contract-ci, MCP (38)Roadmap
Transitive impact (a consumer that re-exposes the data to its own consumers)
Live gRPC checks through server reflection; WSDL 2.0; GraphQL federation
Optional LLM review for "uncertain" cases, as in the research system
Built by K11 Software Solutions. Part of the K11 Tech Lab agentic QA series, alongside Playwright QA, Selenium QA and LLM Assure. MIT licensed.
Available Tools
8 toolsassess_impactAssess impact on consumersA
Which known consumers a spec change breaks, and why (field-level when consumers list the fields they read/send). Verdict: breaking | breaking_no_known_consumers | compatible; needs_human when 2+ consumers or a high-criticality consumer break. Consumers come from .qa-mcp/consumers.yaml.
Inputs: base_spec (required), head_spec (required), write_report, consumers_file.
check_deployed_contractCheck deployed contractA
Compare what a running service publishes with the spec file: GraphQL introspection (url = the GraphQL endpoint), a WSDL URL (e.g. http://host/orders?wsdl), or a published OpenAPI/Swagger/AsyncAPI document (e.g. http://host/v3/api-docs). Verdict: matches | drift | incompatible. gRPC is not supported (needs reflection). Header values may use ${ENV:NAME}.
Inputs: url (required), spec (required), headers.
check_live_conformanceCheck live conformanceB
Call a running endpoint (e.g. endpoint='GET /orders/{id}', path_params={'id': '1001'}) and check status, content type and the JSON body against the spec's response schema. Header values may use ${ENV:NAME}.
Inputs: spec (required), base_url (required), endpoint (required), body, +3 more.
diff_contractsDiff contractsA
Compare two versions of a contract (any supported format) and classify every change as breaking or compatible, with the rule, field path, before/after and severity. Example: base_spec='origin/main:openapi.yaml', head_spec='openapi.yaml'.
Inputs: base_spec (required), head_spec (required), breaking_only.
discover_consumer_usageDiscover consumer usageC
Scan a consumer service's source code (inside the project) for calls to the provider, with file and line as evidence, and draft its consumers.yaml entry. HTTP paths, GraphQL query documents (exact fields read), gRPC stub calls, SOAP client calls, and AsyncAPI topic names.
Inputs: spec (required), consumer_dir (required), consumer_name.
generate_api_testsGenerate API testsA
Generate contract tests (status + JSON schema) for some or all endpoints: pytest + httpx, or Java REST Assured (JUnit 5). Returns the files; write them with write_test.
Inputs: spec (required), endpoints, framework, java_package.
list_operationsList operationsA
List the operations in a contract (OpenAPI, Swagger, GraphQL, .proto, AsyncAPI or WSDL; a project path or :). Also tells you the detected format.
Inputs: spec (required).
write_testWrite test fileB
Write a generated file under tests/ or src/test/ only. Won't overwrite unless asked.
Inputs: path (required), content (required), overwrite.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Each tool has a distinct role in a logical pipeline: list, diff, assess, discover, check live, check deployed, generate, write. The only pair with surface overlap is check_live_conformance vs check_deployed_contract, but the descriptions clearly separate request/response validation from pulling a published contract document, so misselection risk is low.
All eight names are snake_case verb_noun (list_operations, diff_contracts, assess_impact, discover_consumer_usage, check_live_conformance, check_deployed_contract, generate_api_tests, write_test). The two check_* tools even form a clean parallel pair.
Eight tools is well within the ideal 3-15 range and each maps to a concrete step in contract QA rather than padding. Generation and file writing are sensibly split rather than merged into one overloaded tool.
Coverage spans the full lifecycle: inspect, diff, impact, discover consumers, validate live and deployed, generate and write tests. Minor gaps: discover_consumer_usage only drafts a consumers.yaml entry with no tool to persist or manage entries, and gRPC conformance is explicitly unsupported, but agents can work around both.
Maintenance
Related MCP Connectors
Schema-aware API monitoring: diff OpenAPI specs for breaking changes, manage endpoints.
Detect breaking changes, generate changelogs, diff, and validate OpenAPI specs.
End-to-end API testing — generate and run tests from OpenAPI, curl, Postman, or real user traffic.
Monitor MCP servers, API contracts and AI outputs for schema drift. Alerts on breaking changes.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to browse, read, compare, and validate OpenAPI contracts for providers and consumers.1MIT
- AlicenseBqualityDmaintenanceEnables natural language exploration of OpenAPI/Swagger specs, allowing users to register APIs, browse endpoints, describe schemas, and detect breaking changes through conversational queries.9230 npmMIT
- AlicenseAqualityDmaintenanceEnables AI clients to validate OpenAPI specs, compare versions, detect breaking changes, and generate changelogs.4MIT
- AlicenseAqualityCmaintenanceEnables AI agents to call real API endpoints and verify responses against OpenAPI specs, supporting contract testing, auth presets, spec diffing, and health checks.854 npmMIT