modelcontextprotocol / modelcontextprotocol/typescript-sdk

SDK makes HTTPS fetches through an HTTP proxy

Open
#484 3 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug P2 ready for work
Dominant language
TypeScript
Stars
13.4k
Forks
2.2k
Avg merge
3d 15h
Merged PRs (30d)
4

Description

We have a corporate proxy, running on a localhost port, for third-party applications to be able to talk to internal services over HTTP. We can't complete connections over this proxy with the Typescript SDK (via the inspector) because, as far as I can tell, Node's fetch implementation ends up trying to run an HTTPS connection through the proxy and fails as the initial CONNECT to set up a tunnel gets early-terminated in a situation where the SDK is expecting the result of a plain HTTP call. In particular, here:

https://github.com/modelcontextprotocol/typescript-sdk/blob/68a0ca350576a9f7908010f1e4fef2f414cd0f9a/src/client/streamableHttp.ts#L455-L458

we get Unexpected content type: null, which our logs show is in response to that CONNECT request. (at the JSON-RPC layer, this is from the initialize request)

Ideally, when we have an HTTP_PROXY env var and no HTTPS_PROXY, we wouldn't be trying to use HTTPS at all.

As a reproduction of the CONNECT request being made, I had Claude write me a little fake version of an HTTP proxy:

st-ajgray1:mcp-repro ajgray$ cat proxy-server.js 
const http = require('http');
const net = require('net');

const server = http.createServer((req, res) => {
  console.log(`Regular HTTP request: ${req.method} ${req.url}`);
  
  // Handle normal HTTP requests
  res.writeHead(200);
  res.end('HTTP request handled');
});

server.on('connect', (req, clientSocket, head) => {
  console.log(`CONNECT request detected for: ${req.url}`);
  
  // Log but reject the CONNECT request
  clientSocket.write('HTTP/1.1 400 Bad Request\r\n\r\n');
  clientSocket.end();
});

server.listen(8888, () => {
  console.log('Proxy server running on port 8888');
});

Running the inspector while pointing at that proxy:

st-ajgray1:inspector ajgray$ HTTP_PROXY=http://127.0.0.1:8888 npm run start

And then trying to connect to a Streamable HTTP server fails:

Image

because this CONNECT request is detected:

st-ajgray1:mcp-repro ajgray$ node proxy-server.js 
Proxy server running on port 8888
CONNECT request detected for: fake-mcp-server.com:80

AIUI, this is consistent with the underlying fetch library, undici, trying to make this an HTTPS request. Due to limitations of our proxy, only HTTP would play nice with our systems; we would prefer that the SDK here make undici stay in HTTP-land here.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/client/streamableHttp.ts around lines 455-458 and reproduce through the inspector with HTTP_PROXY and the provided proxy-server.js. Trace how the SDK and Node fetch choose the proxy for the initialize request; done means an HTTP-only proxy does not trigger CONNECT and Streamable HTTP initialization succeeds.

Written by the indexing model from the issue text.

Assessment

Tech stack
nodejs, typescript
Domain
networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.