mcp-gateway
An open-source project by Fetch Hive.
OpenAPI to MCP. Connect your API to Cursor, Codex, Claude Code, VS Code, ChatGPT, or any MCP client — in minutes.
That means a live API, and it also means the API on your laptop: a WIP
branch, localhost:3000, a Docker compose stack. Point the editor at the
gateway and call the same tools you will ship.
Prefer a hosted MCP Gateway with tokens, quotas, and a dashboard? https://fetchhive.com/mcp
Two equally important flows
1. Local / branch API → editor
Your server is already running on this machine. It does not need to be an MCP
server. The gateway compiles the OpenAPI document and serves the MCP endpoint.
mcp-gateway tunnel <mcp-url> is the other flow: the local process already
speaks MCP. A plain REST app returning 404 for POST /mcp is expected.
Compile from a file, or from the OpenAPI URL the API already serves. Use one
add-spec command, not both.
mcp-gateway init --allow-private-networks
# from a file:
mcp-gateway add-spec --name demo --file ./openapi.yaml \
--base-url http://127.0.0.1:3000 --insecure-http
# or from the URL the API already serves:
mcp-gateway add-spec --name demo \
--url http://127.0.0.1:3000/openapi.json \
--insecure-http --allow-private-networks
export MCP_GATEWAY_TOKEN=… # printed once by init
mcp-gateway test demo list_pets --args '{}'
mcp-gateway serve demo
mcp-gateway inspect demo --client cursor # or: codex | claude-code | vscode | claude
--allow-private-networks is required for loopback and RFC1918. --insecure-http
is required when the API speaks HTTP (typical on localhost). Both flags are
required together to fetch an http:// spec URL, and that host must be
loopback, RFC1918, or IPv6 ULA. A public http:// URL is refused. --file
does not fetch anything; --base-url is the origin of this checkout, not
production, and still needs both flags when that origin is HTTP on a private
host.
2. Live API → editor or agent
Same compiler, public HTTPS OpenAPI, no private-network flag.
mcp-gateway init
mcp-gateway add-spec --name demo --url https://api.example.com/openapi.json
export MCP_GATEWAY_TOKEN=…
mcp-gateway serve demo
mcp-gateway inspect demo --client cursor
Or skip operating a process: hosted MCP Gateway. PaaS / VPS: deploy.
3. Local server, remote client
The process stays on loopback. An outbound tunnel gives you
https://<slug>.mcp.fetchhive.com/mcp for OpenAI, Claude, Cursor, and any
other client that can send a bearer header. No account. The URL is released
30 minutes after the CLI exits.
export MCP_GATEWAY_TOKEN=…
mcp-gateway serve demo --tunnel
The same tunnel also sits in front of an MCP server this CLI did not compile: a Streamable HTTP URL, or a stdio server.
mcp-gateway tunnel http://127.0.0.1:8000/mcp
mcp-gateway tunnel --stdio -- npx -y @modelcontextprotocol/server-filesystem /tmp
On a terminal, each finished call prints the HTTP method, status, duration,
path, and the JSON-RPC method. tools/call also prints the tool name. That
label is omitted when the body is streamed or larger than 64 KiB. Library
info logs stay off that screen unless you set RUST_LOG or [log] level.
Colors follow --color and NO_COLOR.
Details: Tunnel.
mcp-gateway login is optional for an anonymous URL. It stores an fh_cli_
account token in credentials.toml next to config.toml (mode 0600 on
Unix). serve --name and tunnel --name read that token and keep
https://<name>.mcp.fetchhive.com/mcp while the process is offline.
doctor reads the file only to report the file mode and the email.
Anonymous tunnels do not require login. See Account
and Persistent names.
Deploy
Guides: Render · Heroku · DigitalOcean · Hetzner. Vercel cannot run this server (why).
Set MCP_GATEWAY_TOKEN and MCP_GATEWAY_SPEC_URL (HTTPS OpenAPI; loopback HTTP is the local flow above, not this image). The image
reads PORT itself (distroless, no shell). After deploy, paste
mcp-gateway inspect demo --client cursor (replace the URL with your
https://…/mcp) into the editor.
Install
# Homebrew — use the fully qualified name (Homebrew 6 trusts only this formula).
# `brew tap` then `brew install mcp-gateway` is refused until you `brew trust`.
brew install Fetch-Hive/tap/mcp-gateway
# Docker (linux/amd64 and linux/arm64)
docker run --rm -p 127.0.0.1:8787:8787 ghcr.io/fetch-hive/mcp-gateway:0.11.2 version
# npm — wrapper plus the prebuilt binary for this machine
npx --yes @fetch-hive/mcp-gateway version
# GitHub Release installer
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Fetch-Hive/openapi-mcp/releases/latest/download/mcp-gateway-cli-installer.sh | sh
# From a checkout of this repo
cargo install --path crates/mcp-gateway-cli
mcp-gateway compiles OpenAPI 3.0/3.1 to a versioned IR, serves tools over
Streamable HTTP or stdio, and injects upstream credentials from env or file
references. Outbound HTTP uses an SSRF-hardened dialer.
Security
Default bind is loopback. Binding 0.0.0.0 requires --expose. Upstream
private networks and localhost require --allow-private-networks. Report
vulnerabilities to [email protected] — see SECURITY.md.
Docs
- Connect Cursor, Codex, Claude Code
- Tunnel (local server, public URL)
- CLI reference
- Config schema
- Deploy (PaaS + VPS)
- SSRF policy
- Private-network flag
- Tunnel protocol
Licence
Apache License 2.0. See LICENSE and NOTICE.