Direct answer: Run the MCPMCPA standard that lets an AI program use your tools and data under clear permissions.Open the glossary server locally over stdio when every user runs the client on the same machine and no hosting needs paying. Choose Cloudflare Workers when the server must be remote and serve a Claude connector or ChatGPT. Free gives 100,000 requests per day, Paid starts at USD 5 monthly. Choose a VPS when the server must sit on the same network as the source system, or you already run servers. All 3 run the same server; only the transport and hardening differ.

Main condition: the steps here follow the MCP transport specification revision 2026-07-28 and the Cloudflare Agents documentation updated June to July 2026. Workers prices use the pricing page dated 28 August 2026. Limit: VPS prices and model APIAPIThe official door 2 systems use to exchange data, without anybody copying it by hand.Open the glossary prices are not given because they were not opened today, so price that separately with your provider. This article does not cover McpAgent (Durable Object) because it is deprecated. Shell commands are generic; project names and domains are examples.

We wrote this guide on 13 September 2026 from the MCP transport specification, the Cloudflare Agents documentation, and the Cloudflare Workers pricing page. On our own systems, 3 MCP servers run on Cloudflare Workers over Streamable HTTP.

The problem: the server runs on a laptop, but the team needs it from 3 places

The MCP server you test on a laptop runs over stdio. The client starts it as a child process. The server dies the moment the laptop closes or the client stops. This works for 1 person. A team using ChatGPT or a Claude connector needs 1 address that stays up, not a process on someone's laptop. Background on MCP is in our what MCP is article, and the term MCP server is defined in the MCP glossary entry.

A second problem appears once a team moves to a VPS without hardening. The Origin header goes unchecked, and tokens are sent without an audience check. Anyone who finds the address can then call the server. Steps 3 and 4 in this article close that gap.

3 places to run an MCP server

The MCP transport specification is neutral on the hosting provider: there are 2 standard transports, stdio and Streamable HTTP, and both can run anywhere. Source: the MCP transport specification. In practice, 3 places are common for the same server.

Three places to run an MCP server: locally over stdio on a laptop, stateless Cloudflare Workers over Streamable HTTP, and a VPS behind a reverse proxy with TLS
Local (1) has no hosting cost but serves only clients on the same machine. Workers (2) serves remote clients. A VPS (3) fits when the server must sit near the source system.

stdio runs the server as the client's child process; stdout may carry only MCP messages. Source: the stdio transport specification. Cloudflare supports remote servers over Streamable HTTP and states that SSE for remote MCP is deprecated; new servers use the stateless handler. Source: the Cloudflare Agents documentation.

OptionTransportWho runs itAuthenticationHosting cost we could verifyFits when
Local (stdio)stdioThe client on the user's machine, as a child processCredentials from the environmentNo hosting costEvery user runs Claude Desktop, Claude Code, OpenClaw, or Hermes AgentAI agentAn AI program that performs work steps by itself, for example reading a message, drafting a reply, and recording the result.Open the glossary on their own machine
Cloudflare WorkersStreamable HTTPCloudflare, stateless per requestAn API key (Bearer) or OAuth 2.1 through a templateFree 100,000 requests/day, 10 ms CPU; Paid USD 5/month minimumRemote clients (Claude connectors, ChatGPT, Gemini API); no server of your own to manage
Your own VPSStreamable HTTPYour team, behind a reverse proxy with TLSAn API key or OAuth 2.1Paid separately to the provider; the price was not checked todayThe server must share a network with the source system, or your team already runs servers

We already wrote up the 5 published specification revisions and the move from HTTP+SSE to Streamable HTTP. That history is in our transport generations across the 5 MCP versions (in Indonesian) article, and this article does not repeat it.

Before you start, prepare the following.

  • Access to the source system you want to connect, including test credentials.
  • 1 MCP client already installed for testing: Claude Desktop, Claude Code, or OpenClaw.
  • A Cloudflare account if you choose Workers, or root access to a VPS if you run your own server.
  • 1 test identity you may use to try a read tool and a write tool.

The 6 steps below take the server from a local test to something ready to open for the team.

Step 1: Pick the transport from the clients in use

A client that reaches the server from another network needs Streamable HTTP: a Claude connector, ChatGPT, and the Gemini API all fall in this group. A client that runs on the same machine as the server can use stdio: Claude Desktop, Claude Code, OpenClaw, and Hermes Agent all support stdio. The support details for each client, including transport, authentication, and usage limits, are in our MCP clients 2026 article.

