Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Apidiff

БесплатноНе проверен

Breaking-change detector for OpenAPI / GraphQL across commits

GitHubEmbed

Описание

Breaking-change detector for OpenAPI / GraphQL across commits

README

APIDIFF

APIDIFF

Breaking-change detector for OpenAPI / GraphQL across commits

PyPI CI Ports License: COCL 1.0 Suite

Developer Tools — fast, single-purpose, CI- and agent-friendly.

pip install cognis-apidiff
apidiff diff openapi.old.json openapi.new.json   # → classified changes in milliseconds

apidiff compares two versions of an API definition and tells you, with a clear severity (BREAKING / WARNING / INFO), exactly what changed and whether it will break existing consumers. Point it at the baseline and the candidate in your CI pipeline and it fails the build before a breaking change ships. It is dependency-free, offline, and read-only — it diffs two files; it never calls your API and never touches the network.

🔎 Example output

Real, reproducible output from the tool — runs offline:

$ apidiff-emit --version
apidiff 0.6.0
$ apidiff-emit --help
usage: apidiff [-h] [--version] {diff,mcp} ...

Breaking-change detector for OpenAPI / GraphQL across commits.

positional arguments:
  {diff,mcp}
    diff      Diff two API definitions
    mcp       Run the MCP stdio server (requires the 'mcp' extra)

options:
  -h, --help  show this help message and exit
  --version   show program's version number and exit

Blocks above are real apidiff output — reproduce them from a clone.

Sample result format (illustrative values — run on your own data for real findings):

{
"findings": [
    {
        "id": "123456",
        "title": "Suspicious Network Traffic",
        "description": "Potential malicious activity detected on port 443",
        "severity": "medium",
        "labels": ["network", "traffic"],
        "created_at": "2023-02-15T14:30:00Z"
    },
    {
        "id": "789012",
        "title": "Unusual File Access",
        "description": "User accessed a file with unusual permissions",
        "severity": "high",
        "labels": ["file", "access"],
        "created_at": "2023-02-15T14:31:00Z"
    }
]
}

Usage — step by step

apidiff detects breaking changes between two OpenAPI / GraphQL definitions.

  1. Install (either way works today):
    pip install cognis-apidiff                                       # PyPI
    pip install "git+https://github.com/cognis-digital/apidiff.git"  # from source
    
  2. Diff a baseline against a candidate definition:
    apidiff diff openapi.old.json openapi.new.json
    
  3. Force the format when auto-detection is ambiguous:
    apidiff diff schema.old.graphql schema.new.graphql --fmt graphql
    
  4. Read the output as JSON for tooling, or SARIF for code scanning:
    apidiff diff openapi.old.json openapi.new.json --format json
    apidiff diff openapi.old.json openapi.new.json --format sarif
    
  5. Automate in CI--fail-on controls when the diff returns a non-zero exit:
    apidiff diff openapi.old.json openapi.new.json --fail-on breaking
    

Input formats. OpenAPI documents are read as JSON (OpenAPI 3.x or Swagger 2.0). If your spec is YAML, convert it first — e.g. python -c "import sys,yaml,json; json.dump(yaml.safe_load(open(sys.argv[1])), open(sys.argv[2],'w'))" openapi.yaml openapi.json — then diff the JSON. GraphQL is read as SDL text (.graphql).

Contents

Why apidiff?

A renamed field, a newly-required parameter, a dropped 2xx response — small diffs that silently break every client of your API. Code review rarely catches them; integration tests catch them late. apidiff makes the contract itself the gate.

apidiff is single-purpose, scriptable, and self-hostable: point it at a baseline + candidate, get prioritized results in the format your workflow already speaks (table · JSON · SARIF), gate CI on it, and let agents drive it over MCP.

Features

  • ✅ Detects breaking changes in OpenAPI 3.x / Swagger 2.0 (JSON) and GraphQL SDL
  • ✅ Severity model: BREAKING / WARNING / INFO with stable change codes (path.removed, param.added.required, response.property.removed, enum.value.removed, …)
  • ✅ Output as table · JSON · SARIF 2.1.0 (GitHub code scanning)
  • ✅ CI gate via exit codes + --fail-on breaking|warning|never
  • Zero runtime dependencies — Python standard library only
  • Offline & read-only — diffs two files; no network, no live API access
  • ✅ Runs on Linux / macOS / Windows · Docker · devcontainer
  • MCP server (apidiff mcp) so AI agents can drive it
  • ✅ Verified polyglot ports in JavaScript, Go, and Rust (ports/)

Quick start

pip install cognis-apidiff
apidiff --version
apidiff diff openapi.old.json openapi.new.json                     # human table
apidiff diff openapi.old.json openapi.new.json --format json       # machine-readable
apidiff diff openapi.old.json openapi.new.json --format sarif      # code-scanning
apidiff diff openapi.old.json openapi.new.json --fail-on breaking  # CI gate
apidiff diff schema.old.graphql schema.new.graphql --fmt graphql   # GraphQL SDL

What counts as breaking

