mcp-gateway

OpenAPI or local API to MCP server for Claude Code, Codex and Cursor, with a public HTTPS tunnel.

Documentation

mcp-gateway

An open-source project by Fetch Hive.

OpenAPI to MCP, with a tunnel. Turn an OpenAPI spec, or an MCP server already running on your machine, into an MCP endpoint any client can call: Cursor, Codex, Claude Code, VS Code, ChatGPT, Claude, or any MCP client.

  • Live API or localhost. Compile a public spec, or the API on your laptop: a WIP branch, localhost:3000, a Docker compose stack.
  • Public HTTPS URL, no inbound port. Add --tunnel and remote clients get https://<name>.mcp.fetchhive.com/mcp while your process stays on loopback.
  • Safe defaults. Loopback bind, bearer token required, SSRF-hardened outbound dialer.

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

Deploy to Render Deploy to Heroku Deploy to DigitalOcean

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.4 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 tom@fetchhive.com — see SECURITY.md.

Docs

Licence

Apache License 2.0. See LICENSE and NOTICE.