Observed since 20 Oct, 22:17 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Static linter that checks whether an OpenAPI spec is safe and clear enough to expose as MCP/AI-agent tools.
English | 한국어
An OpenAPI spec being machine-readable does not make it agent-ready.
agenticlint is a static linter that checks whether an OpenAPI/Swagger document is
safe and clear enough to expose as MCP / AI-agent tools — before you convert it.
It flags ambiguous names, unclassified risk, missing approval policy, data-exfiltration
surfaces, and tool-poisoning vectors. No LLM in the judgment path: every finding is
deterministic and reproducible, so it works as a CI gate.
Docs: English guide · 한국어 가이드 · Rule reference
pip install "agenticlint[cli]" # library + full CLI
pip install agenticlint # library only (a minimal built-in CLI still works)
pipx run agenticlint scan openapi.yaml
Not yet published to PyPI; until then install from source:
pip install -e ".[cli]".
agenticlint scan openapi.yaml
agenticlint scan https://api.example.com/openapi.json
agenticlint scan openapi.yaml --fail-on high --format markdown --output report.md
agenticlint baseline openapi.yaml # freeze the legacy backlog
agenticlint scan openapi.yaml --baseline .agenticlint-baseline.json # only NEW findings fail
Exit codes: 0 pass · 1 findings at/above --fail-on · 2 load/config error.
Behavior is configurable via ./.agenticlint.yaml (presets, rule on/off, thresholds,
lexicon extension, ignorePaths) — see the guide.
from agenticlint import scan
report = scan("openapi.yaml") # path, http(s) URL, or a parsed dict
print(report.summary())
if not report.passed("high"):
raise SystemExit(1)
report.to_json() # versioned JSON contract — the cross-language interface
report.to_markdown()
- run: pipx run agenticlint scan openapi.yaml --fail-on high
| Family | Concern | Examples |
|---|---|---|
| S structure | fields missing → can't interpret/construct | S007 risky op with no auth |
| A ambiguity | vague names/descriptions → wrong tool/payload | A001 generic id param |
| X cross-op | duplicate / conflicting tools across the spec | X001 near-identical descriptions |
| R risk | HTTP-semantics contradictions, dangerous surfaces | R001 side-effect GET · R003 collection-wide delete |
| P policy | declared x-agent-policy vs observed risk | P001 destructive with no policy |
| I integrity | tool poisoning in descriptions | I001 prompt injection · I002 hidden chars |
| M MCP compat | conversion loss / degradation | M001 invalid tool name · M003 too many tools |
Full judgment logic and the lexicons live in the rule reference; the reasoning for why static analysis can do this is in the "How it works" section of the guide.
OpenAPI (YAML/JSON) → parse ($ref) → IR (tokenized) → risk classifier
→ rule engine (pure functions) → report + exit code
The risk classifier is a weighted signal table (HTTP method baseline + lexical override), not a model. Ambiguity is measured by proxy signals (short descriptions, generic names, near-duplicate descriptions) — the same principle ESLint uses for "bad code". See the guide for what static analysis covers vs. what stays with a human reviewer, and its Evidence & prior art section for the research (Hermes, AutoMCP, MetaTool, Anthropic/OpenAI tool guidance) grounding the rules.
x-agent-policyFindings suggest an OpenAPI vendor extension you attach per operation:
x-agent-policy:
risk: destructive # read | write | destructive | financial | external | privilege
requireConfirmation: true
confirmationMessage: "Cancel order {orderId}? This cannot be undone."
sensitiveData: false
exposeToAgent: true
These map cleanly onto MCP tool annotations (readOnlyHint, destructiveHint, …),
so the same policy drives the eventual MCP conversion.
pip install -e ".[dev]"
pytest
The demo/ specs are the test oracle: shop-api-bad.yaml must reproduce
expected-findings.yaml exactly, and shop-api-good.yaml must produce zero findings
(it embeds false-positive traps). See demo/README.md.
Apache-2.0
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.0 | 10 Jul 2026 | 3 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 22:17 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:2117abee721a68aeaa973df01291a6308452b12609156565b1d410834f0d7a2d