apidiff classifies each change by who it hurts. A change is BREAKING when it can break an existing consumer; WARNING when it is risky but tolerable; and INFO when it is purely additive.

Change OpenAPI GraphQL Severity
Endpoint / type removed path.removed, operation.removed type.removed 🔴 BREAKING
Field a client reads removed response.property.removed field.removed 🔴 BREAKING
New required input param.added.required, requestBody.required.added input.field.added.required, arg.added.required 🔴 BREAKING
Existing input made required param.required.added arg.required.added 🔴 BREAKING
Type narrowed / changed *.property.type.changed field.type.changed 🔴 BREAKING
Success (2xx) response dropped response.removed 🔴 BREAKING
Enum value removed enum.value.removed 🔴 BREAKING
Optional input / parameter removed param.removed arg.type.changed 🟡 WARNING
Enum value added enum.value.added 🟡 WARNING
New optional field / endpoint / type path.added, param.added, *.property.added field.added, arg.added, type.added 🟢 INFO

GraphQL nullability is direction-aware: loosening an output field (String!String) breaks readers, while tightening an input field (StringString!) breaks callers. apidiff scores each correctly.

Example

$ apidiff diff demos/01-basic/openapi.old.json demos/01-basic/openapi.new.json
format: openapi
changes: 4  breaking: 3  warning: 0  info: 1

  [BREAKING] DELETE /pets/{petId}  Operation 'DELETE /pets/{petId}' was removed
  [BREAKING] GET /pets             New required parameter 'tenant' (in: query) added
  [BREAKING] GET /pets             response property 'tag' was removed
  [INFO    ] /pets/{petId}/notes   Path '/pets/{petId}/notes' was added

The same diff as machine-readable JSON:

$ apidiff diff demos/01-basic/openapi.old.json demos/01-basic/openapi.new.json --format json
{
  "format": "openapi",
  "summary": { "total": 4, "breaking": 3, "warning": 0, "info": 1 },
  "changes": [
    { "severity": "BREAKING", "code": "operation.removed",
      "location": "DELETE /pets/{petId}", "message": "Operation 'DELETE /pets/{petId}' was removed" },
    { "severity": "BREAKING", "code": "param.added.required",
      "location": "GET /pets", "message": "New required parameter 'tenant' (in: query) added" },
    { "severity": "BREAKING", "code": "response.property.removed",
      "location": "GET /pets", "message": "response property 'tag' was removed" },
    { "severity": "INFO", "code": "path.added",
      "location": "/pets/{petId}/notes", "message": "Path '/pets/{petId}/notes' was added" }
  ]
}

The process exits 1 when breaking changes are found, so the CI step fails before the change ships.

Demos — real-world scenarios

Each folder under demos/ is a self-contained, runnable scenario: a baseline + candidate definition in apidiff's real input format, plus a SCENARIO.md describing where the data came from, what to expect, the exact command, and how to act. Every demo is verified by the test suite.

Demo Format What it shows
01-basic OpenAPI Removed op + new required param + dropped response field
02-graphql-schema GraphQL Field removals across a release
03-safe-evolution OpenAPI Purely additive release → green build (exit 0)
04-graphql-required-input GraphQL New required input field & argument
05-response-shape-change OpenAPI Response property type change + dropped field
06-status-code-dropped OpenAPI Removed 206 + removed query param (mixed severity)
07-sarif-codescanning OpenAPI --format sarif for GitHub code scanning
08-graphql-enum-and-args GraphQL Enum churn + argument made required
09-request-body-tightening OpenAPI Request-body field becomes required
10-multitenant-rollout OpenAPI Big mixed PR: breaking + additive across many paths
# run any demo
python -m apidiff diff demos/02-graphql-schema/schema.old.graphql \
                       demos/02-graphql-schema/schema.new.graphql

Architecture

flowchart LR
  OLD[old definition] --> D[detect format]
  NEW[new definition] --> D
  D -->|openapi| OA[OpenAPI diff]
  D -->|graphql| GQ[GraphQL SDL diff]
  OA --> R[classify BREAKING / WARNING / INFO]
  GQ --> R
  R --> T[table]
  R --> J[JSON]
  R --> S[SARIF 2.1.0]

The engine is one module (apidiff/core.py): a format detector, two diff walkers (OpenAPI JSON, GraphQL SDL via a stdlib subset parser), a severity classifier, and three renderers. No plugins, no config files, no I/O beyond reading the two files you name.

Use it from any AI stack

apidiff is interoperable with every popular way of using AI:

  • MCP serverapidiff mcp exposes an apidiff_diff(old_path, new_path, fmt) tool to Claude Desktop, Cursor, Cognis.Studio, and the uncensored-fleet (needs the mcp extra: pip install "cognis-apidiff[mcp]")
  • OpenAI-compatible / JSON — pipe apidiff diff old new --format json into any agent or LLM
  • LangChain · CrewAI · AutoGen · LlamaIndex — wrap the CLI/JSON as a tool in one line
  • CI / scripts — exit codes + SARIF for non-AI pipelines

Polyglot ports — same engine, four languages

