mcp-proxy 6.5.0 → 6.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/mcp-proxy.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{stdio-BGZrO8Rz.mjs → stdio-DLwYts_5.mjs} +12 -2
- package/dist/stdio-DLwYts_5.mjs.map +1 -0
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/startHTTPServer.test.ts +30 -0
- package/src/startHTTPServer.ts +17 -2
- package/dist/stdio-BGZrO8Rz.mjs.map +0 -1
package/jsr.json
CHANGED
package/package.json
CHANGED
|
@@ -667,6 +667,36 @@ it("does not require auth for /ping endpoint", async () => {
|
|
|
667
667
|
await httpServer.close();
|
|
668
668
|
});
|
|
669
669
|
|
|
670
|
+
it("responds with 400 to a malformed request target instead of crashing", async () => {
|
|
671
|
+
const port = await getRandomPort();
|
|
672
|
+
|
|
673
|
+
const httpServer = await startHTTPServer({
|
|
674
|
+
createServer: async () => {
|
|
675
|
+
return new Server({ name: "test", version: "1.0.0" }, { capabilities: {} });
|
|
676
|
+
},
|
|
677
|
+
port,
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
// `//` is not a valid URL target; sent via http.request so it isn't
|
|
681
|
+
// normalized away. Before the fix this threw inside the request listener
|
|
682
|
+
// and crashed the process.
|
|
683
|
+
const statusCode = await new Promise<number>((resolve, reject) => {
|
|
684
|
+
const request = http.request(
|
|
685
|
+
{ host: "localhost", path: "//", port },
|
|
686
|
+
(res) => {
|
|
687
|
+
res.resume();
|
|
688
|
+
resolve(res.statusCode ?? 0);
|
|
689
|
+
},
|
|
690
|
+
);
|
|
691
|
+
request.on("error", reject);
|
|
692
|
+
request.end();
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
expect(statusCode).toBe(400);
|
|
696
|
+
|
|
697
|
+
await httpServer.close();
|
|
698
|
+
});
|
|
699
|
+
|
|
670
700
|
it("does not require auth for OPTIONS requests", async () => {
|
|
671
701
|
const port = await getRandomPort();
|
|
672
702
|
const apiKey = "test-api-key-999";
|
package/src/startHTTPServer.ts
CHANGED
|
@@ -688,7 +688,14 @@ const handleStreamRequest = async <T extends ServerLike>({
|
|
|
688
688
|
}
|
|
689
689
|
| undefined = sessionId ? activeTransports[sessionId] : undefined;
|
|
690
690
|
|
|
691
|
-
if (!sessionId) {
|
|
691
|
+
if (!sessionId) {
|
|
692
|
+
// Return METHOD_NOT_ALLOWED so stateless clients' transport stops reconnecting
|
|
693
|
+
if (stateless) {
|
|
694
|
+
res.writeHead(405, { Allow: "POST" }).end("Method Not Allowed");
|
|
695
|
+
|
|
696
|
+
return true;
|
|
697
|
+
}
|
|
698
|
+
|
|
692
699
|
res.writeHead(400).end("No sessionId");
|
|
693
700
|
|
|
694
701
|
return true;
|
|
@@ -944,7 +951,15 @@ export const startHTTPServer = async <T extends ServerLike>({
|
|
|
944
951
|
// and would otherwise short-circuit the MCP protocol handlers.
|
|
945
952
|
// Use a fixed base because `host` may be "::" (IPv6 any), which is not a
|
|
946
953
|
// valid URL authority. We only need pathname here.
|
|
947
|
-
|
|
954
|
+
// A malformed request target (e.g. "//") makes `new URL` throw, which
|
|
955
|
+
// would crash the process from this listener, so reject it with 400.
|
|
956
|
+
let requestUrl: URL;
|
|
957
|
+
try {
|
|
958
|
+
requestUrl = new URL(req.url || "", "http://localhost");
|
|
959
|
+
} catch {
|
|
960
|
+
res.writeHead(400).end("Bad Request");
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
948
963
|
const isMcpEndpoint =
|
|
949
964
|
(sseEndpoint && requestUrl.pathname === sseEndpoint) ||
|
|
950
965
|
(streamEndpoint && requestUrl.pathname === streamEndpoint);
|