E2E story suite: real specs, real HTTP, real MCP SDK, and the built package - #29
Conversation
…ed multipart bodies as form data
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (4)
WalkthroughThe PR adds a separate E2E suite with real OpenAPI fixtures, MCP and HTTP loopback tests, Arazzo workflow coverage, packaging checks, runnable examples, and generated-signature validation. It also updates schema conversion, binary request handling, SDK output schemas, path-item parameter validation, and shared test-server utilities. ChangesE2E coverage and core behavior
Estimated code review effort: 4 (Complex) | ~60 minutes Mergeability Score: 🟡 Moderate · up to The PR adds end-to-end examples and changes validation, request, and workflow behavior, but the current head still has concrete correctness gaps: referenced or path-item parameters can be mishandled, cookie credentials and valid empty or non-JSON responses are not handled in example request paths, and workflow payload or pointer mapping can silently produce incorrect requests; documentation and lint issues also remain. These issues should be fixed or explicitly accepted before merge. Sequence Diagram(s)sequenceDiagram
participant E2ETest
participant McpClient
participant McpServer
participant sendBuiltRequest
participant LoopbackServer
E2ETest->>McpClient: invoke generated tool
McpClient->>McpServer: send MCP request
McpServer->>sendBuiltRequest: serialize request
sendBuiltRequest->>LoopbackServer: send HTTP request
LoopbackServer-->>sendBuiltRequest: return response
sendBuiltRequest-->>McpServer: provide response data
McpServer-->>McpClient: return structured result
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
e2e/real-specs.e2e.ts (2)
76-78: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAlso match OpenAPI 3.1 union types when checking
ensureArrayItems.The check only matches
type === 'array'. Indiscord-trimmed-3.1.json, 3.1 schemas can declaretype: ['array', 'null']. Those nodes skip the assertion, so theensureArrayItemstransform stays unverified for the fixture that most likely produces them.♻️ Proposed change
- if (record['type'] === 'array') { + const type = record['type']; + const isArrayType = type === 'array' || (Array.isArray(type) && type.includes('array')); + if (isArrayType) { expect(record['items'] ?? record['prefixItems']).toBeDefined(); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@e2e/real-specs.e2e.ts` around lines 76 - 78, Update the array-schema condition in the ensureArrayItems assertions to also recognize OpenAPI 3.1 union types where record['type'] is an array containing 'array', while preserving the existing scalar 'array' behavior and item/prefixItems assertion.
23-23: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winKeep
TARGETSexhaustive asClientTargetevolves.
TARGETScurrently contains everyClientTargetmember. Add a compile-time exhaustiveness check because a hand-writtenClientTarget[]does not detect missing members.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@e2e/real-specs.e2e.ts` at line 23, Update the TARGETS declaration to enforce compile-time exhaustiveness against ClientTarget, so adding a new ClientTarget member causes a type error until it is included. Preserve the existing target values and array usage.e2e/curation-journey.e2e.ts (1)
23-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winPin the resolved operation so the hard-coded overlay description stays truthful.
Line 27 derives
methodandopPathfrom the firstvague-descriptionfinding, but the description text on line 38 describes a specific gist-delete operation. If the fixture or the lint ordering changes, the overlay applies a description that does not match the targeted operation, and the test still passes. Line 27 also uses a non-null assertion and a baresplit(' '); a format change gives a wrong JSONPath and a confusing failure on line 45.Add explicit assertions on the resolved operation.
♻️ Proposed change
const [method, opPath] = vague[0].path!.split(' '); + // The overlay description below is written for this exact operation. + expect(method).toBe('DELETE'); + expect(opPath).toBe('/gists/{gist_id}');As per path instructions: "regenerating a fixture requires updating the literal count assertions that pin it" — these assertions extend that pinning to the overlay target.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@e2e/curation-journey.e2e.ts` around lines 23 - 43, In the curation test, explicitly assert that the selected vague-description finding resolves to the intended gist-delete operation before constructing the overlay. Replace the non-null assertion and bare split around the resolved finding with validated parsing, then assert the expected method and path so the hard-coded description remains truthful and fixture changes fail clearly.Source: Path instructions
e2e/fixtures/trim-openapi.mjs (1)
65-84: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winReport unresolvable component references instead of dropping them silently.
Step 3 skips any
$refwhose target is missing (if (target === undefined) continue;). The trimmed output then contains a dangling$ref, and the failure only appears later as a confusing dereference error in the E2E stories. The lookup also does not unescape JSON Pointer tokens (~0,~1), so a component name that contains those tokens resolves toundefined.♻️ Proposed change
+const unescape = (token) => token.replace(/~1/g, '/').replace(/~0/g, '~'); +const resolve = (ref) => { + const [, , group, name] = ref.split('/'); + return { group, name, target: doc.components?.[group]?.[unescape(name)] }; +}; + let previousSize = -1; while (refs.size !== previousSize) { previousSize = refs.size; for (const ref of [...refs]) { - const [, , group, name] = ref.split('/'); - const target = doc.components?.[group]?.[name]; - if (target) collect(target); + const { target } = resolve(ref); + if (target) collect(target); } } // 3. Copy only reachable components (securitySchemes always kept whole) const components = {}; +const missing = []; for (const ref of refs) { - const [, , group, name] = ref.split('/'); - const target = doc.components?.[group]?.[name]; - if (target === undefined) continue; + const { group, name, target } = resolve(ref); + if (target === undefined) { + missing.push(ref); + continue; + } components[group] ??= {}; - components[group][name] = target; + components[group][unescape(name)] = target; } +if (missing.length > 0) { + console.error(`unresolvable component refs:\n ${missing.join('\n ')}`); + process.exit(1); +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@e2e/fixtures/trim-openapi.mjs` around lines 65 - 84, Update the component-resolution flow around the reachability loop and Step 3 copy in the trim script to decode JSON Pointer tokens (`~1` to `/` and `~0` to `~`) before looking up component names. When a referenced component cannot be found, report the unresolved reference explicitly and fail rather than silently skipping it, while preserving the existing copying of reachable components and complete securitySchemes.e2e/helpers/arazzo-executor.ts (1)
35-42: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winGuard the intermediate nodes in
setPointer.
setPointerassumes every intermediate segment already exists and is an object. If a payload template omits a parent object,nodebecomesundefinedand the final assignment throws aTypeErrorthat is hard to trace back to the pointer. Create missing containers instead.♻️ Proposed hardening
function setPointer(target: Record<string, unknown>, pointer: string, value: unknown): void { const segments = pointer.slice(1).split('/').map(decodeSegment); let node: Record<string, unknown> = target; for (const segment of segments.slice(0, -1)) { - node = node[segment] as Record<string, unknown>; + if (node[segment] === null || typeof node[segment] !== 'object') { + node[segment] = {}; + } + node = node[segment] as Record<string, unknown>; } node[segments[segments.length - 1]] = value; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@e2e/helpers/arazzo-executor.ts` around lines 35 - 42, Update setPointer to ensure each intermediate pointer segment resolves to an object before continuing; create and assign a new container when the segment is missing or not object-like. Preserve decodeSegment handling and the final value assignment, including support for omitted parent objects.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@e2e/fixtures/README.md`:
- Line 17: Update the trim-openapi.mjs link in the README description to use an
absolute GitHub URL targeting the main branch, matching the format of the other
links while preserving the existing link text.
In `@e2e/helpers/arazzo-executor.ts`:
- Around line 109-114: Update the flattened-payload branch in the step
request-building logic to map each payload property through the corresponding
operation.mapper entry, assigning values by mapper.inputKey rather than directly
merging spec property names. Preserve the wholeBody handling and ensure
properties whose mapper key differs from inputKey are retained for
buildHttpRequest.
In `@src/validator.ts`:
- Around line 120-127: The path-item parameters used by the operation loop must
be validated before contributing to template coverage. Update the path-level
parameter handling near validateOperation and the corresponding path-level
validation flow to call validateParameters with the /paths/<path>/parameters
location, while retaining the validated parameters for coverage checks and
preserving operation-level behavior. Add regression cases covering a
non-required path parameter and a path parameter missing its schema.
---
Nitpick comments:
In `@e2e/curation-journey.e2e.ts`:
- Around line 23-43: In the curation test, explicitly assert that the selected
vague-description finding resolves to the intended gist-delete operation before
constructing the overlay. Replace the non-null assertion and bare split around
the resolved finding with validated parsing, then assert the expected method and
path so the hard-coded description remains truthful and fixture changes fail
clearly.
In `@e2e/fixtures/trim-openapi.mjs`:
- Around line 65-84: Update the component-resolution flow around the
reachability loop and Step 3 copy in the trim script to decode JSON Pointer
tokens (`~1` to `/` and `~0` to `~`) before looking up component names. When a
referenced component cannot be found, report the unresolved reference explicitly
and fail rather than silently skipping it, while preserving the existing copying
of reachable components and complete securitySchemes.
In `@e2e/helpers/arazzo-executor.ts`:
- Around line 35-42: Update setPointer to ensure each intermediate pointer
segment resolves to an object before continuing; create and assign a new
container when the segment is missing or not object-like. Preserve decodeSegment
handling and the final value assignment, including support for omitted parent
objects.
In `@e2e/real-specs.e2e.ts`:
- Around line 76-78: Update the array-schema condition in the ensureArrayItems
assertions to also recognize OpenAPI 3.1 union types where record['type'] is an
array containing 'array', while preserving the existing scalar 'array' behavior
and item/prefixItems assertion.
- Line 23: Update the TARGETS declaration to enforce compile-time exhaustiveness
against ClientTarget, so adding a new ClientTarget member causes a type error
until it is included. Preserve the existing target values and array usage.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 516879c3-0172-4a4b-8168-3e5605492c3d
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (34)
.github/workflows/push.ymlCLAUDE.mdCONTRIBUTING.mde2e/arazzo-executor.e2e.tse2e/curation-journey.e2e.tse2e/fixtures/README.mde2e/fixtures/discord-trimmed-3.1.jsone2e/fixtures/github-trimmed-3.0.jsone2e/fixtures/petstore-3.0.yamle2e/fixtures/trim-openapi.mjse2e/helpers/ajv.tse2e/helpers/arazzo-executor.tse2e/helpers/fixtures.tse2e/helpers/http.tse2e/helpers/mcp.tse2e/mcp-server.e2e.tse2e/packaging.e2e.tse2e/real-specs.e2e.tse2e/tsconfig.jsone2e/type-signatures.e2e.tse2e/wire-serialization.e2e.tsjest.e2e.config.jspackage.jsonsrc/__tests__/generator.spec.tssrc/__tests__/helpers/loopback.tssrc/__tests__/request-builder.spec.tssrc/__tests__/sdk.spec.tssrc/__tests__/ssrf.spec.tssrc/__tests__/types.spec.tssrc/__tests__/validator.spec.tssrc/request-builder.tssrc/sdk.tssrc/types.tssrc/validator.ts
…utor key mapping, and static packaging consumers
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/validator.ts`:
- Around line 123-125: The validation flow around OpenAPIToolGenerator.validate
and Validator must resolve Reference Object parameters before validateParameters
and path-coverage checks. Ensure validate receives or dereferences the document
consistently with generateTools, preserving resolved path-level
components.parameters behavior, and add a regression test covering a valid
path-level parameter reference.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d1b1f943-8de9-4691-a20f-caa128fc5ddc
📒 Files selected for processing (8)
e2e/curation-journey.e2e.tse2e/fixtures/README.mde2e/fixtures/trim-openapi.mjse2e/helpers/arazzo-executor.tse2e/packaging.e2e.tse2e/real-specs.e2e.tssrc/__tests__/validator.spec.tssrc/validator.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- e2e/curation-journey.e2e.ts
- e2e/fixtures/README.md
- e2e/fixtures/trim-openapi.mjs
- e2e/packaging.e2e.ts
- src/tests/validator.spec.ts
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/arazzo-workflow/example.ts`:
- Around line 90-94: Decode each JSON Pointer segment from expression.pointer
before traversing or assigning in the payload update loop: convert ~1 to / and
~0 to ~, in that order. Apply the decoded segments when navigating node and
selecting the final property, preserving the existing materialize call and
payloadExpressions flow.
In `@examples/curation/README.md`:
- Line 19: Update the fixture link in the README sentence describing
example.e2e.ts so its URL points directly to
e2e/fixtures/github-trimmed-3.0.json instead of the fixtures README, while
preserving the existing link label and surrounding text.
In `@examples/http-requests/example.ts`:
- Around line 38-45: Update the fetch request construction in
examples/http-requests/example.ts lines 38-45 and
examples/quickstart-mcp-server/example.ts lines 63-69 to merge
SecurityResolver.resolve’s security.cookies into the outbound Cookie header,
preserving any Cookie value already produced by buildHttpRequest; apply the same
cookie merge in both pipelines before fetch while retaining the existing query
and header handling.
In `@examples/quickstart-mcp-server/example.ts`:
- Around line 71-76: Update the response handling around the payload parse in
the MCP request handler to read the body once, tolerate empty, text, HTML, and
invalid-JSON responses, and use raw text in content when JSON parsing fails or
no body exists. Only set structuredContent for successful responses whose parsed
payload is a supported object shape, while preserving isError for non-OK
responses.
In `@examples/README.md`:
- Around line 23-28: Update the fenced directory-layout block in
examples/README.md to specify the text language by adding the text info string
to its opening fence, preserving the existing layout content unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: da3e249a-e89c-4e89-8ead-89e2b082b193
📒 Files selected for processing (27)
CLAUDE.mdREADME.mddocs/examples.mde2e/tsconfig.jsonexamples/README.mdexamples/arazzo-workflow/README.mdexamples/arazzo-workflow/example.e2e.tsexamples/arazzo-workflow/example.tsexamples/client-targets/README.mdexamples/client-targets/example.e2e.tsexamples/client-targets/example.tsexamples/curation/README.mdexamples/curation/example.e2e.tsexamples/curation/example.tsexamples/http-requests/README.mdexamples/http-requests/example.e2e.tsexamples/http-requests/example.tsexamples/quickstart-mcp-server/README.mdexamples/quickstart-mcp-server/example.e2e.tsexamples/quickstart-mcp-server/example.tsexamples/secure-loading/README.mdexamples/secure-loading/example.e2e.tsexamples/secure-loading/example.tsexamples/typed-tools/README.mdexamples/typed-tools/example.e2e.tsexamples/typed-tools/example.tsjest.e2e.config.js
🚧 Files skipped from review as they are similar to previous changes (3)
- CLAUDE.md
- jest.e2e.config.js
- e2e/tsconfig.json
… and tolerant response parsing in examples
There was a problem hiding this comment.
Pull request overview
Adds a comprehensive E2E story suite covering real OpenAPI specifications, HTTP traffic, MCP SDK integration, generated TypeScript, examples, and built-package consumption.
Changes:
- Adds 14 E2E/example suites, shared helpers, real-world fixtures, and CI execution.
- Fixes cyclic schema conversion, path-level validation, SDK output schemas, and multipart binary handling.
- Adds tested examples and supporting documentation.
Reviewed changes
Copilot reviewed 56 out of 59 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/push.yml |
Runs E2E tests after build. |
CLAUDE.md |
Documents E2E conventions. |
CONTRIBUTING.md |
Adds the E2E command. |
README.md |
Links tested examples. |
docs/examples.md |
Promotes runnable examples. |
package.json |
Adds E2E script and dependencies. |
yarn.lock |
Locks new dependencies. |
jest.e2e.config.js |
Configures isolated E2E suites. |
src/validator.ts |
Validates path-level parameters and references. |
src/types.ts |
Makes schema conversion cycle-safe. |
src/sdk.ts |
Filters MCP-incompatible output schemas. |
src/request-builder.ts |
Corrects multipart binary-part handling. |
src/__tests__/validator.spec.ts |
Tests path-level and referenced parameters. |
src/__tests__/types.spec.ts |
Tests cyclic schemas. |
src/__tests__/sdk.spec.ts |
Tests SDK output filtering. |
src/__tests__/request-builder.spec.ts |
Tests multipart binary parts. |
src/__tests__/ssrf.spec.ts |
Uses the shared loopback server. |
src/__tests__/generator.spec.ts |
Reuses loopback infrastructure. |
src/__tests__/helpers/loopback.ts |
Adds request-capturing HTTP helper. |
e2e/tsconfig.json |
Configures E2E type-checking. |
e2e/mcp-server.e2e.ts |
Tests MCP calls over real transport. |
e2e/wire-serialization.e2e.ts |
Verifies serialized HTTP traffic. |
e2e/real-specs.e2e.ts |
Exercises real specifications and targets. |
e2e/type-signatures.e2e.ts |
Compiles generated declarations. |
e2e/arazzo-executor.e2e.ts |
Executes workflow IR over HTTP. |
e2e/packaging.e2e.ts |
Tests CJS, ESM, and package exports. |
e2e/curation-journey.e2e.ts |
Tests overlay and trimming workflows. |
e2e/helpers/mcp.ts |
Provides MCP client/server wiring. |
e2e/helpers/http.ts |
Sends built requests over HTTP. |
e2e/helpers/fixtures.ts |
Loads vendored fixtures. |
e2e/helpers/arazzo-executor.ts |
Implements the test workflow executor. |
e2e/helpers/ajv.ts |
Validates generated JSON Schemas. |
e2e/fixtures/README.md |
Documents fixture provenance. |
e2e/fixtures/trim-openapi.mjs |
Reproducibly trims specifications. |
e2e/fixtures/petstore-3.0.yaml |
Vendors the Petstore specification. |
e2e/fixtures/github-trimmed-3.0.json |
Vendors a trimmed GitHub specification. |
e2e/fixtures/discord-trimmed-3.1.json |
Vendors a trimmed Discord specification. |
examples/README.md |
Indexes tested examples. |
examples/quickstart-mcp-server/README.md |
Documents the MCP quickstart. |
examples/quickstart-mcp-server/example.ts |
Implements an MCP proxy server. |
examples/quickstart-mcp-server/example.e2e.ts |
Tests the quickstart end-to-end. |
examples/http-requests/README.md |
Documents request execution. |
examples/http-requests/example.ts |
Implements HTTP tool calls. |
examples/http-requests/example.e2e.ts |
Tests request serialization. |
examples/secure-loading/README.md |
Documents secure URL loading. |
examples/secure-loading/example.ts |
Implements hardened loading. |
examples/secure-loading/example.e2e.ts |
Tests SSRF protection. |
examples/curation/README.md |
Documents tool curation. |
examples/curation/example.ts |
Implements curation reporting. |
examples/curation/example.e2e.ts |
Tests real-spec curation. |
examples/client-targets/README.md |
Documents schema dialect targets. |
examples/client-targets/example.ts |
Generates client-specific tools. |
examples/client-targets/example.e2e.ts |
Tests target transformations. |
examples/typed-tools/README.md |
Documents typed tool surfaces. |
examples/typed-tools/example.ts |
Builds signatures and declarations. |
examples/typed-tools/example.e2e.ts |
Compiles the generated surface. |
examples/arazzo-workflow/README.md |
Documents workflow execution. |
examples/arazzo-workflow/example.ts |
Implements an example workflow executor. |
examples/arazzo-workflow/example.e2e.ts |
Tests workflow execution. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…le patterns per review
Adds a real-example / user-story E2E suite alongside the unit suite — real HTTP, the real MCP SDK, real-world specs, and the built package — plus three product
fix:commits for bugs the suite caught before it was even finished.Why
Everything under
src/__tests__/asserts data structures: nothing ever went over HTTP, the builtdist/was never imported by any test, the doc-promised "spec → running MCP server" journey had never met the real SDK, and emitted TypeScript was never compiled. The Tier-4 review cycles kept finding exactly the bug classes such a suite would catch.The suite (
e2e/*.e2e.ts,yarn test:e2e)Structurally separate from the unit gate: own jest config (
roots: e2e/,.e2e.tssuffix), no coverage — the 100% threshold stays a unit-suite contract. New dev-only deps:@modelcontextprotocol/sdk,ajv.mcp-serverServer/ClientoverInMemoryTransport: listTools round-trip, callTool → SecurityResolver + buildHttpRequest → real fetch → wire assertions, error semanticswire-serializationallowReserved, cookies, form-urlencoded, multipart binary bytes, and Bearer/Basic/apiKey credentials as raw captured HTTPreal-specstype-signaturesarazzo-executorfromArazzoIR over live HTTP —$inputs/$steps/$response.body#/idreach the wirepackagingdist/symlinked as an installed packagecuration-journeyFixtures are commit-pinned with licenses and the trim script vendored (
e2e/fixtures/README.md); the shared loopback helper now captures raw requests and is reused by the unit suite (generator.spec.ts,ssrf.spec.ts).Bugs the suite caught (fixed here, with unit regression tests)
toJsonSchemainfinite recursion on cyclic specs — Discord's self-referential schemas crashed every operation withMaximum call stack size exceeded. Now cycle-safe via a path stack (true cycles break to an unconstrained schema; diamond-shared nodes still copy).parametersdeclared on the path item (Discord's style) failed validation withMISSING_PATH_PARAMETERon every operation.toSdkToolemitted MCP-invalid output schemas — MCP requiresoutputSchemaroottype: 'object'; the real SDK client rejects listings carrying array/scalar/status-union roots. Non-object roots are now omitted from the SDK config (full schema stays ontool.outputSchema).format: binaryfile part flipped the whole-body-binary flag, producing a plain-object body with a bare boundary-lesscontent-type: multipart/form-data. Multipart uploads throughbuildHttpRequest+ fetch were broken end-to-end; now they build realFormData.CI + docs
yarn test:e2eruns after Build in the existing matrix job (node 20/22/24). CLAUDE.md scopes the "inline specs, no fixture files" rule to unit tests and documents the e2e conventions; CONTRIBUTING gains the command.Test plan
yarn test:coverage— 1,039 unit tests, 100/100/100/100 enforced, exit 0yarn build && yarn test:e2e— 48 e2e tests across 7 stories, exit 0; on a clean tree the packaging story fails loudly with "run yarn build first"npx tsc -p tsconfig.lib.json --noEmitandnpx tsc -p e2e/tsconfig.json— cleanjest --listTestsshows no e2e files; the e2e runner lists exactly the 7 storiesSummary by CodeRabbit
Bug Fixes
Testing
Documentation
Addendum: tested examples (
examples/)Seven example folders, each pairing consumer-style code (
example.ts, importingmcp-from-openapiby its package name — the e2e runner maps the bare specifier ontosrc/) with a colocatedexample.e2e.tsexecuted byyarn test:e2e. An example that stops working fails CI, so the docs can safely point at them:quickstart-mcp-server · http-requests · secure-loading · curation (runs over the real GitHub fixture) · client-targets · typed-tools (output compiled by real tsc) · arazzo-workflow (IR executed over live HTTP)
Each folder carries a README with what it demonstrates and doc cross-links;
examples/README.mdis the index, anddocs/examples.md+ the README doc table point to it. Suite totals are now 56 e2e tests across 14 suites.Also folded in from review: reference-object (
$ref) parameters no longer false-positive structural validation, and the template-coverage check defers when unresolved refs are present (three regression tests).