openapi-agent-ready 0.1.0__tar.gz → 0.2.0__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 (21) hide show
  1. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/.github/workflows/ci.yml +22 -0
  2. openapi_agent_ready-0.2.0/.github/workflows/publish.yml +47 -0
  3. openapi_agent_ready-0.2.0/CHANGELOG.md +107 -0
  4. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/PKG-INFO +32 -19
  5. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/README.md +24 -18
  6. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/pyproject.toml +9 -2
  7. openapi_agent_ready-0.2.0/src/agent_ready/mcp_generator.py +243 -0
  8. openapi_agent_ready-0.2.0/tests/test_mcp_conformance.py +502 -0
  9. openapi_agent_ready-0.1.0/CHANGELOG.md +0 -38
  10. openapi_agent_ready-0.1.0/src/agent_ready/mcp_generator.py +0 -119
  11. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/.gitignore +0 -0
  12. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/CONTRIBUTING.md +0 -0
  13. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/LICENSE +0 -0
  14. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/examples/agent_ready_booking_api.yaml +0 -0
  15. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/examples/sample_booking_api.yaml +0 -0
  16. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/src/agent_ready/__init__.py +0 -0
  17. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/src/agent_ready/auditor.py +0 -0
  18. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/src/agent_ready/cli.py +0 -0
  19. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/src/agent_ready/report_generator.py +0 -0
  20. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/src/agent_ready/rubric.py +0 -0
  21. {openapi_agent_ready-0.1.0 → openapi_agent_ready-0.2.0}/tests/test_audit.py +0 -0
@@ -33,6 +33,28 @@ jobs:
33
33
  - name: Test
34
34
  run: pytest --cov=agent_ready --cov-report=term-missing
35
35
 
36
+ - name: Verify generated MCP scaffold speaks the protocol
37
+ run: |
38
+ # Fail loudly if no usable MCP server class is present — otherwise the
39
+ # conformance tests skip silently and CI goes green on nothing.
40
+ # The class moved in mcp 2.0, so accept either generation.
41
+ python - <<'PY'
42
+ try:
43
+ from mcp.server import MCPServer as S
44
+ except ImportError:
45
+ from mcp.server.fastmcp import FastMCP as S
46
+ print("MCP server class available:", S.__name__)
47
+ PY
48
+ agent-ready examples/agent_ready_booking_api.yaml --generate-mcp /tmp/server.py --quiet
49
+ python /tmp/server.py < /dev/null || true
50
+ # Defence in depth: a skipped conformance suite is a silent pass, which
51
+ # is the exact failure this step exists to prevent.
52
+ pytest tests/test_mcp_conformance.py -v -rs | tee /tmp/conformance.log
53
+ if grep -q "SKIPPED" /tmp/conformance.log; then
54
+ echo "::error::Conformance tests were skipped, not run — treating as failure."
55
+ exit 1
56
+ fi
57
+
36
58
  - name: Smoke-test the CLI
37
59
  run: |
38
60
  agent-ready examples/sample_booking_api.yaml