Evidence for this step: you have 1 list of clients with the transport each one supports, taken from each client's own documentation, not assumed.

Step 2: Build a stateless modern-era server

Revision 2026-07-28 removed the protocol session and the initialize handshake. Every request now carries its version and capabilities in _meta, and a server must implement the server/discover RPC. Sources: the MCP specification changelog and the MCP versioning page.

Business state is no longer kept in a protocol session. MCP keeps it as an explicit handle passed as a tool argument. This makes a server easier to scale and to put behind a proxy. Source: the MCP tools specification, Stateful Tools section.

The TypeScript SDK v2 splits the @modelcontextprotocol/server 2.0.0 package (published 27 July 2026) from the legacy @modelcontextprotocol/sdk package at 1.30.0. Source: the npm registry entry for @modelcontextprotocol/server. On our own systems, 3 MCP servers use createMcpHandler from SDK v2.

Evidence for this step: the server/discover response names revision 2026-07-28 and lists the server's capabilities.

Step 3: Add authentication that matches the transport

A stdio transport takes credentials from the environment. The specification states that stdio implementations should not follow the HTTP authorization specification and should read credentials from the environment instead. Streamable HTTP sends the token in the Authorization: Bearer header on every request, and the token must never sit in the query string. Source: the MCP authorization specification.

When a client needs OAuth 2.1, such as a Claude connector, the server publishes Protected Resource Metadata. It must validate the token's audience. A token issued for another party must not be accepted or forwarded. Cloudflare ships a remote-mcp-authless template for a server with no auth and a remote-mcp-github-oauth template for OAuth through OAuthProvider. Source: Cloudflare's remote MCP server guide.

Evidence for this step: a request with no token gets a 401 status code.

Step 4: Harden HTTP on Workers and behind a reverse proxy

A Streamable HTTP server must validate the Origin header and answer 403 for a foreign Origin. When it runs locally, it should bind to 127.0.0.1 to block DNS rebinding. Source: the Streamable HTTP specification.

Streamable HTTP behind a reverse proxy: the client sends POST with 3 required headers and Bearer, the proxy checks Origin and disables buffering, the stateless server answers 1 JSON or 1 SSE stream
The 3 headers (1) must match the body; otherwise error -32020 (4). A foreign Origin is rejected with 403 (2). Buffering is off (3) so streams are not held back.

Every POST carries 3 required headers: MCP-Protocol-Version, Mcp-Method, and Mcp-Name. Mcp-Name applies to tools/call, resources/read, and prompts/get. Header values must match the body, or the server answers code -32020 (HeaderMismatch). Code -32022 flags an unsupported protocol version. Source: the MCP specification changelog.

Behind nginx, disable buffering with X-Accel-Buffering: no, or the stream stays held back until the connection ends. Fuller authentication and hardening controls, including an audit log and a prompt-injection test, are in our MCP server security article.

Evidence for this step: a request from a foreign Origin gets a 403; a wrong header triggers code -32020.

Step 5: Deploy to Workers, a VPS, or run locally

The same server can run in all 3 places; only the deploy command and the network hardening in front of it change.

Cloudflare Workers

npm create cloudflare@latest -- <name> --template=cloudflare/ai/demos/remote-mcp-authless creates a server with no authentication; swap the template for remote-mcp-github-oauth for OAuth. Source: Cloudflare's remote MCP server guide. Use the stateless createMcpHandler; McpAgent (Durable Object) is deprecated and feature-frozen, so do not start a new project on it. Source: the Cloudflare Agents handler API documentation.

Your own VPS

Run the Node process behind a reverse proxy with TLS, then apply the Origin check and the authentication from Steps 3 and 4. We do not give a VPS price because it was not opened today; that is paid separately to your provider. We already wrote a fuller server-hardening pattern for OpenClaw on a VPS. The same steps match for an MCP server: the OpenClaw VPS hardening tutorial (in Indonesian).

Local (stdio)

Claude Desktop runs a local server through a stdio configuration file. The client must show the full command before it runs the server, because a local server runs with the same privileges as the client. Sources: the MCP build-a-server documentation and the MCP security guidance.

A local MCP server as a Claude Desktop subprocess: stdin and stdout only for MCP messages, logs to stderr, credentials from the environment
The host (1) runs the server as a subprocess (2). Messages go over stdin/stdout (3); logs go to stderr (4). Writing logs to stdout breaks the connection.

