
mcpify
io.github.furkan708Published by GitHub account furkan708v1.19.0Updated Oct 24, 2026
Focused, production-ready CLI: turn any OpenAPI REST API into an MCP server.
The publisher's own server: MCPify
Overview
CLI that turns any OpenAPI REST API into an MCP server, exposing each API operation as a callable tool for MCP clients.
- What you can do
- Generate MCP tools from an OpenAPI 3.x or Swagger 2.x spec, one tool per operation, with typed arguments and resolved references
- Preview and audit the generated surface: list tools, price their context cost, and run a doctor check on spec quality
- Serve the tools over stdio or HTTP/SSE, including several APIs in one server with per-API auth, caching, retries and rate limits
- Call tools without an agent client, serve a schema-shaped mock API, or bake a serve command into a shareable script
- Compare two spec versions for breaking changes and gate CI on the result
- Apply governance options: read-only mode, allow/deny filters, per-token RBAC, response projection, secret masking, audit log, metrics…
- When to use it
- Use it when you have an OpenAPI spec and want an assistant to call that REST API directly, without writing a bespoke MCP server. It also suits teams that need read-only limits, credential handling, or a shared HTTP-hosted server for several APIs.
- Requirements
- Runs locally as a Python CLI, installed from PyPI (pipx or uvx) or as a container; Python 3.10-3.12. YAML specs need the optional yaml extra. Credentials are supplied through environment variables named on the command line, and network access to the target API is required.
Installation
In SourceWeft
- Open mcpify in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
mcpify
[Tests] [CI] [CodeQL] [PyPI] [PyPI Downloads] [Python] [License] [MCP Registry] [Dependencies]
English | Türkçe
[mcpify in action — listing and serving OpenAPI endpoints as MCP tools]
Turn any OpenAPI REST API into an MCP server — so Claude Code, Cursor, and every other MCP client can call your API directly. One command, zero runtime dependencies:
Focused, production-ready, CLI-first: one job (OpenAPI → MCP). Everything else — governance, credentials, token economics, operations — is opt-in and stays out of the way until you need it:
- Safe for agents by default — lazy context budget (
--lazy), secret masking (--redact), blast-radius limits (--read-only, per-token RBAC) - Ready for real deployments — stdio + HTTP/SSE, OAuth2 and split read/write credentials, health probes, audit trail, metrics, multi-API serving, hot reload
- Proven, not promised — 520 tests across twenty-eight suites, a hostile-spec corpus, live-CI checks, zero runtime dependencies
Why you'll like it
From spec to server
- 60 seconds to working — point it at any OpenAPI 3.x spec (file or URL)
- Every operation becomes a first-class MCP tool — input schemas are generated from
parameters+requestBody, internal$refs are resolved - Spec versions diffed from the tool view —
mcpify diff old.yaml new.yamlreports added/removed/changed operations with per-change breaking verdicts and a migration guide;--fail-on-breakingis a CI gate mcpify doctor— tells you if your spec is agent-friendly before you ship: missing operationIds, missing summaries, instruction-like tool text, overlong descriptions;--probedials the API once — with your real credential (--auth-env) when you want auth proven end-to-end, and--fail-on-http-errorfor a strict CI gatemcpify try/mcpify mock/mcpify output-server— call the tools without an agent client, serve a schema-shaped fake API for CI, or bake a serve command into a shareable script
Credentials & policy
- Credentials never touch the spec or the model — pulled from your environment at call time; the spec's own security declarations pick the flags (bearer, basic, header, query)
- OAuth2 client-credentials built in — tokens are fetched, cached, refreshed and re-fetched on a mid-flight 401 (RFC 6749, stdlib only);
--write-oauth2-*gives non-GET calls a second client identity so reads and writes authenticate as different clients - Least-privilege by default —
--write-auth-envsplits the static credential (reads on your read key, writes on a dedicated key),--read-onlyfilters the surface,--deny/--allowhides mutating GETs, per-token RBAC gives each bearer token its own allow/deny scopes --redact password,token— values whose key names a secret are masked with***at every level of every response (error bodies included, case-insensitive); the model never sees them- Audit trail without content exposure — one JSON line per call: tool, API, status, latency, an argument fingerprint (never raw arguments);
--pluginloads your Python module for auth/request/result hooks
Token economics
- See the bill before serving —
mcpify list --costprices the surface (~4 chars/token): what every agent pays in EVERYtools/list; multi-API configs get per-API and total prices in one run --fields id,event— response projection that selects at every level: selected keys keep their value, non-selected containers stay transparent, emptied containers drop. Live weather.gov: 350 alerts in full inside the budget that previously truncated at ~189- Valid truncation — oversized responses are cut along JSON structure with an explicit
"truncated": truemarker, never mid-document --lazysearch-then-call — cut api.weather.gov's listing by 95.5%; search results now show what pulling each full schema would cost, so the agent pulls only what it needs[tool-text]overrides — doctor flags model-facing instruction-like descriptions; you replace them per tool in config
Operations
- Two transports, one tool surface — stdio for local agents;
serve --http 8080speaks MCP Streamable HTTP (SSE responses for clients that ask, JSON otherwise) so a whole team shares one server, with optional bearer tokens - Several APIs, one MCP server —
[apis.NAME]sections in.mcpify.toml: per-API auth, caching, retries, filters and rate limits; collision-safe renames; aggregated health;mcpify statusprobes every API in parallel - Upstream courtesy built in — ETag-aware caching, idempotent-only retries (502/503/504),
--wait-on-429honors Retry-After,--rate-limit RPScaps requests/second (per upstream in multi-API, retries included) - Observability, opt-in only — Prometheus
--metrics(call counters, latencies, cache, health — plus projection/redaction counters when those run),--otelspans,--reloadhot swap,mcpify uilocal dashboard - Host it yourself for free — docker-compose with automatic-HTTPS Caddy plus a hardened systemd unit: Self-hosting guide
- Zero runtime dependencies — the entire tree is auditable stdlib Python; YAML specs need an optional
pip install 'mcpify[yaml]'
Quick start
With authentication
No explicit style needed in the common case — the spec's security
declarations pick bearer/basic/header/query (with the right name) for
you. For HTTP Basic, the env variable holds username:password:
--auth-style basic --auth-env CREDS.
With OAuth2 (client credentials)
For APIs behind an OAuth2 identity provider (RFC 6749 §4.4). Credentials
live in the environment; the access token is fetched, cached until its
expires_in, refreshed transparently, and re-fetched automatically once
if the API answers 401 mid-flight:
Split write identities too: --write-oauth2-token-url (+ client/scope
flags) runs a second client-credentials flow for non-GET calls — reads
authenticate as the read client, writes as the write client, each with
its own token cache and the same 401 self-heal. Mutually exclusive with
--write-auth-env (pick one credential kind for writes).
Multiple APIs in one server
Put several OpenAPI documents in one config and serve them as a single tool surface — no gateway, no per-API process:
Surface switches (--lazy, --enable-preview, --http, --format) are
server-wide flags; credentials, policies, caching and retries are per-API.
mcpify status reports per API — [catalog] reachable (status 200, 0.03s) — https://shop.example.com — 31 tools — and exits non-zero if any API is
unreachable. When two APIs expose the same tool name (list_pets), both
get renamed with their label (catalog_list_pets, crm_list_pets) so
nothing silently wins; non-conflicting names stay untouched. The
mcpify_health tool returns one report covering every API. Precedence
per key: CLI flags > [apis.NAME] > [serve]. Pass a positional spec
or [apis.*] sections — never both.
Plug it into your agent
Claude Code:
Claude Desktop / Cursor / any MCP client (claude_desktop_config.json):
HTTP transport (team-shared server) — run mcpify serve api.json --http 0.0.0.0:8080 --http-token $TOKEN once, then point HTTP-capable clients at it:
Now ask your agent: "list the pets, then create one named Milo" — it discovers list_pets and create_pet, fills the arguments, and performs real HTTP calls.
How operations become tools
The agent only ever sees the tool list and your API's JSON responses — mcpify adds no middleware, caches nothing you did not ask for, and sends credentials nowhere except your API.
Doctor
Add --probe for a live pre-flight — after the static report, mcpify
dials one argument-free GET (or the base URL) and reports reachability;
a connection failure exits non-zero so CI and shell scripts stop before
serving:
CLI reference
Notes & limitations
- JSON specs work out of the box; YAML specs need
pip install 'mcpify[yaml]' - External
$reftargets (files or URLs) are bundled automatically at load; circular cross-file refs are left in place rather than unwound (surface skips what it cannot resolve) - Oversized JSON responses truncate to valid JSON (first items + a truncation marker); non-JSON bodies cut at a character boundary
--fieldsselects at every level by documented rule (selected keys verbatim, non-selected containers transparent); it is a projection, not a security boundary — use--redactwhen a field must never reach the model- Request bodies are exposed as a single
bodyobject argument — predictable over clever - HTTP transport serves one JSON-RPC response per request (batching was removed from
the MCP spec); clients that send
Accept: text/event-streamget it framed as a single SSEmessageevent. Server-initiated streams (a GET stream with sessions) stay deliberately out of scope for a stateless server - Spec versions: OpenAPI 3.x and Swagger 2.x roots are accepted; 3.x is the happy path
Hardened against the real world
mcpify is audited on every release against a 10-category checklist of MCP best practices and published production failure modes — not just our own examples:
- Hostile-spec corpus (12/12): circular
$refs, multipart uploads,allOfschemas, server URL variables, relative base URLs, oversized responses — every scenario derived from a documented real-world failure, fixed, and locked in by a regression test. Sources include the arXiv study of REST→MCP generation across 18 real APIs. - Live integration: the real api.weather.gov spec loads in CI — and the live checks found the last two real bugs (nested-truncation envelope splits, top-level-only projection) before any user did.
- MCP lifecycle enforced: tools are unreachable until the client
completes the
initializehandshake. - Session survives upstream failures: a slow upstream (read timeout), a
mid-response disconnect, or even an unexpected exception inside one tool
becomes a clean
isErrortool result with remediation — never a dead stdio connection (the failure mode reported against other OpenAPI-to-MCP servers, replayed here and locked in by regression tests). - Blast-radius controls: read-only mode, deny/allow policy layer,
per-token RBAC, response projection + secret masking, rate limiting,
40k-char valid truncation,
--timeout, credentials never logged.
Full checklist with per-item status: docs/AUDIT-CHECKLIST.md
Tests
520 passing, plus one live-integration test that loads the real
api.weather.gov document (auto-skipped when offline) and an OTel positive
test that runs wherever the optional tracing extra is installed. Every
suite runs on Python 3.10–3.12 across Linux and Windows; ruff, strict
mypy and CodeQL gate every push.
Policy on failures: every bug found in the wild becomes a pinned regression test before the fix ships — the suite only grows.
Run it locally:
Roadmap
The v1.6–1.16 roadmap is fully shipped. Possible future work (not promised): server-initiated SSE (a GET stream with sessions — deliberately out for a stateless transport).
-
— shipped in v1.16.0statuspolicy visibility, REPL:redact/:fields,diff --probe+ cost delta, form examples -
Authenticated— shipped in v1.15.0doctor --probe+--fail-on-http-errorCI gate,init --probe, projection/redaction metrics, lazy-surface pricing -
— shipped in v1.14.0--redact,--rate-limit,doctor --probe, lazy-search costs, multi-APIlist -
OAuth2 write flow (— shipped in v1.13.0--write-oauth2-*),list --cost,--fieldsprojection, SSE POST responses -
Read/write credential split, tool-text overrides, doctor prompt-hygiene audit, structure-aware truncation— shipped in v1.12.0 -
Spec diff + audit log + per-token RBAC + plugin hooks + config JSON Schema + external— shipped in v1.11.0$refbundling + OTel extra -
Web dashboard, Prometheus metrics, mock server, hot reload— shipped in v1.10.0 -
Multi-API aggregation: one— shipped in v1.9.0serveprocess fronting several OpenAPI documents -
HTTP transport,OAuth2 client-credentials,,mcpify tryREPL— shipped in v1.6.0--output-server
License
MIT — see the LICENSE file for details.
Source: README.md at commit 7d888dd
Tools
0Version history
1- v1.19.0LatestSep 16, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts