openapi-agent-ready 0.4.0__tar.gz → 0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/CHANGELOG.md +10 -0
  2. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/PKG-INFO +32 -32
  3. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/README.md +30 -30
  4. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/pyproject.toml +1 -1
  5. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/src/agent_ready/cli.py +15 -3
  6. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/src/agent_ready/rubric.py +4 -3
  7. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/tests/test_audit.py +7 -0
  8. openapi_agent_ready-0.4.0/openapi.yaml +0 -11890
  9. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/.github/workflows/ci.yml +0 -0
  10. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/.github/workflows/publish.yml +0 -0
  11. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/.gitignore +0 -0
  12. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/CONTRIBUTING.md +0 -0
  13. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/LICENSE +0 -0
  14. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/examples/agent_ready_booking_api.yaml +0 -0
  15. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/examples/sample_booking_api.yaml +0 -0
  16. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/src/agent_ready/__init__.py +0 -0
  17. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/src/agent_ready/auditor.py +0 -0
  18. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/src/agent_ready/baseline.py +0 -0
  19. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/src/agent_ready/mcp_generator.py +0 -0
  20. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/src/agent_ready/report_generator.py +0 -0
  21. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/tests/test_baseline.py +0 -0
  22. {openapi_agent_ready-0.4.0 → openapi_agent_ready-0.4.1}/tests/test_mcp_conformance.py +0 -0
@@ -5,6 +5,16 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.4.1] - 2026-10-24
9
+
10
+ ### Fixed
11
+ - **Swagger 2.0 specs are now rejected (exit 2)** instead of being audited.
12
+ They have `paths`, so they were scored, but auth lives in
13
+ `securityDefinitions`, so a spec with scoped OAuth2 was reported as having no
14
+ security schemes at all.
15
+ - **Progress bar counts operations, not paths.** A spec with 100 paths × 3
16
+ methods (300 operations) previously never showed progress.
17
+
8
18
  ## [0.4.0] - 2026-08-08
9
19
 
10
20
  ### Added
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: openapi-agent-ready
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: Audit any OpenAPI spec for AI-agent and MCP readiness, and generate an MCP server scaffold.
5
5
  Project-URL: Homepage, https://github.com/sfaisal/agent-ready
6
6
  Project-URL: Issues, https://github.com/sfaisal/agent-ready/issues
@@ -64,7 +64,7 @@ Description-Content-Type: text/markdown
64
64
  **Audit any OpenAPI spec for AI-agent readiness — then generate an MCP server scaffold for the endpoints that pass.**
65
65
 
66
66
  Your API works fine for human developers. That doesn't mean an AI agent can use
67
- it reliably. `agent-ready` scores a spec against seven categories of
67
+ it reliably. `agent-ready` scores a spec against eight categories of
68
68
  agent-specific failure, tells you exactly which endpoints will cause trouble and
69
69
  why, and can gate a CI pipeline so specs don't regress.
70
70
 
@@ -75,17 +75,18 @@ agent-ready https://example.com/openapi.yaml
75
75
 
76
76
  ```
77
77
  Generic Booking Platform API (v1.0)
78
- AI-readiness score: 54.4/100
79
- Endpoints: 4 Fails: 6 Warnings: 12
78
+ AI-readiness score: 58.4/100
79
+ Endpoints: 4 Fails: 7 Warnings: 14
80
80
 
81
81
  Category scores:
82
- Description Clarity 37.5/100
83
- Side Effects 70.0/100
84
- Error Responses 62.5/100
85
- Auth Clarity 50.0/100
86
- Ambiguity 100.0/100
87
- Parameter Explanation 16.7/100
88
- Usage Guidelines 50.0/100
82
+ Description Clarity 37.5/100
83
+ Side Effects 70.0/100
84
+ Error Responses 62.5/100
85
+ Auth Clarity 50.0/100
86
+ Ambiguity 100.0/100
87
+ Parameter Explanation 10.0/100
88
+ Usage Guidelines 50.0/100
89
+ Tool Surface 100.0/100
89
90
  ```
90
91
 
91
92
  ## Why this exists
@@ -111,9 +112,8 @@ directly onto the rubric:
111
112
  | **Frictionless authentication** | 4 (auth/scope clarity) |
112
113
  | **Structured error handling** | 3 (actionable errors) |
113
114
 
114
- Categories 2 (side effects) and 5 (ambiguity) were added during implementation
115
- — they turned out to matter as much as the original three, which is the usual
116
- reward for actually building the thing you wrote about.
115
+ Categories 2 (side effects) and 5 (ambiguity) weren't in the article. They came
116
+ up once I started building, and they matter as much as the original three.
117
117
 
118
118
  The gap is measurable, and enormous. A 2026 study of 856 tools across 103 MCP
119
119
  servers found that **97.1% of tool descriptions contained at least one quality
