-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Allow bypassing proxy with Connection Type dropdown #810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow bypassing proxy with Connection Type dropdown #810
Conversation
- Add state for connectionType
- Fetch connectionType from localstorage if present
* In Sidebar.tsx
- Add dropdown for connectionType, only visible if transport type is not stdio
* In Sidebar.test.tsx
- set connectionType to "proxy"
* In useConnection.ts
- add connectionType param, defaulting to "proxy"
- add state for mcpSessionId
- Only check proxy health if the connection type is proxy
- create a serverUrl variable which will either be the proxy url OR the server url depending upon the connection type
- added captureResponseHeaders function to extract the protocol-related headers from a response.
- when creating transport options and connectionType is "direct" and transportType is not "stdio",
- add the appropriate `Accept` and `Content-Type` headers
- capture the protocol related response headers and store them in the custom fetch handler
- set serverUrl to be the server url, not the proxy url
- if connection type is proxy set serverUrl to the mcpProxyUrl
- use serverUrl instead of mcpProxyUrl for the transport instantiation
* In useConnection.test.tsx
- replaced test "sends X-MCP-Proxy-Auth header when proxy auth token is configured" with two tests:
- "sends X-MCP-Proxy-Auth header when proxy auth token is configured for 'proxy' connectionType"
- "does NOT send X-MCP-Proxy-Auth header when proxy auth token is configured for 'direct' connectionType"
- added Connection URL Verification section with 2 tests
- uses server URL directly when connectionType is 'direct'"
- "uses proxy server URL when connectionType is 'proxy'"
My initial take when I raised this in discord a few months back was "can we do away with it for all but stdio servers." The answer, of course, is CORS. Unless servers are built with an open door CORS policy, it won't work. Right now that's 99.999% of all servers because this is the first time we're trying to hit a server directly with the browser.
The problem with the proxy is that it has two transports, Client <-> Proxy & Proxy <-> Server. Bridging headers and responses is not as automatic as you might think. I recently had to add a bunch of code to fish headers out of the responses and shuttle them back to the client because headers that weren't part of the initial connection but that were introduced later in the conversation weren't making it back and were therefore being dropped from later requests, i.e, A number of issues that have come up have shown that the proxy makes communications more opaque and difficult to troubleshoot. This is why an option to connect directly is desirable. You can be certain that the headers and responses arriving in the browser (or failing to) are not the result of the proxy acting as an unintentional filter.
The problem is that it is never going to be as optimal as a direct connection. You can never be certain that some flaw in the proxy itself isn't causing the problem. If you are having a particularly difficult time troubleshooting the problem, even with the source of the proxy running locally and adding in more log statements, if you bypass the proxy, you can rule it out completely.
Sure we can do tooltips - I can do that right away. And entries in the readme as well as the documentation in on the website. And a blog post about this way of debugging things. An educational outreach step can come after the feature is available. People can see that with a minor config change to their server, they can make the communications much clearer and easier to debug. |
@felixweinberger That's a lot of text to go in a tooltip or to take up valuable space in the sidebar. Here's a crack at a compromise:
|
- Add tooltip over the Connection Type field
|
A drive-by proposal on an alternative (I might be missing something here, sorry if so!): always default to direct, and if that doesn't work try proxy. If no proxy is available or it still doesn't work, throw an error. This removes people having to think about / understand this at all, which is probably better UX. (If we want to generally encourage allowing direct connections, we could have a green tick + 'connected directly' OR orange warning sign 'connected via proxy' with info bubble with tooltip linking to some docs about CORS) |
|
Woohoo! We have the server side of this effort merged: |
@domdomegg That would be an interesting approach I do like it. But maybe a 2.0? It will be a bit more involved to manage the state for that. The useConnection hook could use a bit of refactoring first. I think we need to do some educational outreach, documentation, blog posts, etc on opening up CORS first and how this can give you a better troubleshooting experience first. |
domdomegg
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM



Description
In App.tsx
In Sidebar.tsx
In Sidebar.test.tsx
In useConnection.ts
AcceptandContent-TypeheadersIn useConnection.test.tsx
Motivation and Context
Multiple issues have been raised where the proxy has obfuscated what is actually going on with the server.
Checking the browser's network inspector tab doesn't help because it only shows the connection to the proxy, not what was actually sent to or returned from the server.
The Proxy is only actually necessary for STDIO connections, because it runs the server in a process. For SSE and StreamableHttp servers, the only hurdle for connecting directly from the browser is that the server must configure CORS to allow it.
So for developers who would like better insight into the traffic and don't mind configuring CORS on their server, this dropdown (which only appears for SSE and StreamableHttp Transport types) is a great way to cut out the middleman.
How Has This Been Tested?
I added CORS configuration to the Everything Reference server for its SSE and StreamableHttp transports.
Direct SSE Connection From Inspector
Direct StreamableHttp Connection From Inspector
Proxied SSE Connection From Inspector
Proxied StreamableHttp Connection From Inspector
Breaking Changes
Nope.
Types of changes
Checklist
Additional context
Test against this PR on the Servers repo: modelcontextprotocol/servers#2725