ui: Linting & Formatting scripts (#26819)

This commit is contained in:
Aleksander Grygier
2026-08-10 08:38:37 +02:00
committed by GitHub
parent 1e396e72a8
commit 92d1bb0c99
538 changed files with 8806 additions and 6036 deletions
+135 -121
View File
@@ -1,63 +1,63 @@
import { Client } from '@modelcontextprotocol/sdk/client';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
import {
StreamableHTTPClientTransport,
StreamableHTTPError
} from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
import { WebSocketClientTransport } from '@modelcontextprotocol/sdk/client/websocket.js';
import type {
Tool,
Prompt,
GetPromptResult,
ListChangedHandlers
} from '@modelcontextprotocol/sdk/types.js';
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
import type {
GetPromptResult,
ListChangedHandlers,
Prompt,
Tool
} from '@modelcontextprotocol/sdk/types.js';
import {
DEFAULT_MCP_CONFIG,
CORS_PROXY_ENDPOINT,
CORS_PROXY_HEADER_PREFIX,
DEFAULT_CLIENT_VERSION,
DEFAULT_IMAGE_MIME_TYPE,
CORS_PROXY_HEADER_PREFIX,
MCP_PARTIAL_REDACT_HEADERS,
CORS_PROXY_ENDPOINT
DEFAULT_MCP_CONFIG,
MCP_PARTIAL_REDACT_HEADERS
} from '$lib/constants';
import {
MCPConnectionPhase,
MCPLogLevel,
MCPTransportType,
MCPContentType,
MCPRefType
MCPLogLevel,
MCPRefType,
MCPTransportType
} from '$lib/enums';
import type {
MCPServerConfig,
MCPResourceIcon,
ToolCallParams,
ToolExecutionResult,
Implementation,
ClientCapabilities,
Implementation,
MCPConnection,
MCPPhaseCallback,
MCPConnectionLog,
MCPServerInfo,
MCPPhaseCallback,
MCPReadResourceResult,
MCPResource,
MCPResourceTemplate,
MCPResourceContent,
MCPReadResourceResult
MCPResourceIcon,
MCPResourceTemplate,
MCPServerConfig,
MCPServerInfo,
ToolCallParams,
ToolExecutionResult
} from '$lib/types';
import {
buildProxiedUrl,
buildProxiedHeaders,
getAuthHeaders,
sanitizeHeaders,
throwIfAborted,
isAbortError,
buildProxiedUrl,
createBase64DataUrl,
getRequestUrl,
getRequestMethod,
getRequestBody,
summarizeRequestBody,
formatDiagnosticErrorMessage,
extractJsonRpcMethods,
type RequestBodySummary
formatDiagnosticErrorMessage,
getAuthHeaders,
getRequestBody,
getRequestMethod,
getRequestUrl,
isAbortError,
type RequestBodySummary,
sanitizeHeaders,
summarizeRequestBody,
throwIfAborted
} from '$lib/utils';
interface ToolResultContentItem {
@@ -101,11 +101,11 @@ export class MCPService {
details?: unknown
): MCPConnectionLog {
return {
timestamp: new Date(),
phase,
message,
details,
level,
details
message,
phase,
timestamp: new Date()
};
}
@@ -118,12 +118,12 @@ export class MCPService {
): DiagnosticRequestDetails {
const body = getRequestBody(input, init);
const details: DiagnosticRequestDetails = {
url: getRequestUrl(input),
method: getRequestMethod(input, init, baseInit).toUpperCase(),
body: summarizeRequestBody(body),
credentials: init?.credentials ?? baseInit.credentials,
mode: init?.mode ?? baseInit.mode,
headers: sanitizeHeaders(requestHeaders, extraRedactedHeaders, MCP_PARTIAL_REDACT_HEADERS),
body: summarizeRequestBody(body)
method: getRequestMethod(input, init, baseInit).toUpperCase(),
mode: init?.mode ?? baseInit.mode,
url: getRequestUrl(input)
};
const jsonRpcMethods = extractJsonRpcMethods(body);
@@ -144,6 +144,7 @@ export class MCPService {
useProxy && !key.toLowerCase().startsWith(CORS_PROXY_HEADER_PREFIX)
? `${CORS_PROXY_HEADER_PREFIX}${key}`
: key;
requestHeaders.set(proxiedKey, value);
}
}
@@ -151,12 +152,12 @@ export class MCPService {
private static summarizeError(error: unknown): Record<string, unknown> {
if (error instanceof Error) {
return {
name: error.name,
message: error.message,
cause:
error.cause instanceof Error
? { name: error.cause.name, message: error.cause.message }
? { message: error.cause.message, name: error.cause.name }
: error.cause,
message: error.message,
name: error.name,
stack: error.stack?.split('\n').slice(0, 6).join('\n')
};
}
@@ -173,13 +174,13 @@ export class MCPService {
}
return {
isSecureContext: window.isSecureContext,
location: window.location.href,
origin: window.location.origin,
protocol: window.location.protocol,
isSecureContext: window.isSecureContext,
sameOrigin: window.location.origin === targetUrl.origin,
targetOrigin: targetUrl.origin,
targetProtocol: targetUrl.protocol,
sameOrigin: window.location.origin === targetUrl.origin,
useProxy
};
}
@@ -244,6 +245,7 @@ export class MCPService {
disable: () => void;
} {
let enabled = true;
const logIfEnabled = (log: MCPConnectionLog) => {
if (enabled) {
onLog?.(log);
@@ -251,9 +253,13 @@ export class MCPService {
};
return {
disable: () => {
enabled = false;
},
fetch: async (input, init) => {
if (useProxy && typeof window !== 'undefined') {
let requestUrlStr = '';
if (typeof input === 'string') {
requestUrlStr = input;
} else if (input instanceof URL) {
@@ -262,6 +268,7 @@ export class MCPService {
if (requestUrlStr) {
const parsedRequestUrl = new URL(requestUrlStr, window.location.origin);
if (
parsedRequestUrl.origin === window.location.origin &&
!parsedRequestUrl.pathname.includes(CORS_PROXY_ENDPOINT)
@@ -308,8 +315,8 @@ export class MCPService {
`HTTP ${method} ${url}`,
MCPLogLevel.INFO,
{
serverName,
request
request,
serverName
}
)
);
@@ -324,11 +331,11 @@ export class MCPService {
MCPLogLevel.INFO,
{
response: {
url,
durationMs: 0,
isFake: true,
status: response.status,
statusText: response.statusText,
durationMs: 0,
isFake: true
url
}
}
)
@@ -353,11 +360,11 @@ export class MCPService {
response.ok ? MCPLogLevel.INFO : MCPLogLevel.WARN,
{
response: {
url,
durationMs,
headers: sanitizeHeaders(response.headers, undefined, MCP_PARTIAL_REDACT_HEADERS),
status: response.status,
statusText: response.statusText,
headers: sanitizeHeaders(response.headers, undefined, MCP_PARTIAL_REDACT_HEADERS),
durationMs
url
}
}
)
@@ -373,21 +380,18 @@ export class MCPService {
`HTTP ${method} ${url} failed: ${formatDiagnosticErrorMessage(error)}`,
MCPLogLevel.ERROR,
{
serverName,
request,
error: this.summarizeError(error),
browser: this.getBrowserContext(targetUrl, useProxy),
durationMs,
error: this.summarizeError(error),
hints: this.getConnectionHints(targetUrl, config, error),
durationMs
request,
serverName
}
)
);
throw error;
}
},
disable: () => {
enabled = false;
}
};
}
@@ -463,15 +467,15 @@ export class MCPService {
}
return {
stopPhaseLogging: () => {},
transport: new WebSocketClientTransport(url),
type: MCPTransportType.WEBSOCKET,
stopPhaseLogging: () => {}
type: MCPTransportType.WEBSOCKET
};
}
if (config.transport === MCPTransportType.SSE) {
const url = useProxy ? buildProxiedUrl(config.url) : new URL(config.url);
const { fetch: diagnosticFetch, disable: stopPhaseLogging } = this.createDiagnosticFetch(
const { disable: stopPhaseLogging, fetch: diagnosticFetch } = this.createDiagnosticFetch(
serverName,
config,
requestInit,
@@ -485,18 +489,18 @@ export class MCPService {
}
return {
stopPhaseLogging,
transport: new SSEClientTransport(url, {
requestInit,
eventSourceInit: { fetch: diagnosticFetch },
fetch: diagnosticFetch,
eventSourceInit: { fetch: diagnosticFetch }
requestInit
}),
type: MCPTransportType.SSE,
stopPhaseLogging
type: MCPTransportType.SSE
};
}
const url = useProxy ? buildProxiedUrl(config.url) : new URL(config.url);
const { fetch: diagnosticFetch, disable: stopPhaseLogging } = this.createDiagnosticFetch(
const { disable: stopPhaseLogging, fetch: diagnosticFetch } = this.createDiagnosticFetch(
serverName,
config,
requestInit,
@@ -515,25 +519,25 @@ export class MCPService {
}
return {
stopPhaseLogging,
transport: new StreamableHTTPClientTransport(url, {
requestInit,
fetch: diagnosticFetch
fetch: diagnosticFetch,
requestInit
}),
type: MCPTransportType.STREAMABLE_HTTP,
stopPhaseLogging
type: MCPTransportType.STREAMABLE_HTTP
};
} catch (httpError) {
console.warn(`[MCPService] StreamableHTTP failed, trying SSE transport...`, httpError);
try {
return {
stopPhaseLogging,
transport: new SSEClientTransport(url, {
requestInit,
eventSourceInit: { fetch: diagnosticFetch },
fetch: diagnosticFetch,
eventSourceInit: { fetch: diagnosticFetch }
requestInit
}),
type: MCPTransportType.SSE,
stopPhaseLogging
type: MCPTransportType.SSE
};
} catch (sseError) {
const httpMsg = httpError instanceof Error ? httpError.message : String(httpError);
@@ -557,17 +561,17 @@ export class MCPService {
}
return {
name: impl.name,
version: impl.version,
title: impl.title,
description: impl.description,
websiteUrl: impl.websiteUrl,
icons: impl.icons?.map((icon: MCPResourceIcon) => ({
src: icon.src,
mimeType: icon.mimeType,
sizes: icon.sizes,
src: icon.src,
theme: icon.theme
}))
})),
name: impl.name,
title: impl.title,
version: impl.version,
websiteUrl: impl.websiteUrl
};
}
@@ -617,9 +621,9 @@ export class MCPService {
}
const {
stopPhaseLogging,
transport,
type: transportType,
stopPhaseLogging
type: transportType
} = this.createTransport(serverName, serverConfig, (log) => onPhase?.(log.phase, log));
// Setup WebSocket reconnection handler
@@ -650,7 +654,6 @@ export class MCPService {
listChanged: listChangedHandlers
}
);
const runtimeErrorHandler = (error: Error) => {
// the SDK reports any post initialize error here, including the abort we trigger
// ourselves on the next health check cycle, on tab unload, or on server teardown.
@@ -661,7 +664,9 @@ export class MCPService {
if (isAbortError(error)) {
return;
}
const msg = error?.message ?? '';
if (
/SSE stream disconnected:.*AbortError/i.test(msg) ||
/AbortError: .*aborted/i.test(msg) ||
@@ -669,6 +674,7 @@ export class MCPService {
) {
return;
}
console.error(`[MCPService][${serverName}] Protocol error after initialize:`, error);
};
@@ -701,6 +707,7 @@ export class MCPService {
try {
let handshakeTimer: ReturnType<typeof setTimeout> | undefined;
const handshakeDeadline = new Promise<never>((_, reject) => {
handshakeTimer = setTimeout(() => {
void transport.close().catch(() => {});
@@ -736,21 +743,21 @@ export class MCPService {
}`,
MCPLogLevel.ERROR,
{
error: this.summarizeError(error),
browser: this.getBrowserContext(url, serverConfig.useProxy ?? false),
config: {
serverName,
configuredUrl: serverConfig.url,
credentials: serverConfig.credentials,
effectiveUrl: url.href,
transportType,
useProxy: serverConfig.useProxy ?? false,
headers: sanitizeHeaders(
serverConfig.headers,
Object.keys(serverConfig.headers ?? {}),
MCP_PARTIAL_REDACT_HEADERS
),
credentials: serverConfig.credentials
serverName,
transportType,
useProxy: serverConfig.useProxy ?? false
},
browser: this.getBrowserContext(url, serverConfig.useProxy ?? false),
error: this.summarizeError(error),
hints: this.getConnectionHints(url, serverConfig, error)
}
)
@@ -777,10 +784,10 @@ export class MCPService {
}
),
{
serverInfo,
serverCapabilities,
clientCapabilities: effectiveCapabilities,
instructions
instructions,
serverCapabilities,
serverInfo
}
);
@@ -796,15 +803,14 @@ export class MCPService {
const tools = await this.listTools({
client,
transport,
tools: [],
serverName,
transportType,
connectionTimeMs: 0,
requestTimeoutMs:
serverConfig.requestTimeoutMs ?? DEFAULT_MCP_CONFIG.requestTimeoutSeconds * 1000
serverConfig.requestTimeoutMs ?? DEFAULT_MCP_CONFIG.requestTimeoutSeconds * 1000,
serverName,
tools: [],
transport,
transportType
});
const connectionTimeMs = Math.round(performance.now() - startTime);
// Phase: Connected
@@ -815,6 +821,7 @@ export class MCPService {
`Connection established with ${tools.length} tools (${connectionTimeMs}ms)`
)
);
if (import.meta.env.DEV && import.meta.env.VITE_DEBUG) {
console.log(
`[MCPService][${serverName}] Initialization complete with ${tools.length} tools in ${connectionTimeMs}ms`
@@ -823,18 +830,18 @@ export class MCPService {
return {
client,
transport,
tools,
serverName,
transportType,
serverInfo,
serverCapabilities,
clientCapabilities: effectiveCapabilities,
protocolVersion: DEFAULT_MCP_CONFIG.protocolVersion,
instructions,
connectionTimeMs,
instructions,
protocolVersion: DEFAULT_MCP_CONFIG.protocolVersion,
requestTimeoutMs:
serverConfig.requestTimeoutMs ?? DEFAULT_MCP_CONFIG.requestTimeoutSeconds * 1000
serverConfig.requestTimeoutMs ?? DEFAULT_MCP_CONFIG.requestTimeoutSeconds * 1000,
serverCapabilities,
serverInfo,
serverName,
tools,
transport,
transportType
};
}
@@ -861,6 +868,7 @@ export class MCPService {
// by not setting onerror, but since we use it for protocol logging,
// we must clear it before disconnect.
connection.client.onerror = undefined;
if (connection.transport.onclose) {
connection.transport.onclose = undefined;
}
@@ -936,7 +944,7 @@ export class MCPService {
args?: Record<string, string>
): Promise<GetPromptResult> {
try {
return await connection.client.getPrompt({ name, arguments: args });
return await connection.client.getPrompt({ arguments: args, name });
} catch (error) {
console.error(`[MCPService][${connection.serverName}] Failed to get prompt:`, error);
@@ -964,7 +972,7 @@ export class MCPService {
try {
const result = await connection.client.callTool(
{ name: params.name, arguments: params.arguments },
{ arguments: params.arguments, name: params.name },
undefined,
{ signal, timeout: connection.requestTimeoutMs }
);
@@ -1001,6 +1009,7 @@ export class MCPService {
*/
private static formatToolResult(result: ToolCallResult): string {
const content = result.content;
if (!Array.isArray(content)) return '';
return content
@@ -1022,6 +1031,7 @@ export class MCPService {
const resource = content.resource;
if (resource.text) return resource.text;
if (resource.blob) return resource.blob;
return JSON.stringify(resource);
@@ -1058,8 +1068,8 @@ export class MCPService {
): Promise<{ values: string[]; total?: number; hasMore?: boolean } | null> {
try {
const result = await connection.client.complete({
ref,
argument
argument,
ref
});
return result.completion;
@@ -1092,8 +1102,8 @@ export class MCPService {
const result = await connection.client.listResources(cursor ? { cursor } : undefined);
return {
resources: (result.resources ?? []) as MCPResource[],
nextCursor: result.nextCursor
nextCursor: result.nextCursor,
resources: (result.resources ?? []) as MCPResource[]
};
} catch (error) {
if (this.isSessionExpiredError(error)) {
@@ -1113,10 +1123,12 @@ export class MCPService {
*/
static async listAllResources(connection: MCPConnection): Promise<MCPResource[]> {
const allResources: MCPResource[] = [];
let cursor: string | undefined;
do {
const result = await this.listResources(connection, cursor);
allResources.push(...result.resources);
cursor = result.nextCursor;
} while (cursor);
@@ -1138,8 +1150,8 @@ export class MCPService {
const result = await connection.client.listResourceTemplates(cursor ? { cursor } : undefined);
return {
resourceTemplates: (result.resourceTemplates ?? []) as MCPResourceTemplate[],
nextCursor: result.nextCursor
nextCursor: result.nextCursor,
resourceTemplates: (result.resourceTemplates ?? []) as MCPResourceTemplate[]
};
} catch (error) {
if (this.isSessionExpiredError(error)) {
@@ -1162,10 +1174,12 @@ export class MCPService {
*/
static async listAllResourceTemplates(connection: MCPConnection): Promise<MCPResourceTemplate[]> {
const allTemplates: MCPResourceTemplate[] = [];
let cursor: string | undefined;
do {
const result = await this.listResourceTemplates(connection, cursor);
allTemplates.push(...result.resourceTemplates);
cursor = result.nextCursor;
} while (cursor);
@@ -1187,8 +1201,8 @@ export class MCPService {
const result = await connection.client.readResource({ uri });
return {
contents: (result.contents ?? []) as MCPResourceContent[],
_meta: result._meta
_meta: result._meta,
contents: (result.contents ?? []) as MCPResourceContent[]
};
} catch (error) {
console.error(`[MCPService][${connection.serverName}] Failed to read resource:`, error);