# mcp-remote: a stdio bridge for MCP clients that cannot do OAuth

> mcp-remote is a proxy that lets a stdio-only MCP client talk to a remote MCP server, handling the OAuth flow in between. It is a stopgap, and it is built like one.

**punkpeye/mcp-remote** — Connect an MCP Client that only supports local (stdio) servers to a Remote MCP Server.

- Repository: https://github.com/punkpeye/mcp-remote
- Website: https://glama.ai/mcp/servers
- Stars: 1,607 · Forks: 301
- Language: TypeScript
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/punkpeye-mcp-remote

## The stdio-only client problem mcp-remote solves

Most MCP servers in the wild are installed locally and speak stdio. The README lays out why that has been comfortable: client and server implicitly trust each other because the user granted both permission to run, API keys stay in environment variables on the machine, and npx and uvx mean there is often no explicit install step. The trade-off is distribution. The README puts it plainly: most software that could move to the web did move to the web, because a single deploy reaches every user.

The MCP Authorization specification of 2025-03-26 gives a way to expose an MCP server over HTTP without running code on a user's laptop. The missing piece is client support. The README states that most popular MCP clients are stdio-only, and the ones that do support HTTP+SSE do not yet support the OAuth flows the spec requires. mcp-remote fills that gap by running locally as a stdio server to the client and as an HTTP client to the remote server, so the client never learns it is talking to something remote. The README is explicit that this is temporary: as soon as your chosen client supports remote, authorized servers, you can remove it.

## How the proxy and its OAuth session work

The package installs two binaries, mcp-remote and mcp-remote-client, both built from TypeScript sources into dist. The client spawns mcp-remote as a normal stdio process and passes the remote server URL as the first argument. The proxy then opens an HTTP connection to that URL and, when the server requires authorization, runs the OAuth flow on the local machine, opening a browser for the user to sign in.

Session isolation is the part worth understanding before you configure anything. The README states that each unique combination of server URL, resource, custom headers, and --authorize-param values maintains separate OAuth sessions and token storage. That is what makes two Atlassian tenants usable side by side: same server URL, different --resource values, different token stores. The --resource value is sent as the RFC 8707 resource indicator on the authorization, token and refresh requests alike, so the three always agree.

Authorize parameters are a narrower channel than they first appear. The README says they apply to the authorization request only, with resource as the exception. Parameters the flow derives per request, including state, code_challenge, client_id, redirect_uri and response_type, are refused, because a value that disagrees with the real one surfaces as an opaque server error. Changing an authorize parameter starts a new sign-in, since a parameter like audience decides which API the token is for and a token issued for one is not valid for another.

## Installing mcp-remote and getting a first server connected

There is no global install step in the README. You add mcp-remote to the config file of a client such as Claude Desktop, Cursor or Windsurf, and the client invokes it through npx. The README gives this shape as the common format:

```json
{
  "mcpServers": {
    "remote-example": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://remote.mcp.server/sse"
      ]
    }
  }
}
```

After saving that and restarting the client, the remote server should appear alongside your local ones, and if it requires authorization the proxy should open a browser window for the sign-in.

If npx reports errors, the README suggests adding -y as the first argument so the package installation is auto-accepted. To force a check for a newer version on every start, use mcp-remote@latest in place of the bare package name. Both go inside the args array in the same position as the package name.

For a server that needs a bearer token instead of an interactive flow, pass a header. Note the escaping bug the README documents: Cursor, Codex-Cli and Claude Desktop on Windows mangle spaces inside args, so the header value is split across the colon and the space is put in the environment variable instead.

```json
{
  "mcpServers": {
    "remote-example": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://remote.mcp.server/sse",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "Bearer <auth-token>"
      }
    }
  }
}
```

The README warns that a credential passed this way is visible in the process list to any other user on the machine. The alternative it gives is --header-file, pointing at a file with one Name: value per line and # starting a comment. A file that cannot be read is treated as an error rather than a warning, so a mistyped path fails immediately instead of sending the request unauthenticated.

## Redirect ports, resource parameters and the failure modes to expect

The proxy listens on a local port to receive the OAuth redirect. By default the port is derived from the server URL, so each server gets a stable port somewhere in 3335 to 49150, and mcp-remote walks up to eight ports from there if it finds one taken. If you pass a port explicitly, that port is used as-is. The README explains why there is no fallback: an explicit port implies a redirect_uri the authorization server has already been given, so quietly moving to another one would break the flow, and mcp-remote fails instead. --static-oauth-client-info pins the port for the same reason.

The resource parameter is the other common source of breakage. Some authorization servers reject it outright. The README names Microsoft Entra ID v2, which answers AADSTS9010010, and offers --disable-resource-parameter to omit it entirely. If you are pointing mcp-remote at an Entra-protected server and the sign-in fails with an opaque error, that flag is the first thing to try.