Drop apidiff into any stack or ship a single static binary. Each port in ports/ mirrors the reference CLI (diff OLD NEW [--format table|json]), emits the same change codes and the same exit-code contract (1 on breaking, 0 clean, 2 on error), and has its own smoke test wired into the ports.yml CI workflow. The JavaScript port is byte-for-byte verified against the Python reference across every OpenAPI demo.

Language Run Test
Python (reference) apidiff diff old.json new.json python -m pytest
JavaScript / Node node ports/javascript/index.js diff old.json new.json node --test ports/javascript/test.js
Go cd ports/go && go run . diff old.json new.json go test ./...
Rust (zero crates) cd ports/rust && cargo run -- diff old.json new.json cargo test

How it compares

Cognis apidiff oasdiff
Self-hostable, no account varies
Single command, zero config ⚠️
JSON + SARIF for CI varies
MCP-native (AI agents)
Polyglot ports (JS/Go/Rust)
Open license ✅ COCL varies

Built in the spirit of oasdiff, re-framed the Cognis way. Missing a credit? Open a PR.

Integrations

Pipes into your stack: SARIF for code-scanning, JSON for anything, an MCP server (apidiff mcp) for AI agents, and an apidiff-emit forwarder that maps findings onto STIX / MISP / Sigma / Splunk / Elastic / Slack / webhook via cognis-connect. See docs/INTEGRATIONS.md.

# forward a diff to Slack (dry-run shown; cognis-connect is an optional extra)
apidiff diff old.json new.json --format json | apidiff-emit --to slack --url "$WEBHOOK" --dry-run

Install — every way, every platform

pip install "git+https://github.com/cognis-digital/apidiff.git"     # pip (works today)
pipx install "git+https://github.com/cognis-digital/apidiff.git"    # isolated CLI
uv tool install "git+https://github.com/cognis-digital/apidiff.git" # uv
pip install cognis-apidiff                                          # PyPI (when published)
docker run --rm ghcr.io/cognis-digital/apidiff:latest --help        # Docker
brew install cognis-digital/tap/apidiff                             # Homebrew tap
curl -fsSL https://raw.githubusercontent.com/cognis-digital/apidiff/main/install.sh | sh
Linux macOS Windows Docker Cloud
scripts/setup-linux.sh scripts/setup-macos.sh scripts/setup-windows.ps1 docker run ghcr.io/cognis-digital/apidiff DEPLOY.md (AWS/Azure/GCP/k8s)

Edge / air-gap

apidiff has zero runtime dependencies and makes no network calls — it only reads the two files you hand it. That makes it ideal for air-gapped CI: clone once (or vendor the single apidiff/ package), and it runs anywhere Python 3.10+ is present. The Go and Rust ports compile to a single static binary with no third-party crates/modules, so you can drop one executable into a locked-down runner with no package manager at all.

Scope & safety

  • Passive and read-only. apidiff opens two local definition files and compares them. It does not call any API, send traffic, or perform active scanning of any kind.
  • No network. The core has no network code path; it runs fully offline. (The optional apidiff-emit forwarder can POST findings to a SIEM/Slack webhook you configure, and supports --dry-run; this is opt-in and never runs during a diff.)
  • Defensive use. apidiff is a developer/CI quality gate. Use it on API contracts you own or are authorized to review.
  • Deterministic. Same inputs → same output. No fabricated data, no external state.

Related Cognis tools

  • mcpforge — Scaffold, test, and publish MCP servers in minutes
  • promptlint — Lint, version, and test prompts as code with a CI gate
  • envdoctor — .env validator, secret-presence and config-drift checker
  • codeglance — Repo onboarding map — architecture + hotspots for humans and agents
  • flakefinder — Flaky-test detector from CI history with quarantine suggestions
  • licenselens — Dependency license + SBOM gate, developer-CLI first

Explore the suite → 🗂️ all 170+ tools · ⭐ awesome-cognis · 🔗 cognis-sources · 🤖 uncensored-fleet · 🧠 engram

Contributing

PRs, new rules, and demo scenarios are welcome under the collaboration-pull model — see CONTRIBUTING.md and SECURITY.md. New language ports should add a smoke test wired into ports.yml and verify against the OpenAPI demos.

⭐ If apidiff saved you time, star it — it genuinely helps others find it.

Interoperability

apidiff composes with the 300+ tool Cognis suite — JSON in/out and a shared OpenAI-compatible /v1 backbone. See INTEROP.md for the suite map, composition patterns, and reference stacks.

License

Source-available under the Cognis Open Collaboration License (COCL) v1.0 — free for personal, internal-evaluation, research, and educational use; commercial / production use requires a license ([email protected]). See LICENSE.


Cognis Digital · one of 170+ tools in the Cognis Neural Suite · Making Tomorrow Better Today

from github.com/cognis-digital/apidiff

Установка Apidiff

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/cognis-digital/apidiff

FAQ

Apidiff MCP бесплатный?

Да, Apidiff MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Apidiff?

Нет, Apidiff работает без API-ключей и переменных окружения.

Apidiff — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Apidiff в Claude Desktop, Claude Code или Cursor?

Открой Apidiff на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Apidiff with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development