All notable changes to this project are documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning starting with the v1.0.0 release.
- Provider-aware proxy schemas and strict OpenAI compatibility. Generated proxy packages now expose standard, OpenAI, and provider-selecting registration entry points. The OpenAI surface follows strict-schema requirements recursively: object properties are all listed in
required, OpenAPI-optional fields are nullable, and objects reject unspecified properties. - Fail-closed security with native OAuth client credentials and mTLS. Proxy generation now preserves OpenAPI security OR/AND semantics; supports
apiKey, Basic, Bearer, pre-acquired OAuth tokens, OAuth 2 client-credentials token acquisition/refresh, and OpenAPI 3.1mutualTLS; and refuses to send an unauthenticated request when no declared alternative is satisfied.openIdConnectandaws4-hmac-sha256are supported throughruntime.WithRequestAuthProviderfor deployment-owned OIDC/SigV4 signers. A selected mTLS alternative requiresMTLS_CERT_FILEandMTLS_KEY_FILE(with optional CA/server-name settings); manual integrations useruntime.WithMTLSHTTPClient, not the generic HTTP-client option. - Startup-time dynamic registration.
pkg/dynamic.Registercan register tools directly from a local document or a fully bundled HTTPS document. Remote sources have a bounded body/time budget, no redirects or external references, and require a caller-selected HTTPSBaseURL; source-fetch and upstream clients are intentionally separate. Dynamic tools share proxy parameter, security, provider-schema, timeout, and response-boundary behavior. - OpenAPI parameter serialization. Proxy and dynamic paths now apply
style,explode, andallowReservedfor supported path/query/header/cookie forms, including matrix, label, space/pipe-delimited arrays, deep objects, and cookie expansion. Unsupported location/style combinations are diagnostics rather than silently coerced. - Bounded upstream responses. Proxy handlers use a 16 MiB default cap before buffering or base64-encoding an upstream response. Set
runtime.WithMaxResponseBytes(ordynamic.Config.MaxResponseBytes) to choose a deployment-specific bound; oversized responses produce the machine-readableresponse_too_largetool error. - Embedded resources for generic binary responses. PDF, video, octet-stream, XML, and other non-text/non-image/non-audio 2xx responses now surface as native embedded MCP blob resources through both adapters. They use an opaque content-addressed URN and carry no fetchable upstream URL; the response cap applies before projection.
image/*andaudio/*responses surface as native MCP content blocks. A 2xx upstream response with an image or audio content type now produces an MCPImageContent/AudioContentblock (both SDK adapters, both companion and proxy modes), so MCP clients can render the media directly instead of receiving base64 text. The content-type parameters are stripped from the surfacedmimeType(image/png; charset=binary→image/png); classification follows the same precedence as before, so+jsonsuffixes still win (image/foo+jsonstays JSON) andimage/svg+xmlcounts as an image. New library surface:runtime.CallToolResultgains additiveBinary/MediaKind/MIMETypefields, plusruntime.NewToolResultImage/runtime.NewToolResultAudioconstructors and theruntime.MediaKindtype. Together with embedded blob resources for other binary media, this closes the "Richer MCP result types" roadmap item.
- 2xx media responses no longer emit base64 text envelopes. Images and audio use their native MCP blocks; other binary types use embedded blob resources. The payload now lives only in its native content block — duplicating multi-MB media as base64 text would double the wire size. HTTP status/header metadata (
_meta) is unaffected.
- Tool annotations — every generated tool now carries MCP annotation hints derived from its HTTP method (RFC 9110 semantics): GET/HEAD/OPTIONS/TRACE →
readOnlyHint+idempotentHint, PUT →idempotentHint, DELETE →idempotentHint+ explicitdestructiveHint. The operationsummarybecomes the annotationtitle. New library typeruntime.ToolAnnotations(+runtime.BoolPtrhelper,Tool.Annotationsfield); both SDK adapters forward the hints. Applies to companion and proxy modes. - Tool output schemas — operations whose selected 2xx response is object-rooted JSON now declare an MCP
outputSchema(newoutput_<tool>schema constants,RawOutputSchemapopulated). Array/scalar/non-JSON responses emit none (both SDKs require an object root). Adefaultresponse feeds the output schema only when the operation declares no 2xx at all, so the classic "204 + default error" pattern doesn't advertise its error shape as output. The schema description notes that error results carry the{status, headers, body}envelope instead. - Parameter-object metadata in input schemas —
description,example, anddeprecateddeclared on the Parameter object (not its schema) are now merged into the tool input schema; the schema's own keywords win on collision. Previously this metadata was silently dropped. - Deprecated operations surfaced —
deprecated: trueon an operation now prefixes the tool description withDeprecated.(MCP has no native flag). - Webhook / link / nested-multipart-encoding diagnostics are now emitted — the codes
dropped-webhook(OpenAPI 3.1 top-levelwebhooks, including webhooks-only documents),dropped-link(responselinks, named per<status>.<link>), andnested-multipart-encoding(encoding metadata keyed by a nested binary field's name, which OpenAPI cannot address) existed but never fired; these spec features were dropped with no trace. All three are warnings and therefore visible to-warnings-as-errorspipelines. - Roadmap tracking — the release introduced an explicit roadmap for gaps that were intentionally deferred at that point.
- E2E coverage for
-openai-compat—tests/e2e/cli_test.godrives the real binary against the composition-heavy complex-schemas fixture and asserts the strict-dialect invariants (no$ref/oneOf/anyOf/allOf/$defs,additionalProperties:falseforced). The generator-level invariants test also gained the recursive fixture.
-openai-compatstack overflow on recursive schemas. The strict dialect inlines every reference, and the inlining path had no recursion guard — a self-referential schema (e.g. a comment tree) recursed until the process crashed. Re-entrant conversions now truncate to a permissive object stub whose description names the recursive component.- Proxy scaffold SDK pins drifted from the tested versions. The generated
go.modpinnedmodelcontextprotocol/go-sdk v1.6.0/mark3labs/mcp-go v0.54.0while this repo builds and tests against v1.6.1 / v0.55.1 — despite a comment claiming the pins track the repo. Now synced. - README CLI reference documents proxy mode.
-mode,-module, and-sdkwere implemented and used in the Quick Start but missing from the flag reference block.
- Multi-spec batch generation — the
-specflag now accepts directories (walked recursively, filtered to.yaml/.yml/.json), glob patterns (stdlibfilepath.Globsyntax:*,?,[...]), and comma-separated combinations of files / globs / directories. Single-file and URL inputs are unchanged. New packagepkg/batchderives per-specPackageName/OutDir/ClientImportfrom each matched spec's filename stem (-out gen -spec apis/writesgen/billingmcp/billingmcp.mcp.goetc.).-client-importis treated as a base path and the slug is appended withpath.Joinso generated import lines use forward slashes on every OS. Per-spec failures are accumulated and reported at end, exit code rolls up to3(exitGenerate); single-spec mode keeps its previous fail-fast behaviour and exit codes. Slug collisions (e.g.v1/api.yamlandv2/api.yaml) are reported with all source paths before any file is written. The flags-packageand-emit-v3are rejected in batch mode (exitUsage=1) because they would produce ambiguous or overwriting output.-listis supported and groups operations by spec with=== <path> ===headers. pkg/loader.ExpandSpecArg— new exported helper for callers that want to resolve a-spec-style argument into a deterministic, sorted, deduplicated list ofloader.SpecRefvalues (file paths orhttp(s)://URLs). Empty matches are surfaced as errors quoting the offending entry.generator.MCPPackageSuffix— exported constant ("mcp") sopkg/batchand any future caller can derive consistent package names without re-encoding the convention.x-mcpextension filtering — spec authors can now mark individual operations, path-items, or the whole document with anx-mcp: falseextension to exclude operations from MCP tool generation, orx-mcp: trueto opt back in. Precedence is operation > path-item > document > generator default. Excluded operations emit anexcluded-by-x-mcpinfo diagnostic; unrecognised values (e.g.x-mcp: "maybe") emit aninvalid-x-mcp-valuewarning and fall through to the next level so typos surface loudly. Boolean and string forms are both accepted (true/false/"true"/"false"), andjson.RawMessageis handled for forward-compatibility with legacy kin-openapi versions.-exclude-by-defaultCLI flag /Options.ExcludeByDefault— inverts the document-wide fallback: when set, only operations explicitly opted in withx-mcp: trueare generated. Useful for large specs where the author wants to publish a small curated subset as MCP tools without rewriting the rest of the document.-forceCLI flag /Options.Force— required to overwrite an existing*.mcp.gooutput file. Without it, an already-present file is a fatal error (exit code 3) rather than a silent overwrite, so accidental re-runs over hand-edited or committed output are caught. A directory at the output path is rejected even with-force— removing it would be more destructive than overwriting a file. The repository's ownmake regen-examplestarget now passes-forcevia the newGEN_FLAGSvariable.
-mode=proxyemission mode — new first-class output: a runnable Go module (main.go+go.mod+<pkg>/<pkg>.mcp.go+README.md) that proxies MCP tool calls directly to the upstream HTTP API. Nooapi-codegenstep needed; the generated handlers build*http.Requestobjects viahttp.NewRequestWithContextand dispatch throughcfg.HTTPClient.Do. Companion mode remains the default and its output is golden-test guarded.-module <import-path>CLI flag — required iff-mode=proxy. Becomes themoduledirective in the generatedgo.mod. In batch mode it's treated as a base path; each spec's slug is appended.-sdk={gosdk|mark3labs}CLI flag — picks which MCP SDK adapter the generatedmain.goimports. Defaults togosdk(the officialmodelcontextprotocol/go-sdk). Ignored in companion mode.Options.Mode,Options.ModulePath,Options.SDK— library-level equivalents of the new flags.- Built-in authentication from
securitySchemes— proxy mode readscomponents.securitySchemesand emits oneapplyAuth<Scheme>helper per supported scheme. Credentials are read from environment variables at startup:API_KEY_<NAME>forapiKeyschemes (anyin: header / query / cookie),BEARER_TOKEN_<NAME>forhttp+bearer,BASIC_AUTH_USERNAME_<NAME>/BASIC_AUTH_PASSWORD_<NAME>forhttp+basic,OAUTH2_ACCESS_TOKEN_<NAME>foroauth2(treated as a pre-acquired Bearer; no token-exchange flow). Unsupported schemes (openIdConnect,http+digest, etc.) surface asunsupported-security-schemewarnings and are dropped from auth wiring rather than aborting the build. runtime.MissingCredentialError— typed error surfaced through the MCPtools/callresponse when a required env var is unset. The error names both the scheme and the env var so the user gets an actionable message instead of a silent upstream 401.runtime.ApplyAPIKey,runtime.ApplyBearer,runtime.ApplyBasic— public helpers used by the generatedapplyAuth<Scheme>functions; reusable from user code if needed.runtime.DecodeProxyParam,runtime.BuildProxyURL,runtime.EncodeJSONBody,runtime.EncodeFormBody,runtime.ReadResponseBody— new helpers consumed by the proxy template (and available to anyone constructing their own proxies on top of the runtime).generator.ParseSecuritySchemes/ResolveOperationSecurity— exported helpers that lower an OpenAPI 3 document's security model into the generator's[]SecuritySchemerepresentation. Useful for tooling that wants to inspect a spec's auth surface without generating code.- E2E coverage —
tests/e2e/cli_proxy_test.gobuilds the generated scaffold, runs it as an MCP stdio server, and verifies (a)initializereturns a result; (b) a Bearer token inBEARER_TOKEN_<NAME>reaches the upstreamAuthorizationheader; (c) a missing required credential surfaces in the MCP error response with the env-var name.
- Runtime options are now applied by generated handlers. Companion and proxy handlers remove
WithExtraPropertiesfields from arguments, place present values oncontext.ContextviaExtraProperty.ContextKey, and applyWithRequestTimeoutper tool call. Proxy handlers also expandWithServerVariablesbefore building upstream URLs. - Proxy URL construction preserves base query strings correctly. A server URL such as
https://api.example.com/v2?tenant=acmenow becomeshttps://api.example.com/v2/<operation>?tenant=acme&...instead of appending the operation path inside the query value. - Proxy path parameters use path-segment escaping. Generated proxy code now escapes path placeholders with
url.PathEscapesemantics so spaces become%20rather than query-form+. - Generated path-parameter locals are collision-safe. Distinct path parameter names that sanitise to the same Go identifier (
foo-barandfoo_bar) now get deterministic suffixed local variable names instead of duplicate declarations. pkg/batch.Slugrejects digit-leading stems. A filename like999.yamlor2024-api.yamlpreviously slugged to999/2024apiand produced a package name (999mcp) that fails to compile because Go identifiers cannot start with a digit.Slugnow returns a clear error pointing at the offending filename so the user can rename it up front, matching the behaviour for the already-rejected empty-stem case.pkg/loader.ExpandSpecArgno longer splits commas inside URL tokens. Matrix parameters and OData$select=a,bvalues are common in real URLs; the previous split would yield bogus "matched no files" errors. The split heuristic is now "comma followed by whitespace separates entries"; a bare comma inside anhttp(s)://token is kept verbatim. A new unit test pins the behaviour.- CLI log prefixes prefer relative paths. Batch-mode
=== <path> ===headers and diagnostic prefixes now render the spec path relative to the working directory when that form is shorter and doesn't escape the tree, falling back to the absolute path otherwise. Underlying loader behaviour is unchanged — only the surface text is shorter.
runtime.NewToolResultFromHTTP(status, header, body, fallbackContentType)— canonical wrapper that preserves the upstream HTTP status code and a curated allowlist of response headers (Location,ETag,Last-Modified,Cache-Control,Content-Type,Content-Disposition,Content-Language,Retry-After,WWW-Authenticate,Link, plus up to 32X-*headers) on*CallToolResult. JSON bodies surface asStructuredContent(unchanged shape);text/*bodies surface as{"contentType","text"}; binary bodies surface as{"contentType","base64"}; 204 / empty bodies surface as success with noStructuredContent; non-2xx responses becomeIsError=truewith a{"status","headers","body"}envelope. Generated handlers now call this helper for every operation, so MCP clients can distinguish 201 +Locationfrom 200, 304 from 200, etc.CallToolResult.StatusCode+CallToolResult.Headers— additive struct fields. Zero values when not from an HTTP round-trip; existing handlers that build the struct directly continue to compile.- Cookie parameter support —
in: cookieparameters are now first-class: exposed in the tool's input schema under acookiegroup, decoded viaruntime.DecodeCookieParam, and forwarded to the upstream client through a newruntime.CookieRequestEditorthat satisfies oapi-codegen'sRequestEditorFn. runtime.WithHTTPClient,runtime.WithRequestTimeout,runtime.WithServerVariables— option groundwork user code can call fromRegister*opts to customise the upstream HTTP client, set a per-tool-call deadline, and supply substitutions for OpenAPI server-URL templates.runtime.SubstituteServerVariables(template, vars)— helper to expand{name}placeholders in OpenAPI server URLs at runtime.runtime.DecodeArguments— shared argument decoder used by both adapters so the gosdk and mark3labs paths surface identical error semantics on malformed input.runtime.BuildHTTPMeta+runtime.HTTPMetaKey— adapters serialise the new HTTP status + headers onto the underlying SDK's_metachannel (go-sdkMeta, mark3labsMeta.AdditionalFields) underopenapi-go-mcp/http, so MCP clients can read both regardless of which SDK is wired up.ExtraProperty.Type— extra-property declarations may now requestnumber,integer, orbooleanshapes in addition to the previous string-only path. Unknown types fall back to string rather than emit invalid schema.- Structured generator diagnostics —
generator.CollectOperationsandgenerator.Generatenow return[]Diagnosticalongside the error. StableCodevalues (dropped-callback,unsupported-parameter-style,shadowed-parameter,dropped-server-variables,dropped-security-requirement,content-type-header-override, …) make findings machine-readable; the legacyOptions.Warningsstream is preserved. -warnings-as-errorsCLI flag — exit code4when any warning-level diagnostic fires, useful for failing CI on spec regressions.- Distinct CLI exit codes —
0ok /1usage /2bad input /3generation failure /4warnings-as-errors. CI pipelines can branch on the code. - URL-based spec loading —
loader.Loadnow dispatcheshttp(s)://paths toloader.LoadFromURL(ctx, url, opts...), which enforces a 32 MiB body cap and a 30 s timeout (bothURLLoadOption-configurable). The CLI's-specflag accepts URLs without any extra ceremony. loader.URLLoadOptionknobs —WithHTTPClient,WithMaxBodySize,WithTimeoutfor custom transports / proxies / mTLS / auth headers.- Collision detection at codegen time —
RenderrejectsClientImportpaths whose base segment collides with Go reserved words or with packages the generated file already imports (context,json,runtime), and refuses operations whoseToolNames mangle to the same const identifier (get-petvsget_petwould have silently produced duplicate decls). - CWD-robust e2e tests —
tests/e2e/cli_test.gonow walks up looking forgo.modinstead of assuming a fixed depth. make smoke-all— exercises both the gosdk and mark3labs backends so adapter parity is verified at the protocol layer.
runtime.HandleErrorJSON-marshal fallback is no longer recursive — when the inner payload fails to encode, the helper synthesises a fixed-shape error string withfmt.Sprintfand returns; previously the fallback could re-enter the encoder.runtime.ToolErrorgained aCause errorfield and anUnwrap()method, so callers canerrors.Is/errors.Asto inspect the underlying parse/decode failure. All call sites inpkg/runtime/http.gowere updated to populate it.- Adapter parity —
pkg/runtime/gosdkandpkg/runtime/mark3labsroute through the sharedDecodeArgumentshelper, so the same MCPargumentspayload yields the same*runtime.CallToolResultregardless of which backend is loaded. The gosdk adapter no longer surfaces malformed-input parses as protocol errors; both now produce anIsErrortool result the LLM can self-correct from. generator.CollectOperationssignature — now returns([]Operation, []Diagnostic, error). Internal callers (Render,Generate) plumb the diagnostics through; the CLI prints them grouped by severity. TheOptions.Warningsio.Writercontinues to receive a free-form line per finding for backwards compatibility.generator.Generatesignature — now returns([]Diagnostic, error).- Generated handlers — every operation's success path now reads
resp.HTTPResponse.Headervia a smallheaderOf(*http.Response)helper emitted into the file and routes throughruntime.NewToolResultFromHTTP. Out-of-tree code that pattern-matched on the previousruntime.NewToolResultJSON(resp.Body)/NewToolResultBinary/NewToolResultTextlines must rerun the generator. callArgstemplate helper — returns(string, error)instead of panicking on an unhandled body kind;Rendernow surfaces the failure cleanly.- Loader file-read errors include the absolute path + CWD so relative-path confusion is debuggable from a single line.
- CLAUDE.md — Go-version reference updated to match
go.mod(1.26.x) and the current CI matrix.
examples/todossplit into two binaries — the example is nowexamples/todos/server(a realnet/httpservice with-addrflag, request log middleware,/healthz, and gracefulSIGINT/SIGTERMshutdown) andexamples/todos/mcp(an MCP proxy that connects via HTTP). The MCP proxy readsTODOS_BASE_URL(defaulthttp://localhost:8080), pings/healthzonce at startup with a 2 s timeout, and logs a non-fatal warning if unreachable. The previous in-processhttptest.Serverbundling is removed in favour of running the two halves separately, matching how the pattern is actually deployed. The README documents the two-terminal workflow and updated MCP-host configs.
0.1.1 — 2026-05-16
-prefer-content-typeflag — when an operation declares multiple request content types, override the default JSON → form → multipart → octet → text → xml priority by naming the spec content type to use. Falls back to the priority order when the preferred type isn't declared on a given op.- OpenAPI
discriminatordescription hint — schemas that carry adiscriminator(with optionalmapping) now surface the property name and mapping keys in the description, so callers can pick the right branch without the source spec. - Multipart
encoding[field]metadata — per-partContent-Typeoverrides declared on a multipart body'sencodingmap are now propagated throughruntime.RequestFilePartto each file part the runtime writes. - Nested multipart binary fields —
format:binaryleaves inside nested objects are detected, rewritten to base64 strings, and extracted from the surrounding object at request time. The residual object (after extraction) is sent as a JSON form field; if extraction leaves it empty, the field is omitted. - Content-Type header parameter collision warning — when a spec declares a
Content-Typeheader parameter alongside a non-JSON body, the generator now writes a warning toOptions.Warnings(defaults to stderr) noting the parameter will be overridden by the body's content type. - Non-JSON response decoding — the generator now picks a wrapper per operation's primary 2xx response:
NewToolResultJSONfor JSON (unchanged),NewToolResultTextfortext/*, and a newNewToolResultBinary([]byte, contentType string) *CallToolResultforapplication/octet-stream,application/xml, and other raw responses. Binary bodies are base64-encoded intoTextand surfaced as{"contentType","base64"}inStructuredContent. - CI
examplesjob — runsmake regen-exampleswith pinned oapi-codegen v2.7.0 on every push, thengit diff --exit-codeso an unsynced generator change fails CI before merge. examples/todosend-to-end example — fully self-contained demo: the binary starts an in-memory HTTP backend (backend.go), points an oapi-codegen client at it, and serves the generated MCP layer over stdio. Covers GET/POST/PUT/DELETE with path params, query params, and JSON request bodies in onego run ./examples/todos.TODOS_BASE_URLoverrides the embedded backend. Ships a dedicatedexamples/todos/README.mdwith copy-pasteable MCP client configs for Claude Desktop, Claude Code, Cursor, VS Code, and MCP Inspector.
runtime.BuildMultipartBodysignature — second argument is now[]runtime.RequestFilePartinstead of[]string. Generated code is updated automatically; out-of-tree callers must migrate. (Pre-1.0; no compatibility shim.)generator.CollectOperationssignature — now takesOptionsinstead of abool openAICompat, threadingPreferContentTypeandWarningsthrough alongside the dialect flag.- GoReleaser config migrated —
dockers+docker_manifests→ singledockers_v2multi-platform block;brews→homebrew_casks(the v2 successor for CLI tools). Localgoreleaser checkis now deprecation-warning-free. oapi-codegenconfigs inexamples/*/gen/*/oapi.yaml— output paths now name the destination explicitly (examples/.../gen/foo/foo.gen.go) somake regen-examplesworks regardless of cwd quirks. Previously some configs wrotefoo.gen.goto the repo root.
make regen-examplesis now idempotent: a second run produces no diff. Previously the oapi-codegen step landed some*.gen.gofiles at the repo root because theoutput:field was a bare filename interpreted relative to cwd.Dockerfilemulti-platform COPY —dockers_v2stages binaries under<os>/<arch>/<binary>in the build context, but the Dockerfile did a flatCOPY openapi-go-mcp …and the release docker build failed with"/openapi-go-mcp": not found. The Dockerfile now declaresARG TARGETOS/ARG TARGETARCH(auto-populated by BuildKit) and copies from${TARGETOS}/${TARGETARCH}/openapi-go-mcp. Verified locally withdocker buildx build --platform linux/amd64,linux/arm64against a reproduced goreleaser staging layout.
0.1.0 — 2026-05-16
Initial public release.
- CLI
openapi-go-mcp— reads OpenAPI 3.0 / 3.1 / Swagger 2.0 specs and generates a*.mcp.gofile per spec. Each operation becomes an MCP tool whose handler forwards to anoapi-codegenClientWithResponsesInterface. - Request body kinds —
application/json,application/x-www-form-urlencoded,multipart/form-data(binary fields accepted as base64),application/octet-stream,text/*, andapplication/xml+ raw-string fallback for any other content type. When an operation declares multiple, the generator picks deterministically (JSON → form → multipart → octet → text → xml → first). Three new runtime helpers —BuildMultipartBody,BuildBase64BytesBody,BuildStringBody— handle the encoding. - Format-aware Go types for path parameters —
format: uuid/email/dateproduce typed wrappers (openapi_types.UUID,openapi_types.Email,openapi_types.Date);format: date-timeproducestime.Time. Required extra imports are emitted automatically. pkg/loader— spec ingestion with auto-conversion of Swagger 2.0 viakin-openapi/openapi2conv. ExportsLoad,WriteV3YAMLJSONOnly,IsJSONContentType.pkg/generator— operation walk, JSON-Schema conversion (draft-07 compatible, recursion-safe via$defs),text/templatedriven Go-source emission with gofmt post-pass.pkg/runtime— MCP-library-agnostic types (MCPServer,Tool,CallToolRequest,CallToolResult), JSON decode helpers (DecodePathParam,DecodeBody,DecodeParamsCombined), functional options (WithNamePrefix,WithExtraProperties).pkg/runtime/gosdk— adapter for the officialmodelcontextprotocol/go-sdk.pkg/runtime/mark3labs— adapter formark3labs/mcp-go. Generated code is unchanged when switching between the two.-openai-compatflag — emits OpenAI-tool-compatible JSON Schema (no$ref, nooneOf/anyOf/allOf,additionalProperties:falseon every object).-emit-v3flag — converts a Swagger 2.0 spec to OpenAPI 3 YAML, pruning non-JSON content types from response bodies. Works around an oapi-codegen v2.7.0 quirk with responses exposed under multiple content types. Request bodies are preserved so downstream oapi-codegen emits the matching Formdata / Multipart / WithBody helpers.-listflag — print operations in the spec and exit.-versionflag — print build metadata (GoReleaser-injectedversion/commit/date, falling back toruntime/debug.BuildInfo).- Examples —
petstore(go-sdk),petstore-mark3labs,swagger2-petstore,users-api,library(v2 → v3 end-to-end),complex(recursive$ref/ oneOf / allOf / enums / formats),non-json-bodies(every non-JSON request kind). - Distribution channels — pre-built binaries on every tagged release (darwin/linux/windows × amd64/arm64), Homebrew formula via
dipjyotimetia/homebrew-tap, and a multi-arch container image atghcr.io/dipjyotimetia/openapi-go-mcp. Driven by.goreleaser.yml; release workflow runs onv*tag push.
- Golden test for generator output (
pkg/generator/golden_test.go); refresh viaUPDATE_GOLDEN=1. - End-to-end OpenAI-compat invariants test running across the petstore and non-JSON-bodies fixtures (
pkg/generator/openai_compat_test.go). - Loader unit tests including
TestPruneNonJSONContent_KeepsRequestBodiesPrunesResponsesandTestLoad_Swagger2_FormDataConverts. - Runtime unit tests for every body builder (
BuildMultipartBodycovers form fields, file fields, multiple-files deterministic ordering, non-string file rejection, missing body;BuildBase64BytesBody/BuildStringBodycover the happy + wrong-type + missing paths). - Stdio end-to-end tests across 5 fixtures (
tests/e2e):- Petstore v3 — basic JSON body and primitive path/query (gosdk + mark3labs adapter parity).
- Users API v3 — UUID path params, multi-path params, required headers, PUT / PATCH / DELETE, no-param operations, bad-UUID error path.
- Library Swagger 2.0 — full v2 → v3 → oapi-codegen → MCP pipeline.
- Complex Schemas — recursive
$refin$defs, oneOf, allOf, enums, date-time/uuid formats, nullable. - Non-JSON bodies — form / multipart (with file part byte-level verification) / octet (base64 round-trip) / text/plain / XML.
- CLI integration tests (
tests/e2e/cli_test.go): build sanity,-list, missing-flag exit,-emit-v3round-trip with response-only pruning, generated-file structural invariants.
Note (historical): this list describes v0.1.0 as released. Several items were addressed later: non-JSON response decoding, nested multipart binary fields, and multipart
encoding[field]content-type metadata shipped in v0.1.1 (see its Added section above); thediscriminatordescription hint also shipped in v0.1.1. The current limitations list lives inarchitecture.md.
- Only
application/jsonresponse bodies are decoded into structured JSON; non-JSON responses are surfaced as raw bytes viaNewToolResultJSON(theTextfield is populated, butStructuredContentmay be malformed for non-JSON payloads). (Superseded in v0.1.1.) - Multipart binary-field rewrite covers only top-level properties; nested binary leaves are not detected. (Superseded in v0.1.1.)
- Multipart
encoding[field]metadata (per-part content-type, custom headers, style) is ignored — every file part is sent asapplication/octet-stream. (Per-part content-type shipped in v0.1.1 for top-level fields; custom headers/style remain unsupported.) - A spec header parameter named
Content-Typeis silently overridden by oapi-codegen's<Op>WithBodyWithResponsefor non-JSON request bodies. (A generator warning for this shipped in v0.1.1.) - Streaming responses (SSE, chunked) surface as raw bytes; no first-class streaming support yet.
- No dynamic (no-codegen, reflection-based) registration path yet. (Superseded by the startup-only
pkg/dynamicpath.) discriminatoris dropped during schema conversion — JSON Schema has no direct equivalent. (Surfaced as a description hint since v0.1.1.)