Remote vs Local MCP Servers: How to Connect and Which Is Safer
A local MCP server is a program your client starts on your machine; a remote one is a service at a URL you sign in to. How to connect each kind in the main clients, where your data and credentials go, what each one can harm, and a short guide to choosing.
9 min read
A local MCP server is a program on your own computer. Your client starts it, talks to it over standard input and output (stdio), and stops it when you close the app. A remote MCP server is a service somewhere else with a URL, usually ending in /mcp, that your client reaches over Streamable HTTP and normally signs in to with OAuth. Neither is safer in general; they fail in different ways. A local server runs with all of your own permissions, so the risk is the code you let it run. A remote server runs someone else’s code on someone else’s machine, so the risk is who operates it and what your sign-in lets it do. The short rule: for a cloud service you already use, connect the vendor’s own remote server with a browser sign-in; for anything that needs your files or your local network, run a local server you have read and pinned.
This guide is about choosing and connecting. How the two transports work on the wire, and what happened to the old SSE transport, is in MCP transports.
What local and remote actually mean
- Local (stdio): the client launches the server as a child process from a command you configure, such as
npx,uvxordocker. Only that client can talk to it. It dies with the client and needs its runtime installed on every machine that uses it. - Remote (Streamable HTTP): the server is already running, on a vendor’s infrastructure or your own. You give the client a URL. Many people and many clients can use it at once, so it has to know who is calling, which is why remote servers sign you in.
- The awkward middle: an HTTP server running on
localhost. It is local in location but reachable by any process on the machine. The specification’s security best practices (opens in a new tab) advise servers meant to run locally to use stdio, or to require an authorisation token if they use HTTP.
Connecting each kind, client by client
- Claude Desktop: local servers go in
claude_desktop_config.json, as the Claude Desktop MCP config shows. A remote server is not added to that file; it is a custom connector under Customize, then Connectors, and Anthropic’s help page on custom connectors (opens in a new tab) says the connection comes from Anthropic’s cloud, not your device, so the server must be reachable from the internet or allowlist Anthropic’s IP addresses. - Claude Code: both, from one command.
--transport httpwith a URL for remote, or--transport stdioand a command after--for local, as in the example below and the Claude Code MCP documentation (opens in a new tab). - ChatGPT: remote only. Developer mode takes a server URL with OAuth, no authentication or a mix; ChatGPT connectors and apps covers the rest.
- VS Code: an entry in
mcp.jsonwith"type": "stdio"and acommand, or"type": "http"and aurl. The step-by-step is in VS Code mcp.json. - Cursor:
.cursor/mcp.jsonin a project or~/.cursor/mcp.jsonfor every project, withcommandfor a local server orurlfor a remote one. See the Cursor integration page.
# Remote: a URL. Sign in afterwards with /mcp. claude mcp add --transport http fenbs https://fenbs.ai/api/mcp # Local: a command Claude Code starts, with its key in the environment. claude mcp add --env DOCS_API_KEY=your-key --transport stdio docs -- npx -y @your-org/docs-mcp@2.3.1
The full list of clients, and which features beyond tools each one supports, is in which apps support MCP.
Where your data goes
Three paths matter, and the third is the one people forget.
- Client to server. With a local server this never leaves your machine. With a remote one it crosses the internet to whoever runs the server, and with Claude on the web or ChatGPT it starts in the vendor’s cloud rather than on your computer.
- Server to the service behind it. A local server calls the service’s API from your own network, with your IP address and your proxy. A remote server calls it from its own infrastructure, or it is the service itself.
- Everything to the model. Whatever a tool returns goes into the conversation, and the conversation goes to the model provider. A local server that reads a confidential file sends that file to the model just as a remote one would. Local keeps the server off the path; it does not keep the data off it.
That second path is why local servers suit anything that sits behind your firewall, and the first is why a cloud chat app cannot reach a server on your laptop or your office network without help, which comes up again under bridges.
Credentials: environment variables or OAuth
The two kinds sign in differently by design. The MCP authorization specification (opens in a new tab) is written for HTTP transports and says stdio implementations should not follow it and should retrieve credentials from the environment instead. So a local server gets an API key in its env block, and a remote server sends you through a browser sign-in.
- An environment variable is simple and works offline. It is also a long-lived key in a plain-text file, usually with all of your access, readable by anything that can read your profile, and shared by every client that reads that file. Rotate it by hand.
- OAuth never shows the client your password. The token is issued to that one client, can be limited to the scopes you approve, is usually short-lived and refreshed quietly, and can be revoked on its own without changing your password. The server also knows which client made each call.
- A remote server with a static header, such as
Authorization: Bearer …, sits between the two. It is the right tool for a script or CI job with no browser, but it is a key again: reference it as an environment variable (${VAR}in Claude Code’s.mcp.json,${env:NAME}in Cursor) rather than pasting it into a committed file.
What happens in the browser during that sign-in is in how MCP sign-in works, and the server side in how to add authentication to an MCP server.
Which is safer
- Local risk: arbitrary code with your privileges. A malicious package, or a malicious startup command pasted into a config, can read your SSH keys or delete files. Unpinned
npx -y packageruns whatever version was published last. Mitigate by installing only from sources you trust, pinning versions, reading the command before you save it, and running untrusted servers in a container. - Remote risk: the operator and the token. The server sees every argument your assistant sends it, and a stolen token acts as you until it expires or is revoked. Mitigate by preferring the service’s own official server over a third-party wrapper, approving narrow scopes, and revoking connections you no longer use.
- Shared risk: prompt injection. A tool result can carry instructions written by someone else, whether the server is local or remote. The documented cases are in MCP security risks.
On balance, for a service that already holds your data in the cloud, its vendor’s remote server with OAuth usually wins: no third-party code on your machine and no permanent key in a file. For your own files, a local database or an internal tool, a local server wins because nothing needs to be exposed at all.
When the client cannot reach the server
- Cloud chat apps cannot reach
localhost. Claude on the web and ChatGPT call servers from their makers’ infrastructure, so a local server is invisible to them. - Claude Desktop’s config file only starts processes. A URL goes in as a connector instead.
- VS Code agent harnesses differ. The agent harnesses page (opens in a new tab) says Copilot harness sessions can currently reach only local MCP servers that do not require authentication, so a remote server with a sign-in needs a Local session.
- Some older or minimal clients speak only stdio and have no way to add a URL at all.
Bridging one kind to the other
- A stdio client that needs a remote server: a small local bridge that the client starts as a command, which forwards to the URL and handles the sign-in. The community
mcp-remotepackage is the common one, used asnpx mcp-remote https://example.com/mcp. It is third-party code holding your tokens, so pin and review it like any other local server. - A cloud app that needs a private server: either expose the server publicly with proper sign-in, allowlist the vendor’s addresses, or use a vendor tunnel. OpenAI’s Secure MCP Tunnel (opens in a new tab) is an outbound-only connection from a host inside your network to an OpenAI-hosted endpoint, for ChatGPT developer mode, Codex and the Responses API.
- A local server that the whole team needs: that is the point to host it as a remote server with authentication, rather than asking everyone to install it.
A decision guide
- Does the tool need your files, your terminal or your local network? Local, over stdio.
- Is it a cloud service with an official remote server? Remote, with OAuth. Do not install a third-party local wrapper for a service that offers its own endpoint.
- Will people use it from Claude on the web, ChatGPT or a phone? It has to be remote and reachable by those vendors.
- Is it for a script, a CI job or a machine with no browser? Remote with a hand-issued token in an environment variable, or local with an environment key.
- Is it internal and sensitive? Local for one person; remote behind your own sign-in, or a vendor tunnel, for a team.
- Is your client stdio-only? A pinned bridge, reviewed like any other local code.
fenbs: a remote server with a sign-in
fenbs, a task board where people and AI assistants are members with roles, is a remote MCP server at https://fenbs.ai/api/mcp, so the same URL works in each client above that takes a remote server. The first call opens fenbs in your browser; you sign in, tick what the assistant may do (reading is always on; adding and changing tasks, and commenting, are your choice) and approve. The assistant gets an access token that lasts an hour and refreshes, it can never do more than your own role on the board allows, and revoking it under Settings ends its access without touching your own sign-in. For a script or a client with no browser, a token issued by hand under Settings has a name, the scopes you tick and an optional expiry, and is sent as an Authorization: Bearer header. Either way, every change it makes is recorded in History under its name.
Related
Setup and the full tool list: MCP docs. What a token may do on a board: assistant tokens and scopes. The three kinds of Claude connector: Claude connectors explained. Habits for any connection: MCP security best practices. What each connected server costs in context: why MCP servers eat your context window.