@@ -219,6 +219,19 @@ future release does not invalidate your baseline.
219
219
 
220
220
  As the team fixes the backlog, regenerate the baseline to lock in the progress.
221
221
 
222
+ ### Python API
223
+
224
+ ```python
225
+ from agent_ready import load_spec, run_audit
226
+
227
+ spec = load_spec("openapi.yaml")
228
+ result = run_audit(spec)
229
+
230
+ print(result["overall_score"])
231
+ for finding in result["gaps"]:
232
+ print(finding.severity, finding.endpoint, finding.message)
233
+ ```
234
+
222
235
  ## Real-world results
223
236
 
224
237
  Running it against Stripe's production spec (587 endpoints), as of v0.1.0.
@@ -244,8 +257,8 @@ Two things worth drawing out.
244
257
  in this tool, not in Stripe.** Stripe documents errors via OpenAPI's `default`
245
258
  response rather than enumerating explicit 4xx/5xx codes. Perfectly valid, and
246
259
  arguably cleaner. The check only looked for `4`/`5` prefixes, so it failed all
247
- 587 endpoints. Fixed, regression-tested, and the reason the README says to run
248
- this against a real spec before trusting it.
260
+ 587 endpoints. Fixed and regression-tested — and a good reason to run this
261
+ against your own real spec before trusting the score.
249
262
 
250
263
  **Stripe is widely and correctly regarded as agent-ready, yet its raw OpenAPI
251
264
  spec scores 62.9.** That isn't a contradiction — it's the whole point. Stripe's
@@ -260,19 +273,6 @@ Genuine findings that survived scrutiny: `GET /v1/account` and
260
273
  uses bearer/basic API keys rather than scoped OAuth2, so there's no way to
261
274
  express "this agent may only read."
262
275
 
263
- ### Python API
264
-
265
- ```python
266
- from agent_ready import load_spec, run_audit
267
-
268
- spec = load_spec("openapi.yaml")
269
- result = run_audit(spec)
270
-
271
- print(result["overall_score"])
272
- for finding in result["gaps"]:
273
- print(finding.severity, finding.endpoint, finding.message)
274
- ```
275
-
276
276
  ## The eight categories
277
277
 
278
278
  | # | Category | What it catches | Published anchor |
@@ -336,7 +336,7 @@ doesn't:
336
336
 
337
337
  - **The ambiguity check uses string similarity**, so it misses endpoints that
338
338
  are semantically similar but differently worded. Embedding-based similarity
