Guide

MCP's data model stays the same either way: JSON-RPC requests such as tools/list and tools/call. The transport is how those bytes move. Pick wrong and you either cannot share the connector, or you publish a remote shell on an open port.

Concept

Before you start: a transport is the pipe under the protocol. stdio means the host spawned a process and speaks on stdin/stdout. Streamable HTTP means the server listens on a URL.

The big idea

stdio. The host starts the server as a subprocess. Credentials often come from that process's environment. There is no network surface. The trust boundary is "code you chose to run on this machine." This fits local tools: filesystem access, IDE helpers, a personal billing CLI.

Streamable HTTP. The server listens on a URL. The client connects remotely. This is what shared team servers and SaaS connectors need. Authorization typically follows an OAuth 2.1-style profile so users grant scoped access without pasting long-lived API keys into config files.

Trade-off

Use stdio for personal and local development tools. Use HTTP plus OAuth when several users or machines must share a connector. Do not expose a privileged stdio-style server over raw HTTP without auth. That publishes a remote shell for whoever can hit the port.

Walking through the isolation difference

A stdio server is a per-user process. Customer A's session cannot reuse Customer B's connection state, because there is no shared process. That is simpler isolation, and a worse fit for shared SaaS.

An HTTP server serving many users must authenticate every call. Reusing one customer's connection state for another is a tenancy bug, the same class of bug as any multi-tenant API.

Timeouts sit on both sides. Hosts abandon slow calls. Set a server-side timeout under the host's limit and return a structured error the model can retry or explain.

Log the tool name, latency, error class and a hash of the arguments. Do not log raw payloads that hold personal data. Correlate with the host's conversation id if the host sends one.

stdio:  host spawns process → env credentials → no network port
HTTP:   client opens URL    → OAuth grant     → shared, multi-user

Schema changes travel over either transport the same way. Removing a required field without a new tool name breaks every prompt that learned the old shape. Publish a changelog, and bump the server version the host pins.

Common mistakes

  • Putting a local privileged server on HTTP with no auth. The process was safe only because it was not reachable.
  • One OAuth grant that does everything. Scope down. Split servers by trust level.
  • Assuming stdio solves multi-tenancy in a SaaS host. Stdio isolation is per process. A shared HTTP server needs per-call auth.

Check yourself

  • A filesystem helper should run on which transport? stdio. It is local, and the trust boundary is the process you spawned.
  • Why does a shared billing connector need HTTP plus OAuth? Several users and machines must call it, and they should grant scoped access instead of sharing a long-lived key.

Key takeaways

  • stdio is a local subprocess. HTTP is a remote, shareable server.
  • OAuth is how remote users grant scoped access without pasting keys.
  • Authenticate every HTTP call. Never reuse one tenant's connection for another.

Further learning

Next, see what a hostile or sloppy server can do in MCP security.