Skip to content

Commit bae36ef

Browse files
authored
UI : fix SSE transport detection and routing through CORS proxy. Assi… (#24500)
* UI : fix SSE transport detection and routing through CORS proxy. Assisted-by: Antigravity * ui : replace magic strings with constants in MCP transport handling
1 parent 5157172 commit bae36ef

3 files changed

Lines changed: 82 additions & 5 deletions

File tree

tools/ui/src/lib/constants/mcp.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,8 @@ export const MCP_TRANSPORT_ICONS: Record<MCPTransportType, Component> = {
8484
[MCPTransportType.STREAMABLE_HTTP]: Globe,
8585
[MCPTransportType.SSE]: Radio
8686
};
87+
88+
/** Standard SSE endpoint path indicators */
89+
export const MCP_SSE_ENDPOINT = '/sse';
90+
export const MCP_SSE_ENDPOINT_SLASH = '/sse/';
91+
export const MCP_SSE_ENDPOINT_QUERY = '/sse?';

tools/ui/src/lib/services/mcp.service.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import {
1616
DEFAULT_MCP_CONFIG,
1717
DEFAULT_CLIENT_VERSION,
1818
DEFAULT_IMAGE_MIME_TYPE,
19-
MCP_PARTIAL_REDACT_HEADERS
19+
MCP_PARTIAL_REDACT_HEADERS,
20+
CORS_PROXY_ENDPOINT
2021
} from '$lib/constants';
2122
import {
2223
MCPConnectionPhase,
@@ -236,6 +237,36 @@ export class MCPService {
236237

237238
return {
238239
fetch: async (input, init) => {
240+
if (useProxy && typeof window !== 'undefined') {
241+
let requestUrlStr = '';
242+
if (typeof input === 'string') {
243+
requestUrlStr = input;
244+
} else if (input instanceof URL) {
245+
requestUrlStr = input.href;
246+
}
247+
248+
if (requestUrlStr) {
249+
const parsedRequestUrl = new URL(requestUrlStr, window.location.origin);
250+
if (
251+
parsedRequestUrl.origin === window.location.origin &&
252+
!parsedRequestUrl.pathname.includes(CORS_PROXY_ENDPOINT)
253+
) {
254+
const originalConfigUrl = new URL(config.url);
255+
const realTargetUrl = new URL(
256+
parsedRequestUrl.pathname + parsedRequestUrl.search,
257+
originalConfigUrl.origin
258+
);
259+
const proxiedUrl = buildProxiedUrl(realTargetUrl.href);
260+
261+
if (typeof input === 'string') {
262+
input = proxiedUrl.href;
263+
} else if (input instanceof URL) {
264+
input = proxiedUrl;
265+
}
266+
}
267+
}
268+
}
269+
239270
const startedAt = performance.now();
240271
const requestHeaders = new Headers(baseInit.headers);
241272

@@ -403,6 +434,32 @@ export class MCPService {
403434
};
404435
}
405436

437+
if (config.transport === MCPTransportType.SSE) {
438+
const url = useProxy ? buildProxiedUrl(config.url) : new URL(config.url);
439+
const { fetch: diagnosticFetch, disable: stopPhaseLogging } = this.createDiagnosticFetch(
440+
serverName,
441+
config,
442+
requestInit,
443+
url,
444+
useProxy,
445+
onLog
446+
);
447+
448+
if (import.meta.env.DEV && import.meta.env.VITE_DEBUG) {
449+
console.log(`[MCPService] Creating SSE transport for ${url.href}`);
450+
}
451+
452+
return {
453+
transport: new SSEClientTransport(url, {
454+
requestInit,
455+
fetch: diagnosticFetch,
456+
eventSourceInit: { fetch: diagnosticFetch }
457+
}),
458+
type: MCPTransportType.SSE,
459+
stopPhaseLogging
460+
};
461+
}
462+
406463
const url = useProxy ? buildProxiedUrl(config.url) : new URL(config.url);
407464
const { fetch: diagnosticFetch, disable: stopPhaseLogging } = this.createDiagnosticFetch(
408465
serverName,

tools/ui/src/lib/utils/mcp.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ import {
1919
DISPLAY_NAME_SEPARATOR_REGEX,
2020
PATH_SEPARATOR,
2121
RESOURCE_TEXT_CONTENT_SEPARATOR,
22-
DEFAULT_RESOURCE_FILENAME
22+
DEFAULT_RESOURCE_FILENAME,
23+
MCP_SSE_ENDPOINT,
24+
MCP_SSE_ENDPOINT_SLASH,
25+
MCP_SSE_ENDPOINT_QUERY
2326
} from '$lib/constants';
2427
import {
2528
Database,
@@ -41,10 +44,22 @@ import type { MimeTypeUnion } from '$lib/types/common';
4144
export function detectMcpTransportFromUrl(url: string): MCPTransportType {
4245
const normalized = url.trim().toLowerCase();
4346

44-
return normalized.startsWith(UrlProtocol.WEBSOCKET) ||
47+
if (
48+
normalized.startsWith(UrlProtocol.WEBSOCKET) ||
4549
normalized.startsWith(UrlProtocol.WEBSOCKET_SECURE)
46-
? MCPTransportType.WEBSOCKET
47-
: MCPTransportType.STREAMABLE_HTTP;
50+
) {
51+
return MCPTransportType.WEBSOCKET;
52+
}
53+
54+
if (
55+
normalized.endsWith(MCP_SSE_ENDPOINT) ||
56+
normalized.endsWith(MCP_SSE_ENDPOINT_SLASH) ||
57+
normalized.includes(MCP_SSE_ENDPOINT_QUERY)
58+
) {
59+
return MCPTransportType.SSE;
60+
}
61+
62+
return MCPTransportType.STREAMABLE_HTTP;
4863
}
4964

5065
/**

0 commit comments

Comments
 (0)