A remote MCP server is a Model Context Protocol server that runs at a public HTTPS URL and speaks the Streamable HTTP transport, so any MCP client can call its tools over the network instead of launching the server as a local subprocess.
You built an MCP server that wraps an internal API, and it works on your machine: the desktop client launches it over stdin and stdout and the tools show up. Then a teammate asks for it, and the hosted client you want to connect only accepts a URL.
The local process now needs an address, an HTTP transport, a way to decide who may call it, and a host that costs little while nobody is calling. Most MCP servers sit idle most of the day, so the idle-hours bill is the number that matters.
What Is a Remote MCP Server?
A remote MCP server is the same protocol carried over HTTP instead of a child process’s standard streams. The specification defines two transports: stdio, for a subprocess the client launches, and Streamable HTTP, where each message is an HTTP POST to a single MCP endpoint.[1] The tools a server exposes are identical on both.
How Streamable HTTP works
The server exposes one path, conventionally /mcp. Every client request is its own POST, answered with either a JSON object or a Server-Sent Events stream scoped to that request.[2] The 2026-07-28 revision removed protocol-level sessions and the standalone GET stream, so a server on the current revision keeps no per-client state at the transport layer. Any instance can answer any request, and an instance can stop between calls without breaking anything.
The older HTTP+SSE transport from 2024 is deprecated, and new servers should not adopt it.[2]
Is it an actual server?
Yes. A remote MCP server is an HTTP service on a port, with the operational needs of any small API. The spec adds two requirements: servers must validate the Origin header to block DNS rebinding, and should authenticate every connection.[2]
Where Can I Host My MCP Server?
You can host a remote MCP server anywhere that runs an HTTP process, holds a streaming response open, and terminates TLS. The options split into two shapes, and the split decides whether your existing code runs unchanged.
Isolate platforms run your handler inside a shared JavaScript runtime. Cloudflare Workers creates a V8 isolate inside an existing runtime process rather than starting a VM or container per function.[4] Its MCP guide builds servers with Cloudflare’s own createMcpHandler() and marks the older stateful McpAgent path as deprecated for new servers.[5] There is no subprocess to hand stdin and stdout to, so a stdio server gets ported rather than wrapped.
Container and VM platforms run your image as a normal process, native dependencies included. Fly Machines are in this group, and so are Cloudflare’s own Containers, billed separately from Workers.[6] Anything that runs in a Docker image runs here, including a stdio server behind a small gateway.
| Isolate platform | Container or VM platform | |
|---|---|---|
| What runs | A handler in the platform’s runtime | Your image, as a process |
| Existing stdio server | Ported to the runtime | Wrapped, unchanged |
| Idle behaviour | Billed per request | Stops when idle, starts on the next request |
| Examples | Cloudflare Workers | Fly Machines, Cloudflare Containers |
Sources: [4][5][6], checked 2026-10-12.
On the scaling side of serverless, the difference that matters is zero traffic, where an MCP server spends its day.
How Much Does It Cost to Host an MCP Server?
A remote MCP server that is idle most of the day costs well under a dollar a month on a Fly Machine that stops when idle, and $5 a month on the Cloudflare Workers Paid plan, using each provider’s published rates.
On Fly.io, a shared-cpu-1x Machine with 256 MB of RAM is $2.19 for 30 days of continuous running, billed by the second while it runs. A stopped or suspended Machine pays $0.15 per GB per month for its root filesystem, and outbound data is $0.02 per GB in North America and Europe.[7] The Workers Paid plan has a $5 monthly minimum per account, which includes 10 million requests and 30 million CPU milliseconds, with no charge for duration or egress.[6]
The table assumes a 500 MB image, 1 GB of responses a month, and traffic inside the Workers allowances.
| Hours running per day | Fly.io compute | Fly.io rootfs while stopped | Fly.io egress | Fly.io total | Cloudflare Workers Paid |
|---|---|---|---|---|---|
| 2 (60 h/month) | $0.18 | up to $0.08 | $0.02 | about $0.28 | $5.00 |
| 8 (240 h/month) | $0.73 | up to $0.08 | $0.02 | about $0.83 | $5.00 |
| 24 (always on) | $2.19 | $0.00 | $0.02 | $2.21 | $5.00 |
Sources: [6][7], iad and ewr rates, checked 2026-10-12. Compute is $2.19 / 720 h, about $0.003 per running hour.
Where each one wins
A shared-cpu-1x Machine costs less than Workers Paid at every row, including always on. The 512 MB size is $3.69 a month always on, and a 1 GB Machine at $6.70 a month stays under $5 up to about 17 hours a day of running time.[7] Workers Paid comes out ahead once a server needs more than $5 of Machine time and its code already fits Cloudflare’s runtime. Past its allowances, Workers adds $0.30 per million requests.[6]
Cloudflare also offers a $0 Workers plan, limited to 100,000 requests a day and 10 milliseconds of CPU per invocation.[6] PaaS pricing compared breaks down per-second and per-request billing in more detail.
How Do I Turn a Local stdio MCP Server Into a Remote One?
There are two ways: switch the server to the SDK’s Streamable HTTP transport, or leave the code alone and put a stdio-to-HTTP gateway in front of it. Both end with an HTTP endpoint at /mcp.
Switch the transport in code
When you own the code, replace the stdio transport with a Streamable HTTP one and add an HTTP listener on 0.0.0.0 and the port your host provides. This is the better long-term path, because the server sees each HTTP request directly and can read the Authorization header itself.
Wrap the stdio server unchanged
Supergateway runs a stdio MCP server as a child process and exposes it over Streamable HTTP, listening on every interface by default and serving /mcp.[8] It also has an --apiKey option that makes clients present the key as a bearer token. A Dockerfile for a Node stdio server looks like this:
FROM node:22-slim
WORKDIR /app
COPY . .
RUN npm ci --omit=dev
EXPOSE 8080
CMD npx -y supergateway@4.1.0 \
--stdio "node server.js" \
--outputTransport streamableHttp \
--port 8080 \
--apiKey "$MCP_API_KEY"
The same pattern works for a Python MCP server: change the base image and the --stdio command.
How Do I Secure a Remote MCP Server?
Secure a remote MCP server with OAuth 2.1 when people outside your team connect to it, and with a bearer token held in a secret when only your own clients do. Authorization is optional in the spec, but an open server lets anyone who finds the URL call every tool, each running with the server’s credentials for the downstream API.[3]
OAuth, end to end
The spec makes the MCP server an OAuth 2.1 resource server. An authorization server issues the tokens, either alongside the MCP server or as a separate identity provider.[3] The full flow:
- The client POSTs to
/mcpwith no token. The server replies401with aWWW-Authenticateheader pointing at/.well-known/oauth-protected-resource. - That metadata document names the authorization server, whose own metadata the client fetches next.
- The client gets a client ID: a Client ID Metadata Document, pre-registration, or the deprecated Dynamic Client Registration.
- The user signs in through the browser, with PKCE and a
resourceparameter naming the MCP server’s URL. - Every request carries
Authorization: Bearer, and the server rejects tokens not issued for it as the audience.
The server must never pass a client’s token through to a downstream API.[3] Downstream calls use the server’s own credentials, so a leaked MCP token never becomes a leaked API key.
Cloudflare’s guide does this with an OAuth provider in the Worker: users sign in with GitHub or Cloudflare Access, and the Worker issues the tokens.[5] On a container host the shape is the same: serve the metadata document, validate tokens from your identity provider, and keep its client secret in the host’s secret store.
When a bearer token is enough
For a server only your team’s clients call, one bearer token is simpler and still closes the door. Generate a long random key, store it as a secret, configure each client to send it, and rotate it by changing the secret.
Hosting a Remote MCP Server on Fly.io
Fly.io runs a remote MCP server as a Fly Machine built from your image, with a public HTTPS address on fly.dev and TLS handled by Fly Proxy. fly launch detects the project, writes fly.toml, and deploys the stdio-wrapping image above with one command.
The cost table above comes from Fly Proxy stopping idle Machines. Set it in fly.toml:
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = "suspend"
auto_start_machines = true
min_machines_running = 0
Fly Proxy suspends the Machine when the app has been idle for several minutes and starts it on the next request. Starting from suspended is faster than starting from stopped.[9] If the first call after a quiet hour must not wait, set min_machines_running = 1. That is the $2.19 always-on row. The autostop and autostart docs cover every option.
Credentials go in Fly secrets: fly secrets set MCP_API_KEY=... for the bearer-token setup, or the OAuth client secret and downstream API keys for the full flow. They reach the Machine as environment variables, never baked into the image.
For a server that should not have a public address at all, Flycast gives the app a private address on your organization’s network. Teammates reach it over WireGuard, and agents in other Fly apps reach it directly. Fly.io vs Cloudflare covers the wider comparison beyond MCP.
Frequently Asked Questions
Is it cheaper to host an MCP server on Fly.io or Cloudflare Workers?
Fly.io, for a server that is idle most of the day. A 256 MB shared-cpu-1x Machine that stops when idle costs well under a dollar a month at a few hours of use a day, and $2.19 always on, against the $5 minimum of Workers Paid. Cloudflare’s $0 Workers plan is cheaper for a server already written for Workers that stays within 100,000 requests a day and 10 milliseconds of CPU per call.
Can a MCP server run on a remote host?
Yes. An MCP server runs on a remote host when it uses the Streamable HTTP transport instead of stdio, exposing a single endpoint such as /mcp that clients reach over HTTPS. On Fly.io it runs as a Fly Machine with a public fly.dev address.
What is the difference between a MCP host and a MCP server?
The MCP host is the application the user works in, such as a chat client or editor, running one MCP client per server. The MCP server is the program that exposes tools. Fly.io hosts the server side, the part that has to be reachable at a URL.
Do MCP servers run on a port?
Yes, remote ones do. A Streamable HTTP server listens on a TCP port, while a stdio server uses no port at all. On Fly.io the server listens on the internal_port set in fly.toml and Fly Proxy serves it on 443.
Is an MCP server a proxy?
No, though many behave like one. An MCP server exposes its own tools, which often call an existing API, so it sits in front of a service much as a proxy would. A stdio-to-HTTP gateway on Fly.io is closer to a true proxy, since it only relays messages.
Should I use stdio or Streamable HTTP?
Use stdio when the server only runs on the same machine as its client, and Streamable HTTP when anyone else needs to reach it. Streamable HTTP lets a server run on Fly.io and serve a whole team from one URL.
Does a remote MCP server have cold starts?
Yes, when it is allowed to stop. A stopped or suspended Fly Machine starts on the next request, suspended ones faster. Setting minmachinesrunning to 1 on Fly.io keeps one Machine running, at $2.19 a month for the 256 MB size.
Can I keep an MCP server private to my team?
Yes. Put a bearer token or OAuth in front of a public endpoint, or give the server no public address. On Fly.io, Flycast assigns the app a private address on the organization’s network, reachable by teammates over WireGuard.
Sources
- ^ Model Context Protocol, “Transports” (specification 2026-07-28). modelcontextprotocol.io/specification/2026-07-28/basic/transports. Checked 2026-10-12.
- ^ Model Context Protocol, “Streamable HTTP” (specification 2026-07-28). modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http. Checked 2026-10-12.
- ^ Model Context Protocol, “Authorization” (specification 2026-07-28). modelcontextprotocol.io/specification/2026-07-28/basic/authorization. Checked 2026-10-12.
- ^ Cloudflare, “How Workers works”. developers.cloudflare.com/workers/reference/how-workers-works. Checked 2026-10-12.
- ^ Cloudflare, “Build a Remote MCP server”. developers.cloudflare.com/agents/model-context-protocol/guides/remote-mcp-server. Checked 2026-10-12.
- ^ Cloudflare, “Pricing” (Workers). developers.cloudflare.com/workers/platform/pricing. Checked 2026-10-12.
- ^ Fly.io, “Fly.io Resource Pricing”. fly.io/docs/about/pricing. Checked 2026-10-12.
- ^ Supercorp, “supergateway” README, v4.1.0. github.com/supercorp-ai/supergateway. Checked 2026-10-12.
- ^ Fly.io, “Autostop/autostart Machines”. fly.io/docs/launch/autostop-autostart. Checked 2026-10-12.