@namanchopra/mcpify
v0.1.0
Published
Point mcpify at any API spec and get a working, typed MCP server out the other side — no hand-wiring.
Maintainers
Readme
mcpify
Point mcpify at any API spec and get a working, typed MCP server out the other side — no hand-wiring.
mcpify turns an OpenAPI 3.x / Swagger 2.0 spec or a Postman collection into a Model Context Protocol server. A spec is already a machine-readable contract, so producing a correct MCP server from it should be one command — not a hand-authored project. mcpify reads the spec, derives one tool per operation (with input schemas, auth, and safety annotations), and serves it — over stdio or Streamable HTTP.
Status: the core is shipped and covered by an extensive test suite. Working today:
run,inspect,generate,publish,init, andstudio; stdio and Streamable HTTP transports; OpenAPI 3.0/3.1, Swagger 2.0, and Postman inputs; API-key / bearer / basic / OAuth2 client-credentials auth; andtag:/path:/op:filtering. GraphQL input is the main feature still in progress — see Status / roadmap. The few not-yet-available features are marked planned throughout this document.
Why mcpify
Most tools in this space are code generators: they emit a project you then own and maintain. mcpify is built around two ideas.
Two modes — run and generate.
runis dynamic and zero-codegen. mcpify parses the spec in memory and serves the tools immediately. Nothing is written to disk. This is the fastest path from "I have a spec" to "an agent is calling my API."generatescaffolds a self-contained, editable TypeScript project you can customize, check in, publish to npm, list in the MCP Registry, or deploy — for when you need to own and extend the server (seepublish).
Same pipeline, same tool output; you choose whether the result is ephemeral or a project.
Correct-by-construction safety annotations. mcpify derives MCP tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) from the HTTP method, so a client knows which tools are safe to call without asking:
| HTTP method | Safety class | Annotations |
|---|---|---|
| GET, HEAD, OPTIONS | read-only | readOnlyHint: true, idempotentHint: true |
| PUT | idempotent write | destructiveHint: true, idempotentHint: true |
| DELETE | destructive | destructiveHint: true, idempotentHint: true |
| PATCH | non-idempotent write | destructiveHint: true, idempotentHint: false |
| POST | non-idempotent write | destructiveHint: true (overridable), idempotentHint: false |
openWorldHint: true is set on every tool, since each one calls an external API.
Deterministic and offline. The same spec always produces the same tools. No LLM call is required to build a server, so output is reproducible and safe to snapshot in tests.
Quickstart
A 60-second happy path.
1. Serve a spec. No install required:
npx @namanchopra/mcpify run ./openapi.yamlThat starts an MCP server over stdio. If your spec declares an absolute server URL, that's all you need. If it only declares a relative one (e.g. /api/v3), pass the target with --base-url:
npx @namanchopra/mcpify run ./openapi.yaml --base-url https://api.example.com2. See what tools you'll get first (optional). inspect prints the derived tool table without starting a server:
npx @namanchopra/mcpify inspect ./openapi.yamlTOOL METHOD PATH SAFETY REQUIRED
list_pets GET /pets read-only -
create_pet POST /pets non-idempotent-write body
get_pet_by_id GET /pets/{petId} read-only petId
delete_pet DELETE /pets/{petId} destructive petId
4 tools3. Connect from an MCP client. For Claude Desktop, add mcpify to claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"petstore": {
"command": "npx",
"args": ["-y", "@namanchopra/mcpify", "run", "/absolute/path/to/openapi.yaml"],
"env": {
"MCPIFY_APIKEYAUTH_KEY": "your-api-key-here"
}
}
}
}Use an absolute path to the spec, and set only the env vars your spec's auth requires (mcpify prints exactly which ones it needs — see Auth). Restart the client and the tools appear.
Commands
mcpify run <spec>
Start an MCP server for a spec over stdio (the default) or Streamable HTTP (--http).
| Flag | Description |
|---|---|
| --base-url <url> | Override the API base URL from the spec. Required when the spec declares only a relative server URL. |
| --read-only | Expose only safe (GET/HEAD) operations. Non-safe operations are actually removed, not just annotated. |
| --include <patterns...> | Keep only operations matching the given tag(s). |
| --exclude <patterns...> | Drop operations matching the given tag(s). Applied after --include. |
| --verbose | Enable debug-level logging (to stderr; stdout is reserved for the MCP protocol stream). |
| --http, --port <n> | Serve over Streamable HTTP instead of stdio (default port 8080). |
--include/--excludeaccept the full filter grammar:tag:<name>,path:<glob>,op:<operationId>, or a bare token. Put global flags after the spec (e.g.mcpify inspect ./api.yaml --include tag:pet).
mcpify warns when a spec produces a large tool surface (>50 tools) and suggests narrowing it with --include/--exclude/--read-only.
mcpify inspect <spec>
Parse a spec and print the derived tool set (name, method, path, safety class, required args) as a deterministic, greppable table — without starting a server. Honors --read-only, --include, --exclude, and --verbose.
mcpify publish [dir]
Ship a generated project to one or more targets — npm (--npm), the MCP Registry (--registry), and/or a hosted Fly.io endpoint (--deploy) — which compose in a single command. A real publish is gated behind a confirmation prompt (defaults to No; --yes for CI), --dry-run previews exactly what would ship without sending anything, and all credentials come from environment variables — never from flags, files, or logs. See the publishing guide.
mcpify publish ./my-server --npm --registrymcpify generate <spec>
Scaffold a self-contained, editable TypeScript MCP-server project. The generated project depends only on @modelcontextprotocol/sdk, ajv, and ajv-formats — the rest of mcpify's runtime is vendored and the tool set is baked in as data. No secret value is ever written; auth is read from env at runtime.
| Flag | Description |
|---|---|
| --out <dir> | Output directory for the generated project (required). |
| --name <name> | Package name for the generated project (defaults to a slug of the spec title). |
| --force | Overwrite the output directory if it already exists. |
Honors --read-only, --include, --exclude, and --base-url. The generated project serves over stdio (npm start) or Streamable HTTP (npm run start:http), and is ready to publish.
mcpify studio
Launch a local web UI (http://localhost:4000 by default) for building MCP servers from specs: drop or upload a spec, preview every tool it becomes, start a live server on the spot, or download the generated project. Runs entirely on your machine — nothing leaves it. Use --port <n> to change the port and --no-open to skip opening the browser.
mcpify init
Scaffold an mcpify.config.json in the current directory. --yes accepts defaults without prompting; --force overwrites an existing config.
Auth
Secrets are only ever read from environment variables — never from files, flags, or the spec, and never logged. mcpify derives the env var name from the security scheme and tells you exactly which variables to set.
Naming convention (scheme name uppercased, non-alphanumeric characters replaced with _):
| Scheme type | Env var pattern | Example |
|---|---|---|
| API key (header / query) | MCPIFY_<SCHEME>_KEY | MCPIFY_APIKEYAUTH_KEY |
| HTTP bearer | MCPIFY_<SCHEME>_TOKEN | MCPIFY_BEARERAUTH_TOKEN |
| HTTP basic | MCPIFY_<SCHEME>_BASIC | MCPIFY_BASICAUTH_BASIC |
| OAuth2 client-credentials | MCPIFY_<SCHEME>_CLIENT_ID / MCPIFY_<SCHEME>_CLIENT_SECRET | MCPIFY_OAUTH_CLIENT_ID |
| No security schemes declared in the spec | MCPIFY_TOKEN (generic bearer fallback) | MCPIFY_TOKEN |
All of the above work today: API key (header/query), HTTP bearer, HTTP basic, and OAuth2 client-credentials (mcpify fetches and transparently caches the access token). Specs that declare no auth still start; mcpify prints the optional fallback variable you can set. Cookie-based API keys and OAuth2 authorization-code are not yet supported.
Supported inputs
| Input | Status | |---|---| | OpenAPI 3.1 (YAML or JSON, local path or URL) | Supported | | OpenAPI 3.0 (YAML or JSON, local path or URL) | Supported | | Swagger 2.0 (auto-upgraded internally to 3.1) | Supported | | Postman collection (v2.1) | Supported | | GraphQL (SDL file or introspection endpoint) | Planned — the parser exists in the pipeline but is not yet wired into the CLI |
Specs are normalized to OpenAPI 3.1 up front, then dereferenced, so downstream stages work on JSON Schema 2020-12.
Status / roadmap
| Milestone | Scope | Status |
|---|---|---|
| M0 — Recon | Survey SDK/parsers, validate the IR against real specs | Done |
| M1 — Core | OpenAPI 3.x → stdio server; run + inspect; API-key + bearer auth; schema compiler; golden tests | Done |
| M2 — Coverage | All HTTP methods; safety annotations; tag:/path:/op: filtering; config file; Streamable HTTP transport | Done |
| M3 — Generate + Studio | Editable project scaffolding; Swagger 2.0 & Postman end-to-end; generated README + example client config; local studio web UI | Done |
| M4 — Hard auth + shaping | HTTP basic; OAuth2 client-credentials; response size-capping / shaping; SSRF guard | Done |
| M5 — Publish & launch | publish to npm / MCP Registry / hosted (Fly.io); docs & landing site | In progress — publish shipped; npm launch pending |
| Next | GraphQL input wired into the CLI; upstream pagination following; richer response filtering | Planned |
GraphQL is the main input still to land at the CLI (its parser already exists in the pipeline). See the feature roadmap for what's being considered next.
Development
Requires Node.js >= 22. mcpify is written in TypeScript and ships as ESM.
npm install # install dependencies
npm test # run the vitest suite (unit, golden, e2e)
npm run build # compile the CLI to dist/
npm run build:all # compile the CLI + the studio SPA
npm run typecheck # type-check without emittingThe pipeline is a series of pure, independently testable stages: loader → normalizer → build-ir → schema-compiler → tool-builder → executor, emitted onto a low-level MCP Server. Golden-file snapshots lock the deterministic tool output.
See CONTRIBUTING.md for the full contributor guide and SECURITY.md to report a vulnerability.
License
MIT © Naman Chopra
