Raviole Labs

MCP transports: local stdio vs remote HTTP, how to choose

Should an MCP server ship as a local stdio binary or a hosted HTTP endpoint? A decision matrix on data locality, auth, updates and install friction.

engrammcpmcpai agentsinfrastructure

Every MCP server ships over a transport, and the transport you pick decides more than plumbing. It sets where the data lives, who authenticates, how you push updates, and how much friction sits between a user and their first tool call. The choice usually comes down to mcp stdio vs http, and the two options pull in opposite directions. This is a builder’s take on when each one wins, with two servers we run in production as the reference points.

If you are new to the protocol itself, start with what is MCP. Here we assume you know what a tool call is and want to decide how to serve one.

The two transports and what the MCP client actually sees

An MCP client (Claude Desktop, Cursor, your own agent loop) speaks JSON-RPC. It does not care whether the bytes travel over a pipe or a socket. What differs is how the client reaches the server.

With stdio, the client spawns your server as a child process and talks to it over stdin and stdout. The server runs on the same machine as the client. There is no port, no URL, no listener.

With HTTP (today the streamable HTTP transport, previously HTTP+SSE), your server is a long-lived endpoint at a URL. The client opens a connection, POSTs requests, and reads a stream of responses. The server runs wherever you host it.

Same protocol, same tool schemas. The wire is the only difference, and everything downstream of the wire flows from it.

stdio: local process, zero network, private data

stdio is the right call when the data must not leave the machine. The server runs as a local process, so nothing touches the network unless you explicitly make an outbound call.

That is exactly the shape of EngramMCP. Engram is semantic memory that runs entirely on your box: SQLite for structured storage, LanceDB for vectors, and Ollama running nomic-embed-text for embeddings. When you call remember or recall, the text is embedded locally and the vectors are written to a local file. No inference API, no vector database bill, no data crossing a wire you do not control. This is the local-first memory argument in transport form: if the whole point is privacy and no recurring cost, a hosted endpoint would undercut it.

stdio also means state is per-user by construction. Each user runs their own process against their own files. There is no multi-tenancy to reason about because there is no shared server. The tradeoff: you can only reach users who can run the binary, and every update is a redeploy on their side.

Engram is core source-available and invite-only in early access. You ask for access by DM on X at @LeRaviole_. That gating fits the stdio model well: the audience is deliberate, and each install is a real machine you know runs the code locally.

HTTP/SSE: hosted, multi-user, API keys, rate limits

The moment your server needs shared data, centralized rate limiting, or an audience that should not install anything, you want HTTP. One endpoint serves everyone, and you control it.

PredMCP is the HTTP case. It exposes 47 tools across Polymarket, Hyperliquid perps, and HIP-4, plus cross-venue signals that only make sense when one server sees all the venues at once. That data is not local to anyone: it is market data the server aggregates and serves. Running it as a hosted endpoint is the only sane option.

HTTP is also where auth and quotas live naturally. PredMCP is free in early access with 100 calls per day per key and no card required. That quota is enforced server-side, per API key, which is a thing you simply cannot do from a stdio process running on someone else’s laptop. When mcp stdio vs http comes down to “do I need to meter this,” HTTP wins by default.

The cost you take on: you now run infrastructure. Uptime, TLS, key management, abuse handling, and a bill that scales with usage are all yours.

Decision matrix: data locality, auth, update cadence, install friction

Four questions settle most cases.

  • Data locality. If the data is the user’s and must stay on their machine, stdio. If the data is yours to aggregate and serve, HTTP.
  • Auth. No per-user metering needed, stdio is fine. Need API keys, quotas, or tiers, HTTP.
  • Update cadence. Ship changes daily and want everyone on the latest instantly, HTTP updates in one deploy. Rare, deliberate updates, stdio is acceptable.
  • Install friction. HTTP is a URL and a key, the lowest possible friction. stdio needs a runtime, a config entry, and often local dependencies (Engram needs Ollama present).

The pattern holds: stdio when the data is private and local, HTTP when it is shared and metered.

Packaging and distribution for each

For stdio, you distribute an executable. The client config points at a command and args:

{
  "mcpServers": {
    "engram": { "command": "engram", "args": ["serve"] }
  }
}

Your job is making that binary easy to obtain and its dependencies easy to satisfy. Pin versions, fail loudly when Ollama is missing, and keep startup fast because the client spawns you on every session.

For HTTP, you distribute a URL and a way to get a key. The config is just the endpoint plus an auth header. PredMCP hands you a key on signup and you are calling tools in under a minute. Your job is keeping the endpoint up and the key flow painless.

Offering both, and how to migrate

The transport is not the protocol, so a well-factored server can offer both. Keep your tool handlers pure: take typed input, return typed output, no assumptions about the wire. Then a stdio entrypoint and an HTTP entrypoint are two thin adapters over the same core.

Migrating stdio to HTTP is mostly additive. You wrap the same handlers in an HTTP server, add auth middleware and rate limiting, and move any local-only state (files, a local model) to a hosted equivalent. The reverse, HTTP to stdio, is harder: you have to give up shared state and per-key metering, which is why servers built around aggregation rarely make that trip.

Pick the transport that matches the data, not the one that is easier to write. Get that right and the rest is adapters.