@@ -0,0 +1,47 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ id-token: write # required for trusted publishing
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.12"
19
+
20
+ # Fail in seconds if the tag and the packaged version disagree, rather
21
+ # than after pulling a Docker image, signing artifacts, and being
22
+ # rejected by PyPI. A version number consumed by a failed upload is
23
+ # gone permanently, so this check is worth its five lines.
24
+ - name: Check tag matches package version
25
+ run: |
26
+ TAG="${GITHUB_REF_NAME#v}"
27
+ VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
28
+ echo "tag=$TAG pyproject=$VERSION"
29
+ if [ "$TAG" != "$VERSION" ]; then
30
+ echo "::error::Tag v$TAG does not match pyproject.toml version $VERSION. Move the tag to a commit with the correct version, then delete and recreate the release."
31
+ exit 1
32
+ fi
33
+
34
+ - name: Build
35
+ run: |
36
+ python -m pip install --upgrade pip build twine
37
+ python -m build
38
+
39
+ # Catches a README that won't render on PyPI and other metadata problems.
40
+ # Unfixable after upload without burning a version number.
41
+ - name: Check metadata
42
+ run: twine check dist/*
43
+
44
+ - name: Show what will be uploaded
45
+ run: ls -la dist/
46
+
47
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,107 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [0.2.0] - 2026-07-30
9
+
10
+ The generated MCP scaffold is now verified against the real protocol rather than
11
+ merely checked for syntax — which immediately surfaced two bugs that made
12
+ generated servers uncallable, and a third that stopped them starting at all
13
+ against the current SDK.
14
+
15
+ **Anyone on 0.1.0 should upgrade:** scaffolds generated by 0.1.0 fail to import
16
+ against mcp 2.x.
17
+
18
+ ### Added
19
+ - **MCP conformance test suite** (`tests/test_mcp_conformance.py`). Launches the
20
+ generated scaffold as a subprocess, completes a real MCP handshake over stdio
21
+ using the official client, and validates the advertised tool definitions: name
22
+ format, uniqueness, description presence, input-schema validity as JSON Schema,
23
+ required-argument correctness, and side-effect disclosure. Previously the only
24
+ check on generated output was that the file compiled.
25
+ - **`ToolAnnotations` on generated tools** (`readOnlyHint`, `destructiveHint`,
26
+ `idempotentHint`, `openWorldHint`), derived from the HTTP method. Prose in a
27
+ description helps a model reason about side effects; annotations let a client
28
+ *enforce* — auto-approving reads while requiring confirmation for writes.
29
+ - **`[server]` extra**, a clearer alias for `[mcp]`: these are dependencies the
30
+ *generated* server needs at runtime, not dependencies of the auditor.
31
+
32
+ ### Fixed
33
+ - **Generated scaffolds failed to import on mcp 2.0.** FastMCP was replaced by
34
+ `MCPServer` in the 2.x SDK. The scaffold now imports through a compatibility
35
+ shim supporting both generations, verified against mcp 1.28.1 and 2.0.0.
36
+ - **Request body fields were silently dropped.** The generator read only
37
+ `parameters`, so a `POST` endpoint's payload properties never became tool
38
+ arguments — producing, for example, a create-booking tool with no way to say
39
+ what to book. Syntactically valid and completely uncallable, which is exactly
40
+ the class of bug a compile check cannot catch.
41
+ - **No arguments were marked required.** Every parameter was emitted with a
42
+ `= None` default, so the advertised input schema had an empty `required`
43
+ array. A model could call an endpoint with a path parameter and omit it,
44
+ producing a malformed URL. Path parameters are now always required, and
45
+ `required: true` from the spec is honoured for query, header, and body fields.
46
+ - **Conformance tests silently skipped under mcp 2.0.** The module guard probed
47
+ a 1.x-only import path, so the whole suite skipped against a current install —
48
+ a green build that verified nothing. The guard now probes for either server
49
+ class, and CI fails explicitly if the suite skips rather than runs.
50
+ - **Conformance assertions were pinned to 1.x field names.** mcp 2.0 renamed
51
+ result fields to snake_case (`serverInfo` → `server_info`, `inputSchema` →
52
+ `input_schema`, `readOnlyHint` → `read_only_hint`). Assertions now read fields
53
+ through version-agnostic accessors; the suite passes on both 1.28.1 and 2.0.0.
54
+ - **Failures inside anyio task groups are now readable.** Exception groups are
55
+ flattened to their leaf causes and `BaseException` is caught rather than
56
+ `Exception`, so a `BaseExceptionGroup` no longer escapes the diagnostic
57
+ wrapper and leaves the real error truncated.
58
+
59
+ ### Changed
60
+ - **Generated scaffolds are self-documenting.** The file header states its
61
+ dependencies, how to run it, a paste-ready Claude Desktop config block, and
62
+ three things to fix before shipping — notably that the scaffold sends no
63
+ credentials, so calls against a real API will 401 until auth is wired in.
64
+ - **Generated servers are named after their source API** (`spotify-web-api`
65
+ rather than a shared `generated-api-server` placeholder), so two connected to
66
+ the same client no longer present identical names.
67
+ - Tool listings are fetched once per generated file and cached rather than
68
+ spawning a server subprocess per test, cutting spawns from ~14 to 4.
69
+
70
+ ## [0.1.1] - 2026-07-29
71
+
72
+ ### Added
73
+ - **Tool Surface & Schema Strictness** category (category 8), derived from
74
+ OpenAI's function-calling guidance: flags catalogues far above the ~20-tool
75
+ ceiling, request bodies incompatible with strict mode
76
+ (`additionalProperties: false`, all properties required), and parameters that
77
+ imply a fixed value set but accept free-form strings where an enum belongs.
78
+ - Findings now carry a `scope` ("endpoint" or "spec"). Spec-level findings are
79
+ weighted at 50% of their category so a single whole-API finding isn't averaged
80
+ away against hundreds of endpoint findings. Stripe's tool-surface score was
81
+ 99/100 before this fix and 49.6/100 after.
82
+
83
+ ### Changed
84
+ - Distribution name is `openapi-agent-ready` (PyPI rejected `agent-ready` as too
85
+ similar to the existing `agentready` package). Import name, CLI command, and
86
+ repo name are unchanged.
87
+
88
+ ## [0.1.0] - 2026-07-28
89
+
90
+ ### Added
91
+ - Seven-category AI-readiness rubric for OpenAPI specs
92
+ - CLI with text, markdown, and JSON output formats
93
+ - CI gate support via `--min-score` and `--max-fails` with documented exit codes
94
+ - Remote spec loading over http(s)
95
+ - Parameter `$ref` resolution and path-level shared parameter inheritance
96
+ - MCP server scaffold generation for endpoints that pass the audit
97
+ - Python API (`load_spec`, `run_audit`)
98
+
99
+ ### Fixed
100
+ - OpenAPI `default` responses now count as error documentation. Previously only
101
+ 4xx/5xx codes were recognised, which failed every endpoint in specs that use
102
+ `default` — including Stripe's entire public API. (Found by auditing Stripe.)
103
+ - Ambiguity findings are capped at the 25 most-similar pairs with a summary
104
+ line, so large catalogues produce a readable report.
105
+ - Usage-guidelines detection is now regex-based; literal matching missed
106
+ phrasings like "use this only when" and "use this only after".
107
+ - CLI exits cleanly when its output is piped to `head` or `less`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openapi-agent-ready
3
- Version: 0.1.0
3
+ Version: 0.2.0
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
@@ -38,12 +38,19 @@ Classifier: Topic :: Software Development :: Quality Assurance
38
38
  Requires-Python: >=3.10
39
39
  Requires-Dist: pyyaml>=6.0
40
40
  Provides-Extra: dev
41
+ Requires-Dist: httpx>=0.27; extra == 'dev'
42
+ Requires-Dist: jsonschema>=4.0; extra == 'dev'
43
+ Requires-Dist: mcp>=1.0; extra == 'dev'
44
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
41
45
  Requires-Dist: pytest-cov>=4.0; extra == 'dev'
42
46
  Requires-Dist: pytest>=7.0; extra == 'dev'
43
47
  Requires-Dist: ruff>=0.4; extra == 'dev'
44
48
  Provides-Extra: mcp
45
49
  Requires-Dist: httpx>=0.27; extra == 'mcp'
46
50
  Requires-Dist: mcp>=1.0; extra == 'mcp'
51
+ Provides-Extra: server
52
+ Requires-Dist: httpx>=0.27; extra == 'server'
53
+ Requires-Dist: mcp>=1.0; extra == 'server'
47
54
  Description-Content-Type: text/markdown
48
55
 
49
56
  # agent-ready
@@ -62,23 +69,24 @@ agent-specific failure, tells you exactly which endpoints will cause trouble and
62
69
  why, and can gate a CI pipeline so specs don't regress.
63
70
 
64
71
  ```bash
65
- pip install agent-ready
72
+ pip install openapi-agent-ready
66
73
  agent-ready https://example.com/openapi.yaml
67
74
  ```
68
75
 
69
76
  ```
70
77
  Generic Booking Platform API (v1.0)
71
- AI-readiness score: 54.4/100
72
- Endpoints: 4 Fails: 6 Warnings: 12
78
+ AI-readiness score: 58.4/100
79
+ Endpoints: 4 Fails: 7 Warnings: 14
73
80
 
74
81
  Category scores:
75
- Description Clarity 37.5/100
76
- Side Effects 70.0/100
77
- Error Responses 62.5/100
78
- Auth Clarity 50.0/100
79
- Ambiguity 100.0/100
80
- Parameter Explanation 16.7/100
81
- 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
82
90
  ```
83
91
 
84
92
  ## Why this exists
@@ -119,8 +127,8 @@ agent failures in production.
119
127
  ## Install
120
128
 
121
129
  ```bash
122
- pip install openapi-agent-ready # core
123
- pip install "openapi-agent-ready[mcp]" # + MCP scaffold generation
130
+ pip install openapi-agent-ready # core
131
+ pip install "openapi-agent-ready[server]" # + MCP scaffold generation
124
132
  ```
125
133
 
126
134
  From source:
@@ -158,7 +166,7 @@ regress when someone adds an endpoint:
158
166
  ```yaml
159
167
  - name: Check API is agent-ready
160
168
  run: |
161
- pip install agent-ready
169
+ pip install openapi-agent-ready
162
170
  agent-ready openapi.yaml --min-score 60 --max-fails 0
163
171
  ```
164
172
 
@@ -177,12 +185,16 @@ Exit codes:
177
185
 
178
186
  ## Real-world results
179
187
 
180
- Running it against Stripe's production spec (587 endpoints):
188
+ Running it against Stripe's production spec (587 endpoints), as of v0.1.0.
189
+ These figures move whenever the rubric changes — rerun the tool for current
190
+ numbers:
181
191
 
182
192
  ```
183
193
  Stripe API (v2026-06-24.dahlia)
184
- AI-readiness score: 62.9/100
194
+ AI-readiness score: 61.3/100
195
+ Endpoints: 587 Fails: 393 Warnings: 2133
185
196
 
197
+ Category scores:
186
198
  Description Clarity 68.3/100
187
199
  Side Effects 64.7/100
188
200
  Error Responses 100.0/100
@@ -190,6 +202,7 @@ AI-readiness score: 62.9/100
190
202
  Ambiguity 50.0/100
191
203
  Parameter Explanation 43.0/100
192
204
  Usage Guidelines 51.2/100
205
+ Tool Surface 49.6/100
193
206
  ```
194
207
 
195
208
  Two things worth drawing out.
@@ -198,11 +211,11 @@ Two things worth drawing out.
198
211
  in this tool, not in Stripe.** Stripe documents errors via OpenAPI's `default`
199
212
  response rather than enumerating explicit 4xx/5xx codes. Perfectly valid, and
200
213
  arguably cleaner. The check only looked for `4`/`5` prefixes, so it failed all
201
- 587 endpoints. Fixed, regression-tested, and the reason the README says to run
202
- this against a real spec before trusting it.
214
+ 587 endpoints. Fixed, regression-tested, and the reason this README says to run it against a
215
+ real spec before trusting it.
203
216
 
204
217
  **Stripe is widely and correctly regarded as agent-ready, yet its raw OpenAPI
205
- spec scores 62.9.** That isn't a contradiction — it's the whole point. Stripe's
218
+ spec scores 61.3.** That isn't a contradiction — it's the whole point. Stripe's
206
219
  agent-readiness comes from the *Agent Toolkit* layered on top: curated tool
207
220
  definitions, an MCP server, managed OAuth. The raw spec is the input to that
208
221
  layer, not the layer itself. Which is exactly why this tool ships with
@@ -14,23 +14,24 @@ 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
 
16
16
  ```bash
17
- pip install agent-ready
17
+ pip install openapi-agent-ready
18
18
  agent-ready https://example.com/openapi.yaml
19
19
  ```
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
@@ -71,8 +72,8 @@ agent failures in production.
71
72
  ## Install
72
73
 
73
74
  ```bash
74
- pip install openapi-agent-ready # core
75
- pip install "openapi-agent-ready[mcp]" # + MCP scaffold generation
75
+ pip install openapi-agent-ready # core
76
+ pip install "openapi-agent-ready[server]" # + MCP scaffold generation
76
77
  ```
77
78
 
78
79
  From source:
@@ -110,7 +111,7 @@ regress when someone adds an endpoint:
110
111
  ```yaml
111
112
  - name: Check API is agent-ready
112
113
  run: |
113
- pip install agent-ready
114
+ pip install openapi-agent-ready
114
115
  agent-ready openapi.yaml --min-score 60 --max-fails 0
115
116
  ```
116
117
 
@@ -129,12 +130,16 @@ Exit codes:
129
130
 
130
131
  ## Real-world results
131
132
 
132
- Running it against Stripe's production spec (587 endpoints):
133
+ Running it against Stripe's production spec (587 endpoints), as of v0.1.0.
134
+ These figures move whenever the rubric changes — rerun the tool for current
135
+ numbers:
133
136
 
134
137
  ```
135
138
  Stripe API (v2026-06-24.dahlia)
136
- AI-readiness score: 62.9/100
139
+ AI-readiness score: 61.3/100
140
+ Endpoints: 587 Fails: 393 Warnings: 2133
137
141
 
142
+ Category scores:
138
143
  Description Clarity 68.3/100
139
144
  Side Effects 64.7/100
140
145
  Error Responses 100.0/100
@@ -142,6 +147,7 @@ AI-readiness score: 62.9/100
142
147
  Ambiguity 50.0/100
143
148
  Parameter Explanation 43.0/100
144
149
  Usage Guidelines 51.2/100
150
+ Tool Surface 49.6/100
145
151
  ```
146
152
 
147
153
  Two things worth drawing out.
@@ -150,11 +156,11 @@ Two things worth drawing out.
150
156
  in this tool, not in Stripe.** Stripe documents errors via OpenAPI's `default`
151
157
  response rather than enumerating explicit 4xx/5xx codes. Perfectly valid, and
152
158
  arguably cleaner. The check only looked for `4`/`5` prefixes, so it failed all
153
- 587 endpoints. Fixed, regression-tested, and the reason the README says to run
154
- this against a real spec before trusting it.
159
+ 587 endpoints. Fixed, regression-tested, and the reason this README says to run it against a
160
+ real spec before trusting it.
155
161
 
156
162
  **Stripe is widely and correctly regarded as agent-ready, yet its raw OpenAPI
157
- spec scores 62.9.** That isn't a contradiction — it's the whole point. Stripe's
163
+ spec scores 61.3.** That isn't a contradiction — it's the whole point. Stripe's
158
164
  agent-readiness comes from the *Agent Toolkit* layered on top: curated tool
159
165
  definitions, an MCP server, managed OAuth. The raw spec is the input to that
160
166
  layer, not the layer itself. Which is exactly why this tool ships with
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "openapi-agent-ready"
7
- version = "0.1.0"
7
+ version = "0.2.0"
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"
@@ -23,8 +23,14 @@ classifiers = [
23
23
  dependencies = ["pyyaml>=6.0"]
24
24
 
25
25
  [project.optional-dependencies]
26
+ # Dependencies the *generated* server needs at runtime — not needed to run the
27
+ # auditor or to generate a scaffold, only to execute one. The scaffold supports
28
+ # both SDK generations: FastMCP (1.x) and MCPServer (2.x).
29
+ server = ["mcp>=1.0", "httpx>=0.27"]
30
+ # Retained as an alias; `server` describes what it does more accurately.
26
31
  mcp = ["mcp>=1.0", "httpx>=0.27"]
27
- dev = ["pytest>=7.0", "pytest-cov>=4.0", "ruff>=0.4"]
32
+ dev = ["pytest>=7.0", "pytest-cov>=4.0", "pytest-asyncio>=0.23", "ruff>=0.4",
33
+ "jsonschema>=4.0", "mcp>=1.0", "httpx>=0.27"]
28
34
 
29
35
  [project.scripts]
30
36
  agent-ready = "agent_ready.cli:main"
@@ -38,6 +44,7 @@ packages = ["src/agent_ready"]
38
44
 
39
45
  [tool.pytest.ini_options]
40
46
  testpaths = ["tests"]
47
+ asyncio_mode = "auto"
41
48
 
42
49
  [tool.ruff]
43
50
  line-length = 100