Two limits are worth stating plainly. First, this is a bridge, not a destination. The README says to remove it once your client supports remote, authorized servers, which means the configuration you write today has a known expiry. Second, tokens live in local storage keyed by the combination described above, and the proxy runs as a local process alongside your client. If your threat model does not allow a local helper to hold refresh tokens for a remote service, mcp-remote is the wrong tool regardless of how convenient the one-liner is.

## How mcp-remote differs from running the server locally

The obvious alternative is not another proxy. It is installing the MCP server itself with npx or uvx and pointing the client at a stdio command, which is what the README describes as the majority of servers in the wild. The difference in approach is where the code and the credentials live. A local server runs on your machine, reads its API keys from environment variables that never leave the machine, and can be trusted implicitly because you granted it permission to run. A remote server behind mcp-remote runs on someone else's infrastructure, gets updated without you doing anything, and authenticates through an OAuth flow that hands the proxy a token.

That trade is the whole point of the project. If the server you need is only offered remotely, or if you want the operator to be able to fix bugs and ship features with a single deploy, the local install is not available to you. If the server is available locally and its dependencies are manageable, the local path avoids the proxy, the browser flow, the redirect port and the token store entirely. The README does not argue that remote is better in general; it argues that the ecosystem has not finished moving, and this bridges the interval.

## Release cadence, licence and what upgrades cost

The repository is MIT licensed and is not archived. Its last push was on 2026-09-09, and the releases recorded around that date are v0.8.6, v0.8.5 and v0.8.4, appearing on consecutive days. The package.json in the repository carries a different version field, 0.1.38, which does not match the release tags; the published binaries come from dist, so the version you actually run is the one npm resolves, not the one in the source tree. That is a detail to check rather than assume.

Upgrade cost is low in the default configuration because npx fetches the package each time the client starts. The README offers mcp-remote@latest to force an update check, and -y to skip the install prompt. The catch is that a floating version means the code running under your client can change between sessions without any action from you, which is convenient until a release changes behavior you depended on. Pinning a specific version in args is the way to stop that, at the cost of doing the upgrades yourself.

MIT places few obligations on use, but the licence covers the proxy, not the remote server you connect it to, and the README notes that credentials can end up in process arguments or in a header file on disk. Those are operational choices, not licence questions.

## Conclusion

Adopt mcp-remote if your MCP client is stdio-only and the server you want is remote and behind OAuth. Skip it if your client already speaks HTTP with authorization, or if you cannot accept that a local process holds your tokens. Before rolling it out, verify the redirect port your server URL derives, confirm whether your authorization server rejects the resource parameter, and check the installed package version rather than trusting @latest.

## FAQ

### How do I install mcp-remote?

There is no separate install step. You add mcp-remote to the mcpServers section of your MCP client's config and let the client invoke it through npx, with the remote server URL as the first argument. If npx reports errors, the README suggests adding -y as the first argument to auto-accept the package installation.

### How do I use mcp-remote?

Point your stdio-only MCP client at the mcp-remote command with the remote server URL, and the proxy handles the HTTP connection and the OAuth sign-in on your behalf. If the server needs a bearer token, pass it with --header or put it in a file and pass --header-file.

### What does mcp-remote do?

It connects an MCP client that only supports local stdio servers to a remote MCP server, including the authorization flow the client does not implement. The README describes it as a temporary bridge to remove once your client supports remote, authorized servers on its own.

### Is mcp-remote safe?

The README warns that a credential passed through --header is visible in the process arguments to any other user on the machine, and offers --header-file to keep it out of the process list. Tokens are stored locally by the proxy, keyed by the server URL, resource, headers and authorize parameters, so the answer depends on whether a local helper holding those tokens fits your threat model.

### What is npx mcp remote?

It is the way mcp-remote is normally launched. The README's client config uses the npx command with mcp-remote and the remote server URL in args, so npx fetches and runs the proxy without a separate install. Adding -y auto-accepts the package installation, and mcp-remote@latest forces an update check.

### What is the difference between mcp remote and a local server?

A local server runs on your machine with its API keys in environment variables that never leave it, and client and server trust each other because you granted both permission to run. A remote server behind mcp-remote runs on someone else's infrastructure, can be updated with a single deploy, and authenticates through an OAuth flow that hands the proxy a token.

## Sources

- [License: MIT](https://github.com/punkpeye/mcp-remote/blob/main/LICENSE)
- [Project website](https://glama.ai/mcp/servers)
- [punkpeye/mcp-remote on GitHub](https://github.com/punkpeye/mcp-remote)
- [README](https://github.com/punkpeye/mcp-remote/blob/main/README.md)
- [Releases](https://github.com/punkpeye/mcp-remote/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/punkpeye-mcp-remote
