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
This commit is contained in:
Harapan Rachman 2026-06-17 13:26:30 +07:00 committed by GitHub
parent 51571722aa
commit bae36efa30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 82 additions and 5 deletions

View File

@ -84,3 +84,8 @@ export const MCP_TRANSPORT_ICONS: Record<MCPTransportType, Component> = {
[MCPTransportType.STREAMABLE_HTTP]: Globe,
[MCPTransportType.SSE]: Radio
};
/** Standard SSE endpoint path indicators */
export const MCP_SSE_ENDPOINT = '/sse';
export const MCP_SSE_ENDPOINT_SLASH = '/sse/';
export const MCP_SSE_ENDPOINT_QUERY = '/sse?';

View File

@ -16,7 +16,8 @@ import {
DEFAULT_MCP_CONFIG,
DEFAULT_CLIENT_VERSION,
DEFAULT_IMAGE_MIME_TYPE,
MCP_PARTIAL_REDACT_HEADERS
MCP_PARTIAL_REDACT_HEADERS,
CORS_PROXY_ENDPOINT
} from '$lib/constants';
import {
MCPConnectionPhase,
@ -236,6 +237,36 @@ export class MCPService {
return {
fetch: async (input, init) => {
if (useProxy && typeof window !== 'undefined') {
let requestUrlStr = '';
if (typeof input === 'string') {
requestUrlStr = input;
} else if (input instanceof URL) {
requestUrlStr = input.href;
}
if (requestUrlStr) {
const parsedRequestUrl = new URL(requestUrlStr, window.location.origin);
if (
parsedRequestUrl.origin === window.location.origin &&
!parsedRequestUrl.pathname.includes(CORS_PROXY_ENDPOINT)
) {
const originalConfigUrl = new URL(config.url);
const realTargetUrl = new URL(
parsedRequestUrl.pathname + parsedRequestUrl.search,
originalConfigUrl.origin
);
const proxiedUrl = buildProxiedUrl(realTargetUrl.href);
if (typeof input === 'string') {
input = proxiedUrl.href;
} else if (input instanceof URL) {
input = proxiedUrl;
}
}
}
}
const startedAt = performance.now();
const requestHeaders = new Headers(baseInit.headers);
@ -403,6 +434,32 @@ export class MCPService {
};
}
if (config.transport === MCPTransportType.SSE) {
const url = useProxy ? buildProxiedUrl(config.url) : new URL(config.url);
const { fetch: diagnosticFetch, disable: stopPhaseLogging } = this.createDiagnosticFetch(
serverName,
config,
requestInit,
url,
useProxy,
onLog
);
if (import.meta.env.DEV && import.meta.env.VITE_DEBUG) {
console.log(`[MCPService] Creating SSE transport for ${url.href}`);
}
return {
transport: new SSEClientTransport(url, {
requestInit,
fetch: diagnosticFetch,
eventSourceInit: { fetch: diagnosticFetch }
}),
type: MCPTransportType.SSE,
stopPhaseLogging
};
}
const url = useProxy ? buildProxiedUrl(config.url) : new URL(config.url);
const { fetch: diagnosticFetch, disable: stopPhaseLogging } = this.createDiagnosticFetch(
serverName,

View File

@ -19,7 +19,10 @@ import {
DISPLAY_NAME_SEPARATOR_REGEX,
PATH_SEPARATOR,
RESOURCE_TEXT_CONTENT_SEPARATOR,
DEFAULT_RESOURCE_FILENAME
DEFAULT_RESOURCE_FILENAME,
MCP_SSE_ENDPOINT,
MCP_SSE_ENDPOINT_SLASH,
MCP_SSE_ENDPOINT_QUERY
} from '$lib/constants';
import {
Database,
@ -41,10 +44,22 @@ import type { MimeTypeUnion } from '$lib/types/common';
export function detectMcpTransportFromUrl(url: string): MCPTransportType {
const normalized = url.trim().toLowerCase();
return normalized.startsWith(UrlProtocol.WEBSOCKET) ||
if (
normalized.startsWith(UrlProtocol.WEBSOCKET) ||
normalized.startsWith(UrlProtocol.WEBSOCKET_SECURE)
? MCPTransportType.WEBSOCKET
: MCPTransportType.STREAMABLE_HTTP;
) {
return MCPTransportType.WEBSOCKET;
}
if (
normalized.endsWith(MCP_SSE_ENDPOINT) ||
normalized.endsWith(MCP_SSE_ENDPOINT_SLASH) ||
normalized.includes(MCP_SSE_ENDPOINT_QUERY)
) {
return MCPTransportType.SSE;
}
return MCPTransportType.STREAMABLE_HTTP;
}
/**