339
- would be stronger. ([#1](https://github.com/sfaisal/agent-ready/issues))
339
+ would be stronger. ([#1](https://github.com/sfaisal/agent-ready/issues/1))
340
340
  - **Category weights are judgement calls, not measured effect sizes.**
341
341
  Description clarity is weighted highest on the prior that wrong tool selection
342
342
  is the costliest failure — that prior is untested here.
@@ -359,7 +359,7 @@ doesn't:
359
359
  - [ ] LLM-assisted rewriting of flagged descriptions (`--fix`)
360
360
  - [ ] Live tool-selection testing against a generated MCP server
361
361
  - [ ] GitHub Action wrapper
362
- - [ ] Baseline mode (`--baseline`) so CI only fails on *new* regressions
362
+ - [x] Baseline mode (`--baseline`) so CI only fails on *new* regressions
363
363
 
364
364
  ## Contributing
365
365
 
@@ -9,7 +9,7 @@
9
9
  **Audit any OpenAPI spec for AI-agent readiness — then generate an MCP server scaffold for the endpoints that pass.**
10
10
 
11
11
  Your API works fine for human developers. That doesn't mean an AI agent can use
12
- it reliably. `agent-ready` scores a spec against seven categories of
12
+ it reliably. `agent-ready` scores a spec against eight categories of
13
13
  agent-specific failure, tells you exactly which endpoints will cause trouble and
14
14
  why, and can gate a CI pipeline so specs don't regress.
15
15
 
@@ -20,17 +20,18 @@ agent-ready https://example.com/openapi.yaml
20
20
 
21
21
  ```
22
22
  Generic Booking Platform API (v1.0)
23
- AI-readiness score: 54.4/100
24
- Endpoints: 4 Fails: 6 Warnings: 12
23
+ AI-readiness score: 58.4/100
24
+ Endpoints: 4 Fails: 7 Warnings: 14
25
25
 
26
26
  Category scores:
27
- Description Clarity 37.5/100
28
- Side Effects 70.0/100
29
- Error Responses 62.5/100
30
- Auth Clarity 50.0/100
31
- Ambiguity 100.0/100
32
- Parameter Explanation 16.7/100
33
- Usage Guidelines 50.0/100
27
+ Description Clarity 37.5/100
28
+ Side Effects 70.0/100
29
+ Error Responses 62.5/100
30
+ Auth Clarity 50.0/100
31
+ Ambiguity 100.0/100
32
+ Parameter Explanation 10.0/100
33
+ Usage Guidelines 50.0/100
34
+ Tool Surface 100.0/100
34
35
  ```
35
36
 
36
37
  ## Why this exists
@@ -56,9 +57,8 @@ directly onto the rubric:
56
57
  | **Frictionless authentication** | 4 (auth/scope clarity) |
57
58
  | **Structured error handling** | 3 (actionable errors) |
58
59
 
59
- Categories 2 (side effects) and 5 (ambiguity) were added during implementation
60
- — they turned out to matter as much as the original three, which is the usual
61
- reward for actually building the thing you wrote about.
60
+ Categories 2 (side effects) and 5 (ambiguity) weren't in the article. They came
61
+ up once I started building, and they matter as much as the original three.
62
62
 
63
63
  The gap is measurable, and enormous. A 2026 study of 856 tools across 103 MCP
64
64
  servers found that **97.1% of tool descriptions contained at least one quality
@@ -164,6 +164,19 @@ future release does not invalidate your baseline.
164
164
 
165
165
  As the team fixes the backlog, regenerate the baseline to lock in the progress.
166
166
 
167
+ ### Python API
168
+
169
+ ```python
170
+ from agent_ready import load_spec, run_audit
171
+
172
+ spec = load_spec("openapi.yaml")
173
+ result = run_audit(spec)
174
+
175
+ print(result["overall_score"])
176
+ for finding in result["gaps"]:
177
+ print(finding.severity, finding.endpoint, finding.message)
178
+ ```
179
+
167
180
  ## Real-world results
168
181
 
169
182
  Running it against Stripe's production spec (587 endpoints), as of v0.1.0.
@@ -189,8 +202,8 @@ Two things worth drawing out.
189
202
  in this tool, not in Stripe.** Stripe documents errors via OpenAPI's `default`
190
203
  response rather than enumerating explicit 4xx/5xx codes. Perfectly valid, and
191
204
  arguably cleaner. The check only looked for `4`/`5` prefixes, so it failed all
192
- 587 endpoints. Fixed, regression-tested, and the reason the README says to run
193
- this against a real spec before trusting it.
205
+ 587 endpoints. Fixed and regression-tested — and a good reason to run this
206
+ against your own real spec before trusting the score.
194
207
 
195
208
  **Stripe is widely and correctly regarded as agent-ready, yet its raw OpenAPI
196
209
  spec scores 62.9.** That isn't a contradiction — it's the whole point. Stripe's
@@ -205,19 +218,6 @@ Genuine findings that survived scrutiny: `GET /v1/account` and
205
218
  uses bearer/basic API keys rather than scoped OAuth2, so there's no way to
206
219
  express "this agent may only read."
207
220
 
208
- ### Python API
209
-
210
- ```python
211
- from agent_ready import load_spec, run_audit
212
-
213
- spec = load_spec("openapi.yaml")
214
- result = run_audit(spec)
215
-
216
- print(result["overall_score"])
217
- for finding in result["gaps"]:
218
- print(finding.severity, finding.endpoint, finding.message)
219
- ```
220
-
221
221
  ## The eight categories
222
222
 
223
223
  | # | Category | What it catches | Published anchor |
@@ -281,7 +281,7 @@ doesn't:
281
281
 
282
282
  - **The ambiguity check uses string similarity**, so it misses endpoints that
283
283
  are semantically similar but differently worded. Embedding-based similarity
284
- would be stronger. ([#1](https://github.com/sfaisal/agent-ready/issues))
284
+ would be stronger. ([#1](https://github.com/sfaisal/agent-ready/issues/1))
285
285
  - **Category weights are judgement calls, not measured effect sizes.**
286
286
  Description clarity is weighted highest on the prior that wrong tool selection
287
287
  is the costliest failure — that prior is untested here.
@@ -304,7 +304,7 @@ doesn't:
304
304
  - [ ] LLM-assisted rewriting of flagged descriptions (`--fix`)
305
305
  - [ ] Live tool-selection testing against a generated MCP server
306
306
  - [ ] GitHub Action wrapper
307
- - [ ] Baseline mode (`--baseline`) so CI only fails on *new* regressions
307
+ - [x] Baseline mode (`--baseline`) so CI only fails on *new* regressions
308
308
 
309
309
  ## Contributing
310
310
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "openapi-agent-ready"
7
- version = "0.4.0"
7
+ version = "0.4.1"
8
8
  description = "Audit any OpenAPI spec for AI-agent and MCP readiness, and generate an MCP server scaffold."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -3,8 +3,8 @@ Command-line interface for agent-ready.
3
3
 
4
4
  Exit codes (designed for CI use):
5
5
  0 audit passed all configured gates
6
- 1 audit ran, but a gate failed (score below --min-score, or
7
- --max-fails exceeded)
6
+ 1 audit ran, but a gate failed (score below --min-score,
7
+ --max-fails exceeded, or --max-new exceeded against --baseline)
8
8
  2 the spec could not be loaded or parsed
9
9
  """
10
10
 
@@ -17,6 +17,7 @@ from . import __version__
17
17
  from .auditor import (
18
18
  SpecLoadError,
19
19
  endpoints_ready_for_mcp,
20
+ extract_endpoints,
20
21
  load_spec,
21
22
  result_to_dict,
22
23
  run_audit,
@@ -183,6 +184,16 @@ def _run(argv=None) -> int:
183
184
  print(f"error: {exc}", file=sys.stderr)
184
185
  return EXIT_SPEC_ERROR
185
186
 
187
+ # Swagger 2.0 has `paths` too, but keeps auth in `securityDefinitions` and
188
+ # bodies in `in: body` params, so auditing it yields confidently wrong scores.
189
+ if isinstance(spec, dict) and "swagger" in spec:
190
+ print(
191
+ f"error: Swagger {spec['swagger']} is not supported — only OpenAPI 3.x. "
192
+ "Convert it first (e.g. with swagger2openapi).",
193
+ file=sys.stderr,
194
+ )
195
+ return EXIT_SPEC_ERROR
196
+
186
197
  if not isinstance(spec, dict) or not spec.get("paths"):
187
198
  print(
188
199
  "error: no 'paths' found — this does not look like an OpenAPI spec.",
@@ -190,7 +201,8 @@ def _run(argv=None) -> int:
190
201
  )
191
202
  return EXIT_SPEC_ERROR
192
203
 
193
- endpoint_count = len(spec.get("paths") or {})
204
+ # Operations, not paths — the audit (and the ambiguity check) is per operation.
205
+ endpoint_count = len(extract_endpoints(spec))
194
206
  result = run_audit(spec, progress=_make_progress(endpoint_count, args.quiet))
195
207
 
196
208
  if result["endpoint_count"] == 0:
@@ -1,7 +1,7 @@
1
1
  """
2
2
  AI-Readiness Rubric
3
3
  -------------------
4
- Seven categories used to score how ready an API (from an OpenAPI spec) is
4
+ Eight categories used to score how ready an API (from an OpenAPI spec) is
5
5
  for reliable use by AI agents / MCP servers. Each endpoint gets checked
6
6
  against every category; failures become concrete, cite-able gaps.
7
7
 
@@ -13,8 +13,9 @@ Categories:
13
13
  5. Ambiguity between endpoints -- Wang et al. (2026) found 73% repeated tool names
14
14
  6. Parameter explanation -- "Opaque Parameters" smell: 84.3% prevalence
15
15
  7. Usage guidelines (when to call) -- "Missing Usage Guidelines" smell: 89.3% prevalence
16
+ 8. Tool surface & schema strictness -- OpenAI function-calling guidance (keep tool count small)
16
17
 
17
- Provenance note (be honest about this in interviews):
18
+ Provenance:
18
19
  Categories 1-5 were derived independently from how MCP tool selection works
19
20
  plus standard API design principles. Categories 6-7 were added after checking
20
21
  the rubric against published empirical work:
@@ -29,7 +30,7 @@ the rubric against published empirical work:
29
30
  Server Descriptions," arXiv:2602.18914. 10,831 servers, 18 smell
30
31
  categories across accuracy / functionality / completeness / conciseness.
31
32
 
32
- IMPORTANT TRADE-OFF (cite this, it's the senior-level point):
33
+ IMPORTANT TRADE-OFF:
33
34
  Hasan et al. found that augmenting ALL description components improved task
34
35
  success by a median 5.85pp but increased execution steps by 67.46% and
35
36
  REGRESSED performance in 16.67% of cases. More completeness is not strictly
@@ -477,6 +477,13 @@ def test_cli_bad_spec_exits_two(tmp_path, capsys):
477
477
  assert main([str(p), "--quiet"]) == 2
478
478
 
479
479
 
480
+ def test_cli_rejects_swagger_2(tmp_path, capsys):
481
+ """Swagger 2.0 has `paths`, so it used to be scored (wrongly) instead of rejected."""
482
+ spec = {"swagger": "2.0", "info": {"title": "Old", "version": "1"}, **GOOD_SPEC}
483
+ assert main([_write(tmp_path, spec), "--quiet"]) == 2
484
+ assert "Swagger 2.0 is not supported" in capsys.readouterr().err
485
+
486
+
480
487
  def test_cli_json_output_is_valid(tmp_path, capsys):
481
488
  main([_write(tmp_path, GOOD_SPEC), "--format", "json"])
482
489
  payload = json.loads(capsys.readouterr().out)