Send logs to stderr, not stdout; writing to stdout breaks the connection, because stdout may carry only MCP messages.

Evidence for this step: tools/list succeeds from 1 test client, on each of the 3 places you chose.

Step 6: Watch requests and cap cost

Workers Free gives 100,000 requests per day and 10 ms CPU per invocation. Paid starts at USD 5 per month. It includes 10 million requests and 30 million ms CPU per month. Extra usage costs USD 0.30 per million requests and USD 0.02 per million ms CPU. There is no egress charge. Source: the Cloudflare Workers pricing page.

The CPU limit per invocation is 5 minutes at most, and 30 seconds by default. Set this limit so a long-running tool cannot spike your bill. Claude gives a tool call 240 seconds on Claude.ai and Claude Desktop, so a tool must finish before that limit. Source: the Claude connectors documentation.

Add a rate limit per caller too. On our own systems, this limit stops 1 caller from using up every other user's request budget.

Evidence for this step: the Workers dashboard shows daily requests and CPU ms per invocation.

Example: deploy a stock server to Workers and check the Free tier

The simulation below uses dummy data; the domain name and request counts are examples, not a real customer's data.

Input (what we did)Recorded (in Workers and the server)Output (what we saw)
Deployed from the remote-mcp-authless template, then added a Bearer checkThe Worker is live on an example domain; server/discover answers with revision 2026-07-28tools/list from a Claude connector succeeds
Tested with no tokenThe server answers 401 with WWW-AuthenticateThe client asks for a token
Tested from a foreign web page (a different Origin)The Origin is rejected with 403The request fails as expected
First business day: 3 clients, 1,200 requestsDashboard: 1,200 requests; average CPU under 10 ms; the Free limit is 100,000/dayStill on Free; note: move to Paid past 100,000 requests/day

Note: the domain name, request counts, and CPU time are dummy data. The Free limit and the Paid price use the Workers pricing page dated 28 August 2026.

Checklist before you open the server to the team

  1. The transport is chosen from the client list: stdio or Streamable HTTP. Owner: head of IT. Evidence: a table of clients and transports.
  2. server/discover answers with revision 2026-07-28 and capabilities. Owner: developer. Evidence: the discover response.
  3. A request with no token gets 401; a token from another server also gets 401. Owner: developer. Evidence: 2 test results.
  4. A foreign Origin gets 403; the local server binds to 127.0.0.1. Owner: developer. Evidence: the Origin test result.
  5. Behind nginx: buffering is off, and the 3 required headers pass through unchanged. Owner: DevOps. Evidence: the proxy configuration and no code -32020.
  6. stdio: logs go to stderr; nothing else is written to stdout. Owner: developer. Evidence: a connection test from Claude Desktop.
  7. The CPU limit per invocation and the per-caller rate limit are both written down. Owner: DevOps. Evidence: the configuration file.
  8. Stop criterion: if the main client can only speak the old SSE, do not deploy yet; SSE is deprecated in the specification and on Cloudflare.

Frequently asked questions

Does an MCP server have to be hosted? No. The stdio transport runs the server as the client's child process on the user's machine, with no hosting and no separate server cost.

How much does Cloudflare Workers cost for an MCP server? Free gives 100,000 requests per day and 10 ms CPU per invocation. Paid starts at USD 5 per month, already including 10 million requests and 30 million ms CPU per month.

Why is SSE no longer used? Streamable HTTP replaced HTTP+SSE from revision 2025-03-26, and SSE became deprecated at revision 2026-07-28. Cloudflare and the Gemini API do not use it for new servers.

Is Cloudflare McpAgent still recommended? No. McpAgent (Durable Object) is deprecated and feature-frozen; Cloudflare recommends the stateless createMcpHandler for new servers.

How does an MCP server on a VPS handle streams behind nginx? Disable buffering with the X-Accel-Buffering: no header. Pass the 3 required Streamable HTTP headers through unchanged, and validate the Origin header before you process the request.

Can the same server run locally and remotely? Yes. The tool logic stays the same; only the transport and how authentication sits in front of the server differ.

Next step

The hosting choice decides the hardening you must add, not the tools the server can run. The limit that still applies: this article does not give a VPS price or a model API price, because they were not opened today. Price those separately with your provider. If your team wants us to set up the server and pick the transport, the MCP Server Development Service arranges hosting in one pass. It covers the Starter, Standard, and Custom packages. To start, Send your brief or Book a free consultation.

Sources