Use a stdio MCP server in claude.ai and ChatGPT without deploying it
To use a stdio MCP server from claude.ai or ChatGPT, you need three things: a bridge that turns stdio into Streamable HTTP (supergateway or mcp-proxy), a public HTTPS URL (a tunnel), and auth in front of it, ideally OAuth. Some tools do all three at once: MCP Warp and mcptunnels spawn the command and give it an OAuth-protected URL.
If your server already speaks Streamable HTTP, skip to One URL for your MCP server, in every client, which covers getting a URL and adding it to each client, or see Expose an HTTP server for the MCP Warp config.
Why web clients can’t use stdio
Section titled “Why web clients can’t use stdio”A stdio server is a program the client starts. In Claude Desktop’s JSON config you write "command": "uvx", "args": ["some-server"], and Claude Desktop launches that as a child process, writes JSON-RPC messages to its stdin and reads replies from its stdout. That only works when the client and the server are on the same machine.
claude.ai and ChatGPT run in someone else’s data centre. When you add a custom connector, Anthropic’s help article says “Claude connects to your remote MCP server from Anthropic’s cloud infrastructure, rather than from your local device.” Those servers can’t start a process on your laptop, and they can’t reach localhost on it either. They need a URL.
stdio, Streamable HTTP and SSE in two minutes
Section titled “stdio, Streamable HTTP and SSE in two minutes”MCP defines how messages travel between client and server. There are three transports you’ll run into:
| Transport | How it works | Status |
|---|---|---|
| stdio | The client spawns the server and exchanges newline-delimited JSON-RPC over stdin and stdout. | Current. Local clients only. |
| Streamable HTTP | The server listens at one HTTP endpoint, usually /mcp. Clients POST messages there, and the server can answer with JSON or stream the response. |
Current. What remote clients use. |
| HTTP+SSE (2024-11-05) | A GET /sse stream for server messages plus POST /messages for client messages. |
Legacy, replaced by Streamable HTTP. |
Which clients take which:
| Client | stdio | Streamable HTTP URL |
|---|---|---|
| claude.ai, ChatGPT | No | Yes, as a custom connector |
| Claude mobile apps | No | Yes, connectors added on the web sync to the phone |
| Claude Desktop | Yes, in claude_desktop_config.json |
Yes, as a custom connector (public URL only) |
| Claude Code | Yes | Yes, claude mcp add --transport http |
| VS Code | Yes | Yes, "type": "http" in mcp.json |
So the job is to turn a stdio program into a Streamable HTTP endpoint that the web clients can reach.
The three jobs
Section titled “The three jobs”Getting a stdio server into claude.ai takes three separate pieces of work:
claude.ai / ChatGPT in Anthropic's or OpenAI's cloud │ HTTPS + auth job 3: auth (OAuth, or a fixed header) ▼Public URL job 2: a tunnel or a host │ ▼Bridge on your machine job 1: Streamable HTTP in, stdio out │ stdin / stdout ▼Your stdio server uvx ..., npx ...- Bridge. Something listens on HTTP and turns each request into stdio messages for the child process.
- Public URL. A tunnel (or a host) gives that local HTTP endpoint an address the internet can reach.
- Auth. Once the URL is public, anyone who finds it can call your tools, on your machine, with your permissions. Something has to decide who gets through.
mcp-remote often comes up in these searches, and it goes the other way. It lets a stdio-only client reach a server that already has a URL. It doesn’t help a web client reach your stdio server.
How MCP Warp works shows the same path for one specific tunnel.
Option A: bridge plus tunnel plus auth
Section titled “Option A: bridge plus tunnel plus auth”This is the free, do-it-yourself route, with one tool per job.
The bridge. Two popular choices are supergateway and the TypeScript mcp-proxy. Both are widely used: between 9 September and 8 October 2026, supergateway had about 596,000 npm downloads and mcp-proxy about 3.2 million (npm API). With supergateway:
npx -y supergateway \ --stdio "npx -y @modelcontextprotocol/server-filesystem ./my-folder" \ --outputTransport streamableHttp \ --port 8000That serves the filesystem server at http://localhost:8000/mcp. supergateway also has --apiKey, which makes clients present a key as a bearer token or X-API-Key header. mcp-proxy’s usage is npx mcp-proxy [options] -- <command>, and its --apiKey option, “Optional and off by default”, makes clients send a valid key in the X-API-Key header.
The tunnel. Point any tunnel at the bridge’s port. Each has trade-offs for MCP:
- A Cloudflare quick tunnel (
trycloudflare.com) needs no account, but Cloudflare’s docs say the hostname changes each time and “Quick Tunnels do not support Server-Sent Events (SSE)”, which Streamable HTTP servers use to stream responses. Cloudflare calls them “for testing and development”. - A named Cloudflare Tunnel gives a stable hostname but needs a domain added to Cloudflare.
- ngrok’s free plan gives each account one auto-assigned dev domain that doesn’t change.
mcp-proxy also has a --tunnel flag that prints a public URL such as https://abcdefghij.tunnel.gla.ma. Its README says the tunnel is “Powered by pipenet, sponsored by glama.ai”, and that a requested subdomain “may not be available”. It’s handy for a quick test, but the subdomain isn’t guaranteed.
The auth. This is the job people skip. The simplest working setup is a fixed key: run supergateway with --apiKey, and in claude.ai’s custom connector dialog put the key in the “Request headers” field, which Anthropic’s help article describes as “fixed credentials such as API keys that Claude sends on every request”. The key then lives in a connector setting as a shared secret. For OAuth, which ties each call to an account and is what MCP clients discover on their own, you need an authorization server and Protected Resource Metadata in front of the bridge, or Cloudflare Access with an identity provider. This write-up on zenn shows what that takes, and mcp-ferry exists to glue the Cloudflare pieces together.
It all works and costs nothing. It’s three tools to install, configure and keep running.
Option B: one tool for all three
Section titled “Option B: one tool for all three”MCP Warp, the tunnel we build, does the three jobs in one process: it spawns your command, bridges it to Streamable HTTP locally, and gives it a public URL with OAuth at the edge. The bridges above are good at bridging; the case for this route is fewer moving parts.
After installing the CLI and signing in once at web.mcpwarp.io to pick a username (see Get started), add the server to ~/.mcpwarp/config.json with the same command you’d give Claude Desktop:
{ "servers": [ { "name": "blender", "kind": "stdio", "command": "uvx", "args": ["blender-mcp"], "env": { "BLENDER_PATH": "/Applications/Blender.app" } } ]}command is resolved on PATH and run directly, not through a shell. env values are used literally, with no ${VAR} expansion. There’s also an optional cwd. The Config reference has every field.
Validate the config, log in and start the tunnel:
mcpwarp statusmcpwarp loginmcpwarp upNAME KIND URLblender stdio https://blender-anatoly.tunnel.mcpwarp.io/mcpPaste that URL into claude.ai or ChatGPT as a custom connector and complete the OAuth sign-in. Only your account can use it: the edge checks that each token belongs to the server’s owner.
MCP Warp isn’t certified by Anthropic or OpenAI; it’s built to work with Claude and ChatGPT as a standard Streamable HTTP MCP client.
How the bridge works
Section titled “How the bridge works”From Expose a stdio server: each stdio server gets a small local HTTP endpoint that turns Streamable HTTP requests into newline-delimited JSON-RPC on the child’s stdin and stdout. It classifies messages by shape, so it supports both session-based MCP and the stateless 2026-07-28 generation of the protocol.
In the full-screen view, r restarts the selected stdio server and l opens its log pane. mcpwarp up --verbose gives more detail. See the CLI reference.
Limits
Section titled “Limits”- No SSE resumability. There’s no
Last-Event-IDor replay, so if a stream drops, the client has to re-issue the request. - Windows.
.cmdand.batshims aren’t launched directly; pointcommandatnodeand pass the underlying.jsfile inargs. Process cleanup on Windows is best-effort and only kills the direct child. - Restart cap. If the child crashes 10 times in a row without a 60-second healthy run, mcpwarp stops restarting it and requests get a
502with “local server ‘<name>’ is not running”. - Your machine has to be on. If
mcpwarp upisn’t connected, the URL returns503. - Free plan. 100 requests a month and 1 server, and every HTTP request a client makes counts. See Limits and quotas.
Option C: OpenAI’s tunnel, for ChatGPT only
Section titled “Option C: OpenAI’s tunnel, for ChatGPT only”If ChatGPT is the only client you care about, OpenAI’s Secure MCP Tunnel handles stdio. Its open-source client, openai/tunnel-client, connects “private or localhost MCP servers to ChatGPT, Codex, the Responses API, and AgentKit”. It can spawn a stdio server itself, with one rule from the README: “run only one active tunnel-client instance per tunnel ID when using --mcp.command”. OpenAI’s announcement has the setup. It doesn’t serve claude.ai or other clients.
Anthropic has a first-party option too, with narrower reach. Its MCP tunnels are for organizations on the Claude Enterprise plan, by request, and they carry Streamable HTTP only, so a stdio server would still need a bridge in front.
Option D: mcptunnels, free with a 24-hour URL
Section titled “Option D: mcptunnels, free with a 24-hour URL”mcptunnels does all three jobs in one command, with no signup:
mcptunnel expose -- npx -y @modelcontextprotocol/server-everythingIts README says tunnels are “anonymous, OAuth-protected by default, and expire after 24 hours.” The CLI prints the public URL and a generated password; when a client runs the OAuth flow, you enter that password on the authorize page. The URL contains a random segment, so after 24 hours (or when you press Ctrl-C) you get a new URL and have to re-add the connector. For an afternoon of testing that’s fine. For a connector you use every day, it’s a chore. You can also run its relay yourself.
Which servers this suits
Section titled “Which servers this suits”Tunnelling a stdio server makes sense when the server needs your machine:
- Local files. A filesystem server, a notes vault, a folder of PDFs.
- Desktop apps. blender-mcp drives Blender, which has to be running on your machine.
- Local data. A database or service on your laptop or home network that you don’t want on the internet.
If a server only calls a cloud API with a key, hosting it somewhere is usually simpler. It stays up when your laptop sleeps, and you don’t depend on a tunnel.
Whichever route you take, remember the server runs with your permissions. Auth decides who can call it; it doesn’t limit what it does once called. Scope it before you expose it. The filesystem server, for example, only touches the directories you pass on its command line, so give it one folder:
{ "servers": [ { "name": "files", "kind": "stdio", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/Documents/shared"] } ]}For a side-by-side look at tunnels for MCP, including ngrok, Cloudflare Tunnel and Tailscale Funnel, see ngrok alternative for MCP. If claude.ai still won’t connect, Why claude.ai can’t connect to your local MCP server covers what the URL needs.