# MCP-Generator > **Also available in:** [Português (Versão em Português)](README.pt-BR.md) Generate MCP servers from OpenAPI specs. > **Status**: `@christopher_dondici/mcp-gen` 2.3.7 is the latest published version on npm; 2.4.0 is prepared (publication pending). See [release notes](RELEASE_NOTES.md) (PT-BR). `mcp-gen` turns an OpenAPI v3 or Swagger 2.0 spec into an MCP server in **TypeScript**, **Python**, or **Go**. It maps each route to a tool, generates typed models (including enums, oneOf/anyOf), and keeps custom code when you regenerate. ## What's new in 2.4.0 (Minor release — no breaking changes. Prepared, publication pending. Includes the unreleased 2.3.8 content.) - Inline `oneOf`/`anyOf` variants become synthetic union members with expanded properties instead of warnings; `discriminator` stays advisory-only. - Nested inline `allOf` members expand recursively; `requestBody.$ref` to `schemas/*` resolves as the `body` param (to `parameters/*` warns instead of dropping silently). - `$ref` parameters via `components.parameters` are resolved; unresolvable ones warn; `pnpm-lock.yaml` and `bun.lock`/`bun.lockb` are skipped by the credential scan. - Also: SDK 1.30.0 → 1.32.1, `proxy-addr` → 2.0.8, `handlebars` → 4.7.10 (prod audit clean); streamed remote reads with 50MB cap; CI on Node 22 with pinned `ubuntu-24.04`; 4 Wave 1 lows. - Local verification: 19 Jest suites / 265 tests, CLI exit-code smoke 4/4, TypeScript/Python/Go generated-server smokes, `npm audit --omit=dev` clean. ## What's new in 2.3.7 ## What's new in 2.5.0 (Minor release — no breaking changes.) - Remote URL `watch` retries transient fetch failures instead of dropping the polling cycle: network errors and `408`/`425`/`429`/`500`/`502`/`503`/`504` responses are retried with exponential backoff, while other `4xx` responses fail immediately. - New `--retries ` (default `2`) and `--retry-delay ` (default `500`) flags control the retry budget and the base backoff, which doubles on each attempt. `--retries 0` keeps the previous single-attempt behaviour. - Fetch failures now carry the HTTP status code, so callers can branch on it without parsing error messages. - Local verification: 19 Jest suites / 272 tests, HTTPS retry smoke against a live TLS server (503, 503, 200 → success), lint + typecheck clean. (Patch release — no breaking changes.) - Tool names use the sanitized `operationId` when present, with fallback to `method_path`. - `allOf` with `$ref` merges referenced properties; `requestBody` resolves via `components.requestBodies`; `trace` is a supported method. - `security --json` prints pure JSON on stdout for CI parsing; `--plugin` accepts a directory or a module file. - URL `watch` validates the URL, enforces a 30s timeout and content checks, and compares by SHA-256 hash. - `security-lint` has fewer false positives (anchored base64 regex, lockfiles skipped, all specs scanned). - CI adds generated-Python smoke and production dependency audit. - Local verification: 19 Jest suites / 246 tests, CLI exit-code smoke 4/4, lint + typecheck clean. ## What's new in 2.3.6 (Patch release — no breaking changes.) - Invalid `watch --interval` now fails with an explicit error instead of silently falling back to 30s. - `init` accepts `--timeout ` and `--max-bytes ` for the registry download (defaults 30s / 50MB) with explicit validation. - Swagger 2.0 conversion reports fidelity warnings (global `body` params, `file` outside `formData`, non-csv `collectionFormat`). - Ignored `discriminator` now warns per schema (advisory only, nothing breaks). - `LINT-TODO-IN-GENERATED` no longer fires inside `examples/`. - CI now runs on `ubuntu-latest` + `windows-latest`. - Local verification: 19 Jest suites / 246 tests, CLI exit-code smoke 4/4, lint + typecheck clean. ## What's new in 2.3.5 (Patch release — no breaking changes.) - Operation allowlist `METHOD path` now matches case-insensitively (`get /pets` = `GET /pets`). - Filters that match zero tools emit a `Filters matched 0 of N tools` warning suggesting `--dry-run`. - Go incremental regeneration uses the Go default stub (`handler not implemented`); untouched stubs are no longer preserved as custom. - Non-JSON request bodies and response examples fall back to the first content-type when `application/json` is absent (covers `multipart/form-data` and `urlencoded` from Swagger 2.0 `formData` conversion). - Local verification: 19 Jest suites / 244 tests, CLI exit-code smoke 3/3, TypeScript/Python/Go generated-server smokes, `npm audit --omit=dev` clean. ## What's new in 2.3.4 (Patch release — no breaking changes.) - `ip-address` 10.4.0 → 10.7.2 through the SDK transitive chain (`express-rate-limit` `^10.2.0`), so `npm audit --omit=dev` is clean again. - New `tests/scaffold-lockfile.test.ts` guard: scaffold `package.json.hbs` ranges against the `package-lock.json.hbs` snapshot, plus an `ip-address` floor above 10.5.0 in both project and scaffold lockfiles. - Dev-only `js-yaml` finding stays documented in `SECURITY.md`, with no broad Jest upgrade on the 2.3.x line. - Local verification: 19 Jest suites / 238 tests, CLI exit-code smoke 3/3, TypeScript/Python/Go generated-server smokes, `npm audit --omit=dev` clean. ## What's new in 2.3.3 (Patch release — no breaking changes.) - Missing `--env-file` paths now fail with an explicit error instead of being silently ignored. - The interactive `init` flow shows Go next steps (`go mod tidy && go run .`) instead of suggesting `pip install`. - Placeholder links in generated READMEs and SECURITY docs replaced with the official repository links. - `dist` is cleaned before every build, so stale artifacts can't leak into builds or tarballs. - Local verification: 18 Jest suites / 234 tests, CLI exit-code smoke 3/3, TypeScript/Python/Go generated-server smokes, `npm audit --omit=dev` clean. ## What's new in 2.3.2 (Patch release — no breaking changes.) - `js-yaml` and `openapi-types` are now direct dependencies instead of transitive ones; YAML spec scanning in security-lint uses a typed import. - Registry URL validation is covered by real tests: non-HTTPS, unknown and removed keys fail without calling `fetch`. - Trailing `/**` path globs also match the base path, so `/pets/**` includes `/pets`. - Incremental markers gained a Go default-stub pattern plus round-trip coverage for `` guards alongside the legacy `@@mcp-gen` markers. - New Go compilation smoke (`npm run test:generated:go`): the Petstore Go scaffold runs `go mod tidy` + `go build`, also gated in CI with Go 1.22. - Local verification: 17 Jest suites / 232 tests, CLI exit-code smoke 3/3, TypeScript and Go generated-server smokes, `npm audit --omit=dev` clean. ## What's new in 2.3.1 (Patch release — no breaking changes.) - Generated TypeScript projects include `package-lock.json`, so their CI and Docker `npm ci` commands work from a fresh checkout. - `--force` now takes precedence when combined with `--incremental`, discarding preserved handlers as documented. - `watch --once` returns exit code 1 on fetch, parse, or generation failures and uses Commander's async action flow. - ESLint is installed locally with a minimal TypeScript flat config and runs in both CI and release. - Local verification: 16 Jest suites / 214 tests, CLI exit-code smoke, TypeScript and Python generated-server smoke, and `npm pack --dry-run`. ## What's new in 2.3.0 (Fase 2 — anchor: unlocks the registry, no breaking changes.) - Swagger 2.0 support: v2 specs are converted to v3 internally on ingest (`host`/`basePath`/`schemes` → `servers`, `definitions` → `components.schemas`, body/formData → `requestBody`, `securityDefinitions` → `securitySchemes`). `validate` + `generate` accept v2 files (see `examples/swagger-v2-petstore.json`). - Registry re-enabled: `slack`, `kubernetes`, `digitalocean` are back (v2, converted on the fly); only `azure` stays removed (it was a types fragment, not a full spec). - Scale benchmark: `examples/large-scale.json` (180 ops, 10 tags) proves `180 → 10 tools` with `--group-by tag` (also `10` with `path-prefix`). See [Benchmark](#benchmark). ## What's new in 2.2.0 (previous) (Fase 1 — solid base, no breaking changes.) - `generate --dry-run` lists tools/models/groups/files without writing anything; `--json` prints a machine-readable summary (Codex-friendly, no chalk noise). - `watch` accepts the same filter/group flags as `generate`, and the interactive mode asks for filters and grouping. `watch --once` exits after the first generation on file inputs too. - `validate` (and `generate`) warn per affected schema when `allOf` `$ref`s are skipped or inline `oneOf`/`anyOf` variants are dropped (partial support is no longer silent). - OSS hygiene: CONTRIBUTING updated, `MCP_GEN_ALLOW_PLUGINS` documented in Plugins. ## What's new in 2.1.5 (previous) (Fase 0, PR #4 — P0 fixes on top of 2.1.4.) - TypeScript client serializes query params (`queryNames` + `URLSearchParams`); `get_pets({ limit: 5 })` calls `/pets?limit=5`. - Python server passes query and headers (`_build_query` / `_build_headers`, `kwargs["params"]`) in `--http` mode, including grouped tools. - Go `--http` mode wired to the real `APIClient` (`__client.do(...)`, `q.Encode()`, `PathEscape`), no more `not yet wired` stubs. - Registry is v3-only (`stripe`, `github`, `openai`, `petstore`, `twilio`, `shopify`); removed keys fail with guidance and unknown keys list `Known keys`; v2 specs fail with `Only OpenAPI v3`. ## What's new in 2.1.4 (previous) (The `v2.1.3` tag was superseded before reaching npm; everything below shipped in 2.1.4, plus a fix for the generated auth middleware on specs without `securitySchemes`.) - Path filtering with globs: `--path-prefix "/users/**"`, `--include-paths`, `--exclude-paths`; inline `--operation-allowlist op1,op2` (file still supported). - Aggregation with `--group-by tag | path-prefix`: one logical tool per tag or path segment, routing internally by `action` (operation name + method). - Name dedup: collisions fall back to method suffix, then short path hash. - Incremental guards: `` regions plus per-tool `@@mcp-gen` markers, 3-way merge on `--incremental`, `--force` to overwrite. - Separate auth middleware (`src/auth.ts`, `auth.py`, `auth.go`) generated from `securitySchemes`, and `handlers.custom.*` files that are never overwritten without `--force`. ## Quick start With Git, Node.js 20+ and npm 9+ installed, run: ```bash git clone https://github.com/ChristopherDond/MCP-Generator.git cd MCP-Generator npm ci npm run build node dist/cli/index.js --version ``` Generate a server from a local spec: ```bash node dist/cli/index.js generate -i examples/petstore.yaml -l typescript -o ./my-server ``` Validate a spec without generating files: ```bash node dist/cli/index.js validate -i examples/petstore.yaml ``` Run these commands from the repository root on `main`. The build and packaging fixes are part of 2.1.2. Generation writes a scaffold; it does not install dependencies, build, or start the generated server. Run the interactive CLI if you prefer prompts: ```bash npm run dev ``` ## What it does ```mermaid sequenceDiagram participant User participant CLI participant Parser participant Generator participant Output User->>CLI: mcp-gen generate --input api.yaml --lang go CLI->>Parser: validate and parse OpenAPI v3 / Swagger 2.0 (JSON or YAML) Parser->>Generator: internal AST (tools, models, examples) Generator->>Output: render Handlebars templates Output-->>User: TypeScript, Python, or Go MCP server project ``` Each route becomes an MCP tool with: - typed input from parameters (path, query, header, cookie, body) and request bodies - example responses from the spec - enum / oneOf / anyOf / discriminator schema support - real HTTP client mode (`--http`) that calls the actual API - scaffolded authContext checks for scoped metadata and credential-like argument keys; review before deployment - optional incremental code preservation ## Requirements - Node.js 20+ - npm 9+ (the source quick start uses the repository lockfile) - Git to clone the repository - (Optional) Python 3.8+ for Python projects - (Optional) Go 1.22+ for Go projects ## Local installation and command shorthand Install the latest release with `npm install -g @christopher_dondici/mcp-gen@2.3.7`. To work from source, use the build in [Quick start](#quick-start). Throughout this README, `mcp-gen` is shorthand for `node dist/cli/index.js` from the repository root. For example, `mcp-gen validate -i examples/petstore.yaml` means `node dist/cli/index.js validate -i examples/petstore.yaml`. Optionally, run `npm link` from the repository root after building to make the `mcp-gen` command point to your local checkout. This changes npm's global links; it does not download a published `@christopher_dondici/mcp-gen` package. The npm package name changed because `mcp-gen` was rejected for similarity to `mcpgen`; the command remains `mcp-gen`. To install a locally produced tarball without publishing: ```bash npm install ./christopher_dondici-mcp-gen-2.3.7.tgz ./node_modules/.bin/mcp-gen --version ./node_modules/.bin/mcp-gen validate -i node_modules/@christopher_dondici/mcp-gen/examples/petstore.yaml ``` ## CLI ### Commands - `mcp-gen generate` or `mcp-gen g` creates a server from a spec. - `mcp-gen validate` or `mcp-gen v` checks a spec with detailed warnings (name collisions, missing examples, unsupported schemas). - `mcp-gen init` downloads a known public spec and can generate a project. - `mcp-gen watch` watches a file or URL and regenerates on changes. ### Generate ```bash mcp-gen generate -i ./api/openapi.yaml -l typescript -o ./my-server mcp-gen generate -i ./api/openapi.yaml -l python -o ./my-server mcp-gen generate -i ./api/openapi.yaml -l go -o ./my-server ``` **Useful flags:** - `--force`, `-f` overwrites existing files, ignoring preserved handlers and custom files (skips 3-way merge). It wins when combined with `--incremental`. - `--incremental` keeps code between `@@mcp-gen:start` and `@@mcp-gen:end` (also ``). Uses 3-way merge: base stub vs your custom code vs new template. - `--http` generates handlers that **call the real API** over HTTP instead of returning example stubs. - `--env-file ` embeds TOKEN/BASE_URL from a .env-style file into the generated client. - `--name ` sets the server name. - `--server-version ` sets the server version. - `--plugin ` loads a plugin module or folder (can be repeated). - `--include-tags ` only includes tools with one of these tags. - `--exclude-tags ` excludes tools with these tags. - `--path-prefix ` only includes paths matching a prefix or glob (`/users`, `/users/**`, `/pets/*`). - `--include-paths ` comma-separated path globs to include. - `--exclude-paths ` comma-separated path globs to exclude. - `--operation-allowlist ` comma-separated `operationId`, tool name, or `METHOD /path` list, or a path to an allowlist file (JSON array or line/comma separated). - `--group-by ` aggregates to one logical tool per group: `tag` or `path-prefix`. Each group routes by `action` (operation name) internally. - `--dry-run` lists tools/models/groups/files that would be generated without writing anything. - `--json` prints the generation summary as machine-readable JSON (pairs with `--dry-run` for scripting). ### Filtering examples ```bash mcp-gen generate -i api.yaml -o ./out --include-tags pets,orders mcp-gen generate -i api.yaml -o ./out --exclude-tags admin mcp-gen generate -i api.yaml -o ./out --path-prefix "/users/**" mcp-gen generate -i api.yaml -o ./out --include-paths "/users/**,/orders/*" --exclude-paths "/users/internal/*" mcp-gen generate -i api.yaml -o ./out --operation-allowlist listPets,createPet mcp-gen generate -i api.yaml -o ./out --operation-allowlist ./allow.json mcp-gen generate -i api.yaml -o ./out --include-tags pets --group-by tag ``` ### Grouping `--group-by tag` emits one tool per tag (plus `untagged`), e.g. 200 operations across 8 tags become ~8 tools. `--group-by path-prefix` emits one tool per first path segment (`/users/**` becomes `users_group`). Each grouped tool takes a required `action` enum (member operation names) and routes internally by `METHOD` + `path`. Member params are unioned as optional. ### Benchmark Measured on `examples/large-scale.json` (180 ops across 10 tags, 2 models): | Mode | Tools | |------|-------| | no grouping | 180 | | `--group-by tag` | 10 | | `--group-by path-prefix` | 10 | `180 → 10 tools` — grouping cuts the surface by 18x on this fixture. Covered by `tests/scale.test.ts`. ### Tool name dedup Tool names come from `METHOD + path` (`GET /pets/{id}` becomes `get_pets_petid`). `operationId` is stored for allowlist matching. On collision the generator suffixes with the method first, then with a short path hash, instead of emitting duplicate tools. ### Auth middleware Generated projects include a separate auth layer built from `securitySchemes`: - TypeScript: `src/auth.ts` - Python: `auth.py` - Go: `auth.go` Put business logic in guards; keep auth and schema validation in the middleware so you do not need a guard for auth. ### How not to overwrite your edits Generated handlers are wrapped in two markers: ```typescript // // @@mcp-gen:start:get_pets // ... your code here ... // @@mcp-gen:end:get_pets // ``` Rules: 1. Edit only between `@@mcp-gen:start:` and `@@mcp-gen:end:` (or `>`). That body is preserved on regen. 2. Put reusable business logic in `src/handlers.custom.ts` (TS), `handlers_custom.py` (Python), or `handlers_custom.go` (Go). That file is created once and never overwritten unless you pass `--force`. 3. Re-run with `generate --incremental`. The generator does a 3-way merge (fresh stub vs your custom body vs new template) and reports `preserved` handlers plus `Merged ... custom handlers preserved`. Pass `--force` to ignore preservation and overwrite everything; force also wins if both flags are present. ### Validate (v2.1+) ```bash mcp-gen validate -i ./api/openapi.yaml ``` Outputs a rich report: ``` Spec is valid Tools: 12 Models: 8 Base URL: https://api.example.com 2 warning(s): ⚠ Tool name collision resolved: "get_users" appears 2x (unique suffixes added) ⚠ 3 tool(s) have no example response: get_users_id, delete_user, patch_user ``` ### Security and lint (v2.1.1) ```bash node dist/cli/index.js security -p ./my-server node dist/cli/index.js security -p ./my-server --fail-on-warn ``` Scans generated files for credential-like patterns, authorization-related identifiers, naming, descriptions, and incremental markers. `--json` prints a JSON report, but the CLI also prints a header; stdout is not a pure JSON document. Errors cause exit code 1; `--fail-on-warn` also fails on warnings. This is static analysis, not a security guarantee. ### Init `init` uses the built-in registry: ```bash mcp-gen init --from list mcp-gen init --from stripe mcp-gen init --from stripe --generate -o ./stripe-mcp ``` Available registry keys: | Key | Description | |-----|-------------| | `stripe` | Stripe Payment API | | `github` | GitHub REST API | | `openai` | OpenAI API | | `petstore` | Swagger Petstore example | | `twilio` | Twilio Communications API | | `shopify` | Shopify Admin API | | `slack` | Slack Web API (Swagger 2.0, converted) | | `kubernetes` | Kubernetes API (Swagger 2.0, converted) | | `digitalocean` | DigitalOcean API (Swagger 2.0, converted) | OpenAPI v3 and Swagger 2.0 are supported (v2 is converted to v3 on ingest). Only `azure` stays removed — it pointed at a types fragment, not a full spec. ### Watch ```bash mcp-gen watch -i ./api/openapi.yaml -o ./my-server mcp-gen watch -i https://example.com/spec.json --interval 60000 ``` For URL inputs, `--interval ` controls the polling interval. `--once` runs one generation immediately and exits. Fetch, parse, or generation failures return exit code 1 instead of a false success. Transient fetch failures on URL inputs are retried with exponential backoff — network errors and `408`/`425`/`429`/`500`/`502`/`503`/`504` responses, while other `4xx` responses fail immediately. `--retries ` (default `2`) sets the retry budget and `--retry-delay ` (default `500`) the base backoff, doubling each attempt. Use `--retries 0` for a single attempt. ```bash mcp-gen watch -i https://example.com/spec.json --retries 5 --retry-delay 1000 mcp-gen watch -i https://example.com/spec.json --once --retries 3 ``` `watch` accepts the same filtering flags as `generate` (`--include-tags`, `--exclude-tags`, `--path-prefix`, `--include-paths`, `--exclude-paths`, `--operation-allowlist`, `--group-by`), plus `--http`, `--force`/`--incremental`: ```bash mcp-gen watch -i ./api/openapi.yaml -o ./my-server --include-tags pets --group-by tag --once ``` ## Plugins Plugins can override templates and register extra Handlebars helpers. Basic structure: - `templates/typescript/...`, `templates/python/...`, or `templates/go/...` for `.hbs` template overrides - `index.js` that exports `registerHandlebars(handlebars)` for custom helpers Example: ```bash mcp-gen generate -i ./api/openapi.yaml --plugin ./my-plugin mcp-gen watch -i ./api/openapi.yaml --plugin ./my-plugin ``` Plugin templates override core templates when they use the same path under `templates//`. > **Plugin code execution gate:** template overrides always apply, but a plugin's JS module (`registerHandlebars`) is only loaded when `MCP_GEN_ALLOW_PLUGINS=true` is set. Without it, `--plugin` only provides template overrides. Never enable the variable with untrusted plugins — see [SECURITY.md](SECURITY.md). ## Generated project structure **TypeScript:** ``` my-server/ ├── src/ │ ├── server.ts # MCP server — tool definitions + handlers │ ├── auth.ts # Auth/validation middleware from securitySchemes │ ├── handlers.custom.ts # Your code — never overwritten without --force │ ├── models.ts # TypeScript interfaces from OpenAPI schemas (enums, unions) │ └── client.ts # HTTP client (used in --http mode) ├── .github/ │ └── workflows/ │ └── ci.yml ├── Dockerfile ├── package.json ├── package-lock.json ├── tsconfig.json └── README.md ``` **Python:** ``` my-server/ ├── server.py # FastMCP server — tool definitions + handlers ├── auth.py # Auth/validation middleware from securitySchemes ├── handlers_custom.py # Your code — never overwritten without --force ├── models.py # Pydantic models from OpenAPI schemas (enums, unions) ├── requirements.txt ├── .github/ │ └── workflows/ │ └── ci.yml ├── Dockerfile └── README.md ``` **Go (new in v2.1):** ``` my-server/ ├── main.go # MCP server using mark3labs/mcp-go ├── auth.go # Auth/validation middleware from securitySchemes ├── handlers_custom.go # Your code — never overwritten without --force ├── models.go # Go types from OpenAPI schemas (enums, unions) ├── client.go # HTTP client (used in --http mode) ├── go.mod ├── .github/ │ └── workflows/ │ └── ci.yml ├── Dockerfile └── README.md ``` --- ## Connect to Claude Desktop **TypeScript:** ```json { "mcpServers": { "my-server": { "command": "node", "args": ["/absolute/path/to/my-server/dist/server.js"] } } } ``` **Python:** ```json { "mcpServers": { "my-server": { "command": "python", "args": ["/absolute/path/to/my-server/server.py"] } } } ``` **Go:** ```json { "mcpServers": { "my-server": { "command": "go", "args": ["run", "/absolute/path/to/my-server/main.go"] } } } ``` Restart Claude Desktop. Your API tools appear automatically. --- ## Security & `authContext` Contract The generated tools expect **scoped authorization metadata** (not raw credentials): ```json { "tokenId": "tok_abc123", "principal": "user:42", "expiresAt": "2026-05-11T14:00:00Z", "allowedTools": ["get_orders"], "endpointAllowlist": ["GET /orders"], "spendLimitUsd": 5, "spendUsedUsd": 1.2, "revoked": false, "requestId": "req_01J..." } ``` The scaffold blocks arguments like `token`, `authorization`, `api_key`, `client_secret`, `password`, `secret` by default. **Quick example (env var):** ```bash # Linux / macOS export TOKEN=your_api_key_here # Windows (PowerShell) $env:TOKEN='your_api_key_here' ``` For advanced integrations and management, consider Cohesivity.ai as a backend for auth, storage, and revocation policies. --- ## Implement handlers Generated files return spec examples by default. Replace stubs with real logic. **TypeScript** (`src/server.ts`): ```typescript case "get_users_id": { // @@mcp-gen:start:get_users_id const user = await db.users.findById(args.id); return { content: [{ type: "text", text: JSON.stringify(user) }] }; // @@mcp-gen:end:get_users_id } ``` **Python** (`server.py`): ```python @mcp.tool() async def get_users_id(id: float, auth_context: dict | None = None) -> Any: # @@mcp-gen:start:get_users_id user = await db.users.find_by_id(id) return user # @@mcp-gen:end:get_users_id ``` **Go** (`main.go`): ```go s.AddTool(get_users_idTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { // @@mcp-gen:start:get_users_id return jsonSerialize(jsonExample(`{"id": 1, "name": "Alice"}`)) // @@mcp-gen:end:get_users_id }) ``` Code between `@@mcp-gen:start` and `@@mcp-gen:end` markers is preserved when you re-run `generate --incremental` (see [How not to overwrite your edits](#how-not-to-overwrite-your-edits)). --- ## Programmatic API (Library Mode) With the package installed from npm, import the scoped package as shown below. From the repository root after building, use `"./dist/index.js"` instead. ```typescript import { generate, validateSpec, parseOpenAPI } from "@christopher_dondici/mcp-gen"; const result = await generate({ input: "./api/openapi.yaml", lang: "typescript", out: "./my-server", force: true, incremental: false, http: false, }); const validation = await validateSpec("./api/openapi.yaml"); console.log(validation.tools, validation.models, validation.warnings); ``` --- ## Development ```bash npm run lint npx tsc --noEmit npm test npm run test:cli npm run test:generated npm run test:generated:py # TypeScript example node dist/cli/index.js generate --input examples/petstore.json --out /tmp/ts-test --force # Python example node dist/cli/index.js generate --input examples/petstore.yaml --lang python --out /tmp/py-test --force # Go example node dist/cli/index.js generate --input examples/petstore.json --lang go --out /tmp/go-test --force # HTTP mode (real API calls) node dist/cli/index.js generate --input examples/petstore.json --lang typescript --out /tmp/ts-http --force --http # Incremental example node dist/cli/index.js generate --input examples/petstore.json --out /tmp/ts-test --incremental ``` --- ## Roadmap | Stage | Status | Scope | |-------|--------|-------| | Existing features | Implemented | CLI, OpenAPI v3 parser, TypeScript/Python generation, incremental generation, interactive mode, spec registry, plugins | | v2.1.0 | Tagged | Go target, HTTP mode, enums, header/cookie params, library API, rich validate | | v2.1.1 | Tagged | Static security/lint scanning and Go server template checks; TypeScript/Python templates unchanged from v2.1.0 | | v2.1.2 | Released on npm | Portable template copy, lockfile, package allowlist, prepack build, corrected release workflow, CI tarball smoke test, dependency updates | | v2.1.3 | Tagged only, superseded (never published to npm) | Feature branch content, replaced by 2.1.4 before publication | | v2.1.4 | Released on npm | Path glob filters, inline operation allowlist, group-by tag/path-prefix with action routing, method/hash dedup, `` guards with 3-way merge, separate auth middleware, never-overwritten `handlers.custom.*`, auth template fix for specs without `securitySchemes` | | v2.1.5 | Released on npm | Fase 0 P0 fixes (PR #4): TS query serialization, Python query/headers, Go HTTP wiring, v3-only registry with guidance | | v2.2.0 | Released on npm | Fase 1: `generate --dry-run` + `--json` summary, filter/group flags on `watch` (+ interactive prompts, `--once` file fix), per-schema partial-support warnings in `validate`/`generate`, CONTRIBUTING + `MCP_GEN_ALLOW_PLUGINS` docs | | v2.4.0 | Released on npm | Inline oneOf/anyOf variants as synthetic union members, nested inline allOf expansion, requestBody $ref to schemas/* resolved, $ref params resolved, pnpm/bun lockfiles skipped; includes unreleased 2.3.8 content | | v2.5.0 | Released on npm | Remote `watch` retries transient fetch failures with exponential backoff (`--retries`, `--retry-delay`), typed `HttpFetchError` | | v2.3.8 | Superseded by 2.4.0 (never published) | SDK 1.32.1 + `proxy-addr` 2.0.8 + `handlebars` 4.7.10 (prod audit clean), streamed remote reads with size cap, 4 Wave 1 lows, CI on Node 22 + pinned `ubuntu-24.04` | | v2.3.7 | Released on npm | `operationId` tool names, `allOf` $ref merge, `requestBody` via `requestBodies`, `trace` support, pure `security --json`, hardened URL watch, quieter security-lint, Python smoke + prod audit in CI | | v2.3.6 | Released on npm | Explicit `watch --interval` error, `--timeout`/`--max-bytes` on `init`, Swagger 2.0 fidelity warnings, `discriminator` warning, TODO lint skips `examples/`, CI on Ubuntu + Windows | | v2.3.5 | Released on npm | Case-insensitive allowlist METHOD, zero-filter warning with `--dry-run` hint, Go stub pattern on incremental regen, non-JSON body/example fallback | | v2.3.4 | Released on npm | `ip-address` 10.4.0 → 10.7.2 via SDK chain, scaffold lockfile snapshot guard, dev-only `js-yaml` stays documented | | v2.3.3 | Released on npm | Explicit missing `--env-file` error, Go next steps in interactive `init`, placeholder links replaced, `dist` cleaned before build | | v2.3.2 | Released on npm | Direct js-yaml/openapi-types deps, real registry validation tests, trailing `/**` matches base path, Go stub pattern + guard round-trip, Go build smoke in CI | | v2.3.1 | Released on npm | TypeScript scaffold lockfile, force-over-incremental precedence, reliable `watch --once` exit codes, reproducible lint gate | | v2.3.0 | Released on npm | Fase 2: Swagger 2.0 → v3 conversion on ingest, `slack`/`kubernetes`/`digitalocean` back in the registry, `examples/large-scale.json` benchmark (180 → 10 tools) | | Distribution | Verified for 2.3.7 | Registry installation works via `npm install -g @christopher_dondici/mcp-gen`; pip publication is not established. Python is a generation target, not a pip installation path for this CLI | | Future | Planned | Streaming/resources/prompts, more registries | --- ## Known limitations - Swagger 2.0 is converted to OpenAPI 3.0.3 on ingest (body/formData → `requestBody`, `definitions` → `components.schemas`); exotic v2 constructs may lose fidelity - `oneOf` / `anyOf` inline variants expand into synthetic union members; `discriminator` schemas generate union types but no runtime validation - Security/lint scanning uses static text patterns and can produce false positives or miss issues. A passing report does not guarantee security or verify runtime authorization, revocation, spending, or audit logging - Generated authorization checks are scaffolding, not a complete security backend; review and test them before deployment - Streaming/resources/prompts are not implemented The `copy-templates` fix included in 2.1.2 uses Node.js `fs.cpSync` on Windows, Linux, and macOS; it no longer requires `cp` or `xcopy`. CI currently runs on Ubuntu only. --- ## License MIT © 2026 - Christopher D.