Repository navigation
Description
Hi there,
Thanks for the library, it's been great to use!
I have encountered a problem however. It doesn't work when I start mcp-remote in two terminals at the same time. This also causes issues when I try using copilot/claude/cursor while developing my server. I have to close the mcp-remote in my terminal each time.
Steps to Reproduce:
Run npx mcp-remote in two terminals at the same time. Second one doesn't work.
Details
I am connecting to an SSE server at port 8080 with:
npx mcp-remote http://localhost:8080/sse --header "Authorization: Bearer authToken"
First time I run it, it works fine. I get these logs (I changed the port numbers a little bit):
[43434] Using automatically selected callback port: 12121
[43434] Using custom headers: {"Authorization":" Bearer authToken"}
[43434] Creating lockfile for server 4f9e15cb6 with process 43434 on port 12121
[43434] OAuth callback server running at http://127.0.0.1:12121
[43434] [43434] Connecting to remote server: http://localhost:8080/sse
[43434] Connected to remote server
[43434] Local STDIO server running
[43434] Proxy established successfully between local STDIO and remote SSE
[43434] Press Ctrl+C to exit
While the server is still open in the terminal, I run the same command in another terminal and get:
[78787] Using automatically selected callback port: 90909
[78787] Using custom headers: {"Authorization":" Bearer authToken"}
[78787] Another instance is handling authentication on port 12121
[78787] Waiting for authentication from the server on port 12121...
[78787] Querying: http://127.0.0.1:12121/wait-for-auth
[78787] Authentication still in progress
[78787] Querying: http://127.0.0.1:12121/wait-for-auth
[78787] Authentication still in progress
[78787] Querying: http://127.0.0.1:12121/wait-for-auth
Note that 12121 ports are the same in both terminals.
While the second terminal sends the queries, the first terminal starts printing these logs:
[43434] Client requested no long poll, responding with 202
[43434] Long poll timeout reached, responding with 202
[43434] Long poll timeout reached, responding with 202
[43434] Long poll timeout reached, responding with 202
Activity
geelen commentedon Apr 16, 2025
Damn, so this is something I added to stop Claude Code firing up heaps of authorization windows (it forks 2 processes every time it boots, I have no idea why, and when your computer wakes from sleep you often see dozens of windows having opened up) It has been an improvement, but what I was hoping was that the two processes would coordinate and share the auth tokens once they appear on disk. That's been flaky from the beginning.
I think a
--allow-concurrentflag or similar that just skips that whole deduping might be worth doing, or make the current behaviour opt-in for Claude only 🤔Oh and it's only relevant to auth, so I suppose if you have a
Bearertoken it should be automatically disabled in the first place...glenngillen commentedon Apr 16, 2025
Thank you for working out what this and putting a fix in place (even if it's imperfect). I was losing my mind about how/why I was ending up with so many auth tabs open.
jmorrell-cloudflare commentedon Apr 16, 2025
@geelen We could block windows based on PID maybe? 🤔
geelen commentedon Apr 17, 2025
@CahidArda can you try
mcp-remote@latest? I've pushed the authorization flow later, so in the case where you're passing your own bearer token it shouldn't hit the dupe-prevention logic at all.Let me know how you go!
geelen commentedon Apr 17, 2025
The way I've come to understand it, the really pernicious bug is when the mcp-remote process lives only long enough to open the browser window then dies. So there's nothing to block on, the browser tab is actually useless since it's redirecting to a localhost port that's no longer open, but still when you wake your laptop from sleep you have a thousand tabs open 🫠
With the change in #32 there's a chance that the problem goes away as I'm being far less eager about trying to handshake the oauth. So, we'll see...
iWayne commentedon Apr 18, 2025
Face the same issue while quitting Claude desktop app doesn't kill the running
mcp-remote. Once re-open Claude app, newmcp-remoteprocess will get stuck.lzilioli commentedon Apr 24, 2025
I'm having the same issue. Very annoying. I constantly have to check the logs and kill the process listening on the stale port.
emilisb commentedon Apr 25, 2025
Hi! First of all, thank you for this amazing library - good job!
We as well ran into issues with multiple mcp-remote servers. More specifically:
~/.mcp-authfolder.I did some debugging and these are my findings:
Issue 1
mcp-remoteprocess is started, the auth http server is listening on port 3334 (default).1.1. A new lockfile is created (with current timestamp and port 3334).
1.2. If user has not authenticated before - auth flow will start and new token files will be written to disk.
1.3.
client_info.jsonwill contain callback urlhttp://127.0.0.1:3334/oauth/callback<- please pay attention to the port being3334here.mcp-remoteprocesses start, they check for an existing lock file. If the lock file is valid, auth flow uses the original process (using port3334). Everything is working fine here.The tricky part begins when more than 30 minutes have passed since the original process start time. Lock files older than 30 minutes are considered invalid (link to code), therefore a new lock file will be created. However, this time the port might not be
3334- if the original process using3334is still running, the process will choose a random port and this new process will become the new "master" process (responsible for auth of other processes).The problem is that now the new process has a different port than the previous one, therefore the new callback url is different. However,
client_info.jsonstill containshttp://127.0.0.1:3334/oauth/callback. This causes oauth token verification to fail on the server and you can no longer connect to the MCP server until you remove old tokens from~/.mcp-auth.In my opinion, the following changes might help:
Issue 2
I think this is the issue that OP had:
mcp-remoteis started for the first time and no auth token exists.mcp-remoteprocesses will work (if created within 30 minutes of first process start).mcp-remoteprocess are killed.mcp-remoteprocess is created (on default port 3334) - we now reuse the previously created tokens.mcp-remoteprocesses will fail to log in becauseauthCompletedPromiseis never resolved.emilisb commentedon Apr 25, 2025
I opened #39 with my proposed solutions
unforced commentedon Apr 30, 2025
Appreciate yah'll looking at this!
Bumped into this here, trying to set up an mcp-remote server in AnythingLLM.
Even after I changed the port to use 3339 it still keeps giving me the same error with 3334.
I'm assuming now that this is likely due to the lockfile?
unforced commentedon Apr 30, 2025
Waited the night and tried again and it seems to be working, so yep seems lockfile was probably the issue for me.
clouatre commentedon Sep 13, 2025
Concrete Multi-Instance Implementation & Findings
We've implemented mcp-remote across multiple MCP clients (Claude Code, OpenCode, Amazon Q) and discovered specific technical limitations with multiple Atlassian instances.
Working Multi-Instance Example (Claude Code)
Claude Code handles this scenario seamlessly with simple configuration (
~/.claude.json):{ "mcpServers": { "atlassian_confluence": { "command": "mcp-remote", "args": ["https://mcp.atlassian.com/v1/sse"] }, "atlassian_jira": { "command": "mcp-remote", "args": ["https://mcp.atlassian.com/v1/sse"] }, "atlassian_tenant2": { "command": "mcp-remote", "args": ["https://mcp.atlassian.com/v1/sse"] } } }Claude Code provides:
OpenCode Attempted Implementation
OpenCode configuration (
~/.config/opencode/opencode.json):{ "mcp": { "atlassian_confluence": { "type": "local", "command": ["mcp-remote", "https://mcp.atlassian.com/v1/sse"], "enabled": true }, "atlassian_jira": { "type": "local", "command": ["mcp-remote", "https://mcp.atlassian.com/v1/sse"], "enabled": true }, "atlassian_tenant2": { "type": "local", "command": ["mcp-remote", "https://mcp.atlassian.com/v1/sse"], "enabled": true } } }Observed Behavior Difference
Claude Code (Working): Each server connects to different Atlassian tenants during OAuth
OpenCode (Limited): All three servers share the same OAuth session and connect to whichever tenant was authorized first
Technical Root Cause
Authentication coordination in
coordination.ts:Evidence from Testing
getAccessibleAtlassianResourcesreturns same tenant for all servers~/.mcp-auth/mcp-remote-*/contains shared session dataEnterprise Impact & User Expectations
Multiple Atlassian tenants are common in enterprise environments:
User Expectation: Based on Claude Code's seamless multi-instance support, users expect the same behavior across MCP clients.
Since Atlassian officially endorses mcp-remote (Getting Started Guide), this limitation affects the official enterprise integration path.
Potential Technical Solutions
clouatre commentedon Sep 13, 2025
Concrete Multi-Instance Implementation & Findings
We've tested mcp-remote across multiple MCP clients and discovered specific technical limitations with multiple Atlassian instances. The issue is specifically with mcp-remote's authentication coordination, not the Atlassian MCP server itself.
Working Multi-Instance Example (Claude Code - Native SSE)
Claude Code handles multiple Atlassian instances seamlessly because it has native SSE support and connects directly to the server:
{ "mcpServers": { "atlassian_slalom": { "type": "sse", "url": "https://mcp.atlassian.com/v1/sse" }, "atlassian_plusgrade": { "type": "sse", "url": "https://mcp.atlassian.com/v1/sse" }, "atlassian_pointsbu": { "type": "sse", "url": "https://mcp.atlassian.com/v1/sse" } } }Claude Code provides:
Limited Multi-Instance Example (OpenCode - using mcp-remote)
OpenCode requires a proxy for SSE transport. We chose mcp-remote (other options like mcp-proxy exist):
{ "mcp": { "atlassian_slalom": { "type": "local", "command": ["mcp-remote", "https://mcp.atlassian.com/v1/sse"], "enabled": true }, "atlassian_plusgrade": { "type": "local", "command": ["mcp-remote", "https://mcp.atlassian.com/v1/sse"], "enabled": true }, "atlassian_pointsbu": { "type": "local", "command": ["mcp-remote", "https://mcp.atlassian.com/v1/sse"], "enabled": true } } }Observed Behavior Difference
Claude Code (Native SSE): Each server connects to different Atlassian tenants during OAuth
OpenCode (via mcp-remote): All three servers share the same OAuth session and connect to whichever tenant was authorized first
Technical Root Cause
Authentication coordination in
coordination.ts:Evidence from Testing
getAccessibleAtlassianResourcesreturns same tenant for all servers~/.mcp-auth/mcp-remote-*/contains shared session dataEnterprise Impact & User Expectations
Multiple Atlassian tenants are common in enterprise environments:
User Expectation: Based on Claude Code's seamless multi-instance support, users expect the same behavior when using mcp-remote.
Since Atlassian officially endorses mcp-remote (Getting Started Guide), this limitation affects the official enterprise integration path for MCP clients using mcp-remote as their SSE proxy.
Potential Technical Solutions
fix: isolate OAuth cache by resource and headers (punkpeye#25)
fix: isolate OAuth cache by resource and headers (#25)
fix: isolate OAuth cache by resource and headers (punkpeye#25)
Add --eager-auth: coordinate before the browser opens (v0.1.39)