Merge pull request #708 from richardkmichael/fix-630
fix: STDIO and SSE transports need MCP_FULL_PROXY_ADDRESS
This commit is contained in:
commit
f94f2d8203
3 changed files with 161 additions and 7 deletions
|
|
@ -877,4 +877,129 @@ describe("useConnection", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("MCP_PROXY_FULL_ADDRESS Configuration", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
// Reset the mock transport objects
|
||||||
|
mockSSETransport.url = undefined;
|
||||||
|
mockSSETransport.options = undefined;
|
||||||
|
mockStreamableHTTPTransport.url = undefined;
|
||||||
|
mockStreamableHTTPTransport.options = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sends proxyFullAddress query parameter for stdio transport when configured", async () => {
|
||||||
|
const propsWithProxyFullAddress = {
|
||||||
|
...defaultProps,
|
||||||
|
transportType: "stdio" as const,
|
||||||
|
command: "test-command",
|
||||||
|
args: "test-args",
|
||||||
|
env: {},
|
||||||
|
config: {
|
||||||
|
...DEFAULT_INSPECTOR_CONFIG,
|
||||||
|
MCP_PROXY_FULL_ADDRESS: {
|
||||||
|
...DEFAULT_INSPECTOR_CONFIG.MCP_PROXY_FULL_ADDRESS,
|
||||||
|
value: "https://example.com/inspector/mcp_proxy",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { result } = renderHook(() =>
|
||||||
|
useConnection(propsWithProxyFullAddress),
|
||||||
|
);
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
await result.current.connect();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that the URL contains the proxyFullAddress parameter
|
||||||
|
expect(mockSSETransport.url?.searchParams.get("proxyFullAddress")).toBe(
|
||||||
|
"https://example.com/inspector/mcp_proxy",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sends proxyFullAddress query parameter for sse transport when configured", async () => {
|
||||||
|
const propsWithProxyFullAddress = {
|
||||||
|
...defaultProps,
|
||||||
|
transportType: "sse" as const,
|
||||||
|
sseUrl: "http://localhost:8080",
|
||||||
|
config: {
|
||||||
|
...DEFAULT_INSPECTOR_CONFIG,
|
||||||
|
MCP_PROXY_FULL_ADDRESS: {
|
||||||
|
...DEFAULT_INSPECTOR_CONFIG.MCP_PROXY_FULL_ADDRESS,
|
||||||
|
value: "https://example.com/inspector/mcp_proxy",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { result } = renderHook(() =>
|
||||||
|
useConnection(propsWithProxyFullAddress),
|
||||||
|
);
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
await result.current.connect();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that the URL contains the proxyFullAddress parameter
|
||||||
|
expect(mockSSETransport.url?.searchParams.get("proxyFullAddress")).toBe(
|
||||||
|
"https://example.com/inspector/mcp_proxy",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("does not send proxyFullAddress parameter when MCP_PROXY_FULL_ADDRESS is empty", async () => {
|
||||||
|
const propsWithEmptyProxy = {
|
||||||
|
...defaultProps,
|
||||||
|
transportType: "stdio" as const,
|
||||||
|
command: "test-command",
|
||||||
|
args: "test-args",
|
||||||
|
env: {},
|
||||||
|
config: {
|
||||||
|
...DEFAULT_INSPECTOR_CONFIG,
|
||||||
|
MCP_PROXY_FULL_ADDRESS: {
|
||||||
|
...DEFAULT_INSPECTOR_CONFIG.MCP_PROXY_FULL_ADDRESS,
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { result } = renderHook(() => useConnection(propsWithEmptyProxy));
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
await result.current.connect();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that the URL does not contain the proxyFullAddress parameter
|
||||||
|
expect(
|
||||||
|
mockSSETransport.url?.searchParams.get("proxyFullAddress"),
|
||||||
|
).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("does not send proxyFullAddress parameter for streamable-http transport", async () => {
|
||||||
|
const propsWithStreamableHttp = {
|
||||||
|
...defaultProps,
|
||||||
|
transportType: "streamable-http" as const,
|
||||||
|
sseUrl: "http://localhost:8080",
|
||||||
|
config: {
|
||||||
|
...DEFAULT_INSPECTOR_CONFIG,
|
||||||
|
MCP_PROXY_FULL_ADDRESS: {
|
||||||
|
...DEFAULT_INSPECTOR_CONFIG.MCP_PROXY_FULL_ADDRESS,
|
||||||
|
value: "https://example.com/inspector/mcp_proxy",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { result } = renderHook(() =>
|
||||||
|
useConnection(propsWithStreamableHttp),
|
||||||
|
);
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
await result.current.connect();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that streamable-http transport doesn't get proxyFullAddress parameter
|
||||||
|
expect(
|
||||||
|
mockStreamableHTTPTransport.url?.searchParams.get("proxyFullAddress"),
|
||||||
|
).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -409,11 +409,20 @@ export function useConnection({
|
||||||
|
|
||||||
let mcpProxyServerUrl;
|
let mcpProxyServerUrl;
|
||||||
switch (transportType) {
|
switch (transportType) {
|
||||||
case "stdio":
|
case "stdio": {
|
||||||
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/stdio`);
|
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/stdio`);
|
||||||
mcpProxyServerUrl.searchParams.append("command", command);
|
mcpProxyServerUrl.searchParams.append("command", command);
|
||||||
mcpProxyServerUrl.searchParams.append("args", args);
|
mcpProxyServerUrl.searchParams.append("args", args);
|
||||||
mcpProxyServerUrl.searchParams.append("env", JSON.stringify(env));
|
mcpProxyServerUrl.searchParams.append("env", JSON.stringify(env));
|
||||||
|
|
||||||
|
const proxyFullAddress = config.MCP_PROXY_FULL_ADDRESS
|
||||||
|
.value as string;
|
||||||
|
if (proxyFullAddress) {
|
||||||
|
mcpProxyServerUrl.searchParams.append(
|
||||||
|
"proxyFullAddress",
|
||||||
|
proxyFullAddress,
|
||||||
|
);
|
||||||
|
}
|
||||||
transportOptions = {
|
transportOptions = {
|
||||||
authProvider: serverAuthProvider,
|
authProvider: serverAuthProvider,
|
||||||
eventSourceInit: {
|
eventSourceInit: {
|
||||||
|
|
@ -431,10 +440,20 @@ export function useConnection({
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case "sse":
|
case "sse": {
|
||||||
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/sse`);
|
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/sse`);
|
||||||
mcpProxyServerUrl.searchParams.append("url", sseUrl);
|
mcpProxyServerUrl.searchParams.append("url", sseUrl);
|
||||||
|
|
||||||
|
const proxyFullAddressSSE = config.MCP_PROXY_FULL_ADDRESS
|
||||||
|
.value as string;
|
||||||
|
if (proxyFullAddressSSE) {
|
||||||
|
mcpProxyServerUrl.searchParams.append(
|
||||||
|
"proxyFullAddress",
|
||||||
|
proxyFullAddressSSE,
|
||||||
|
);
|
||||||
|
}
|
||||||
transportOptions = {
|
transportOptions = {
|
||||||
eventSourceInit: {
|
eventSourceInit: {
|
||||||
fetch: (
|
fetch: (
|
||||||
|
|
@ -451,6 +470,7 @@ export function useConnection({
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case "streamable-http":
|
case "streamable-http":
|
||||||
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/mcp`);
|
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/mcp`);
|
||||||
|
|
|
||||||
|
|
@ -378,7 +378,6 @@ app.get(
|
||||||
let serverTransport: Transport | undefined;
|
let serverTransport: Transport | undefined;
|
||||||
try {
|
try {
|
||||||
serverTransport = await createTransport(req);
|
serverTransport = await createTransport(req);
|
||||||
console.log("Created server transport");
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof SseError && error.code === 401) {
|
if (error instanceof SseError && error.code === 401) {
|
||||||
console.error(
|
console.error(
|
||||||
|
|
@ -391,11 +390,16 @@ app.get(
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
const webAppTransport = new SSEServerTransport("/message", res);
|
const proxyFullAddress = (req.query.proxyFullAddress as string) || "";
|
||||||
|
const prefix = proxyFullAddress || "";
|
||||||
|
const endpoint = `${prefix}/message`;
|
||||||
|
|
||||||
|
const webAppTransport = new SSEServerTransport(endpoint, res);
|
||||||
|
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
|
||||||
console.log("Created client transport");
|
console.log("Created client transport");
|
||||||
|
|
||||||
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
|
|
||||||
serverTransports.set(webAppTransport.sessionId, serverTransport);
|
serverTransports.set(webAppTransport.sessionId, serverTransport);
|
||||||
|
console.log("Created server transport");
|
||||||
|
|
||||||
await webAppTransport.start();
|
await webAppTransport.start();
|
||||||
|
|
||||||
|
|
@ -484,7 +488,7 @@ app.get(
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
try {
|
try {
|
||||||
console.log(
|
console.log(
|
||||||
"New SSE connection request. NOTE: The sse transport is deprecated and has been replaced by StreamableHttp",
|
"New SSE connection request. NOTE: The SSE transport is deprecated and has been replaced by StreamableHttp",
|
||||||
);
|
);
|
||||||
let serverTransport: Transport | undefined;
|
let serverTransport: Transport | undefined;
|
||||||
try {
|
try {
|
||||||
|
|
@ -511,9 +515,14 @@ app.get(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverTransport) {
|
if (serverTransport) {
|
||||||
const webAppTransport = new SSEServerTransport("/message", res);
|
const proxyFullAddress = (req.query.proxyFullAddress as string) || "";
|
||||||
|
const prefix = proxyFullAddress || "";
|
||||||
|
const endpoint = `${prefix}/message`;
|
||||||
|
|
||||||
|
const webAppTransport = new SSEServerTransport(endpoint, res);
|
||||||
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
|
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
|
||||||
console.log("Created client transport");
|
console.log("Created client transport");
|
||||||
|
|
||||||
serverTransports.set(webAppTransport.sessionId, serverTransport!);
|
serverTransports.set(webAppTransport.sessionId, serverTransport!);
|
||||||
console.log("Created server transport");
|
console.log("Created server transport");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue