import { EventEmitter } from "node:events"; import { CallToolRequestParamsSchema, CallToolResult, CallToolResult as CallToolResult$1, CallToolResultSchema, Tool, Tool as Tool$1, ToolAnnotations, ToolAnnotations as ToolAnnotations$1, ToolAnnotationsSchema, ToolSchema } from "@modelcontextprotocol/sdk/types.js"; import { z } from "zod/v4"; import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; //#region src/protocol.d.ts /** * SDK-derived canonical tool schema used internally by the relay. */ declare const NormalizedToolSchema: z.ZodObject<{ description: z.ZodOptional; inputSchema: z.ZodObject<{ type: z.ZodLiteral<"object">; properties: z.ZodOptional>>; required: z.ZodOptional>; }, z.core.$catchall>; outputSchema: z.ZodOptional; properties: z.ZodOptional>>; required: z.ZodOptional>; }, z.core.$catchall>>; annotations: z.ZodOptional; readOnlyHint: z.ZodOptional; destructiveHint: z.ZodOptional; idempotentHint: z.ZodOptional; openWorldHint: z.ZodOptional; }, z.core.$strip>>; execution: z.ZodOptional>; }, z.core.$strip>>; _meta: z.ZodOptional>; icons: z.ZodOptional; sizes: z.ZodOptional>; theme: z.ZodOptional>; }, z.core.$strip>>>; title: z.ZodOptional; name: z.ZodString; }, z.core.$strip>; /** * Permissive inbound tool shape from browser/widget payloads. * * Only enforces a non-empty name at ingest. All other fields are normalized * against SDK schemas by {@link normalizeInboundTool}. */ declare const InboundToolSchema: z.ZodObject<{ name: z.ZodString; }, z.core.$loose>; /** * SDK-derived argument schema for tool invocation payloads. */ declare const RelayInvokeArgsSchema: z.ZodOptional>; /** * Default input schema applied when inbound payload omits or provides * a non-object input schema. */ declare const DEFAULT_TOOL_INPUT_SCHEMA: Tool$1['inputSchema']; /** * Canonical normalized relay tool shape. */ type RelayTool = z.infer; /** * Canonical relay tool annotations shape. */ type RelayToolAnnotations = ToolAnnotations$1; /** * Canonical relay call result shape. */ type RelayCallToolResult = CallToolResult$1; /** * Invocation argument object shape derived from MCP SDK request params. */ type RelayInvokeArgs = Exclude, undefined>; /** * Normalizes permissive inbound tool payloads into SDK-compliant Tool objects. * * Invalid optional metadata (description, output schema, annotations, etc.) * is dropped. Invalid/missing inputSchema falls back to an empty object schema. */ declare function normalizeInboundTool(inbound: z.infer): RelayTool; //#endregion //#region src/schemas.d.ts /** * Schema for source identity bootstrap message. */ declare const BrowserHelloMessageSchema: z.ZodObject<{ type: z.ZodLiteral<"hello">; tabId: z.ZodString; origin: z.ZodOptional; url: z.ZodOptional; title: z.ZodOptional; iconUrl: z.ZodOptional; }, z.core.$strip>; /** * Union schema for all browser-to-relay protocol messages. */ declare const BrowserToRelayMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{ type: z.ZodLiteral<"hello">; tabId: z.ZodString; origin: z.ZodOptional; url: z.ZodOptional; title: z.ZodOptional; iconUrl: z.ZodOptional; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"tools/list">; tools: z.ZodPipe>, z.ZodTransform<{ inputSchema: { [x: string]: unknown; type: "object"; properties?: Record | undefined; required?: string[] | undefined; }; name: string; description?: string | undefined; outputSchema?: { [x: string]: unknown; type: "object"; properties?: Record | undefined; required?: string[] | undefined; } | undefined; annotations?: { title?: string | undefined; readOnlyHint?: boolean | undefined; destructiveHint?: boolean | undefined; idempotentHint?: boolean | undefined; openWorldHint?: boolean | undefined; } | undefined; execution?: { taskSupport?: "optional" | "required" | "forbidden" | undefined; } | undefined; _meta?: Record | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "light" | "dark" | undefined; }[] | undefined; title?: string | undefined; }[], { [x: string]: unknown; name: string; }[]>>; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"tools/changed">; tools: z.ZodPipe>, z.ZodTransform<{ inputSchema: { [x: string]: unknown; type: "object"; properties?: Record | undefined; required?: string[] | undefined; }; name: string; description?: string | undefined; outputSchema?: { [x: string]: unknown; type: "object"; properties?: Record | undefined; required?: string[] | undefined; } | undefined; annotations?: { title?: string | undefined; readOnlyHint?: boolean | undefined; destructiveHint?: boolean | undefined; idempotentHint?: boolean | undefined; openWorldHint?: boolean | undefined; } | undefined; execution?: { taskSupport?: "optional" | "required" | "forbidden" | undefined; } | undefined; _meta?: Record | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "light" | "dark" | undefined; }[] | undefined; title?: string | undefined; }[], { [x: string]: unknown; name: string; }[]>>; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"result">; callId: z.ZodString; result: z.ZodUnknown; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"pong">; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"elicitation-request">; callId: z.ZodString; params: z.ZodRecord; }, z.core.$strip>]>; /** * Browser-to-relay message payload. */ type BrowserToRelayMessage = z.infer; /** * Browser source bootstrap message. */ type BrowserHelloMessage = z.infer; /** * Shared relay identity used for discovery and attach verification. */ declare const RelayDescriptorSchema: z.ZodObject<{ host: z.ZodString; instanceId: z.ZodString; label: z.ZodOptional; port: z.ZodNumber; relayId: z.ZodOptional; workspace: z.ZodOptional; }, z.core.$strip>; /** * Relay identity used for discovery and attach verification. */ type RelayDescriptor = z.infer; /** * Schema for server hello messages sent immediately after WebSocket connect. */ declare const ServerHelloMessageSchema: z.ZodObject<{ host: z.ZodString; instanceId: z.ZodString; label: z.ZodOptional; port: z.ZodNumber; relayId: z.ZodOptional; workspace: z.ZodOptional; type: z.ZodLiteral<"server-hello">; service: z.ZodLiteral<"webmcp-local-relay">; version: z.ZodLiteral<1>; }, z.core.$strip>; /** * Server hello payload. */ type ServerHelloMessage = z.infer; /** * Schema for acceptance of a browser source hello message. */ declare const RelayHelloAcceptedMessageSchema: z.ZodObject<{ type: z.ZodLiteral<"hello/accepted">; }, z.core.$strip>; /** * Acceptance payload for a browser source hello message. */ type RelayHelloAcceptedMessage = z.infer; /** * Schema for rejection of a browser source hello message. */ declare const RelayHelloRejectedMessageSchema: z.ZodObject<{ type: z.ZodLiteral<"hello/rejected">; reason: z.ZodString; message: z.ZodString; }, z.core.$strip>; /** * Rejection payload for a browser source hello message. */ type RelayHelloRejectedMessage = z.infer; /** * Union schema for all relay-to-browser protocol messages. */ declare const RelayToBrowserMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{ host: z.ZodString; instanceId: z.ZodString; label: z.ZodOptional; port: z.ZodNumber; relayId: z.ZodOptional; workspace: z.ZodOptional; type: z.ZodLiteral<"server-hello">; service: z.ZodLiteral<"webmcp-local-relay">; version: z.ZodLiteral<1>; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"hello/accepted">; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"hello/rejected">; reason: z.ZodString; message: z.ZodString; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"invoke">; callId: z.ZodString; toolName: z.ZodString; args: z.ZodOptional>; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"ping">; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"reload">; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"elicitation-response">; callId: z.ZodString; result: z.ZodRecord; }, z.core.$strip>]>; /** * Relay-to-browser message payload. */ type RelayToBrowserMessage = z.infer; /** * Relay-to-relay protocol (client mode <-> server mode). */ /** * Schema for source metadata transmitted in relay-to-relay messages. */ declare const RelaySourceInfoSchema: z.ZodObject<{ sourceId: z.ZodString; tabId: z.ZodString; origin: z.ZodOptional; url: z.ZodOptional; title: z.ZodOptional; iconUrl: z.ZodOptional; connectedAt: z.ZodNumber; lastSeenAt: z.ZodNumber; toolCount: z.ZodNumber; }, z.core.$strip>; /** * Source metadata transmitted in relay-to-relay messages. */ type RelaySourceInfo = z.infer; /** * Union schema for all relay-client-to-server messages. */ declare const RelayClientToServerMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{ type: z.ZodLiteral<"relay/hello">; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"relay/list-tools">; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"relay/invoke">; callId: z.ZodString; toolName: z.ZodString; args: z.ZodOptional>; }, z.core.$strip>]>; /** * Relay client to server message payload. */ type RelayClientToServerMessage = z.infer; /** * Union schema for all relay-server-to-client messages. */ declare const RelayServerToClientMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{ host: z.ZodString; instanceId: z.ZodString; label: z.ZodOptional; port: z.ZodNumber; relayId: z.ZodOptional; workspace: z.ZodOptional; type: z.ZodLiteral<"server-hello">; service: z.ZodLiteral<"webmcp-local-relay">; version: z.ZodLiteral<1>; }, z.core.$strip>, z.ZodObject<{ tools: z.ZodArray; inputSchema: z.ZodObject<{ type: z.ZodLiteral<"object">; properties: z.ZodOptional>>; required: z.ZodOptional>; }, z.core.$catchall>; outputSchema: z.ZodOptional; properties: z.ZodOptional>>; required: z.ZodOptional>; }, z.core.$catchall>>; annotations: z.ZodOptional; readOnlyHint: z.ZodOptional; destructiveHint: z.ZodOptional; idempotentHint: z.ZodOptional; openWorldHint: z.ZodOptional; }, z.core.$strip>>; execution: z.ZodOptional>; }, z.core.$strip>>; _meta: z.ZodOptional>; icons: z.ZodOptional; sizes: z.ZodOptional>; theme: z.ZodOptional>; }, z.core.$strip>>>; title: z.ZodOptional; name: z.ZodString; }, z.core.$strip>>; sources: z.ZodDefault; url: z.ZodOptional; title: z.ZodOptional; iconUrl: z.ZodOptional; connectedAt: z.ZodNumber; lastSeenAt: z.ZodNumber; toolCount: z.ZodNumber; }, z.core.$strip>>>>; toolSourceMap: z.ZodDefault>>>; type: z.ZodLiteral<"relay/tools">; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"relay/result">; callId: z.ZodString; result: z.ZodObject<{ _meta: z.ZodOptional>; "io.modelcontextprotocol/related-task": z.ZodOptional>; }, z.core.$loose>>; content: z.ZodDefault; text: z.ZodString; annotations: z.ZodOptional>>; priority: z.ZodOptional; lastModified: z.ZodOptional; }, z.core.$strip>>; _meta: z.ZodOptional>; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"image">; data: z.ZodString; mimeType: z.ZodString; annotations: z.ZodOptional>>; priority: z.ZodOptional; lastModified: z.ZodOptional; }, z.core.$strip>>; _meta: z.ZodOptional>; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"audio">; data: z.ZodString; mimeType: z.ZodString; annotations: z.ZodOptional>>; priority: z.ZodOptional; lastModified: z.ZodOptional; }, z.core.$strip>>; _meta: z.ZodOptional>; }, z.core.$strip>, z.ZodObject<{ uri: z.ZodString; description: z.ZodOptional; mimeType: z.ZodOptional; annotations: z.ZodOptional>>; priority: z.ZodOptional; lastModified: z.ZodOptional; }, z.core.$strip>>; _meta: z.ZodOptional>; icons: z.ZodOptional; sizes: z.ZodOptional>; theme: z.ZodOptional>; }, z.core.$strip>>>; name: z.ZodString; title: z.ZodOptional; type: z.ZodLiteral<"resource_link">; }, z.core.$strip>, z.ZodObject<{ type: z.ZodLiteral<"resource">; resource: z.ZodUnion; _meta: z.ZodOptional>; text: z.ZodString; }, z.core.$strip>, z.ZodObject<{ uri: z.ZodString; mimeType: z.ZodOptional; _meta: z.ZodOptional>; blob: z.ZodString; }, z.core.$strip>]>; annotations: z.ZodOptional>>; priority: z.ZodOptional; lastModified: z.ZodOptional; }, z.core.$strip>>; _meta: z.ZodOptional>; }, z.core.$strip>]>>>; structuredContent: z.ZodOptional>; isError: z.ZodOptional; }, z.core.$loose>; }, z.core.$strip>, z.ZodObject<{ tools: z.ZodArray; inputSchema: z.ZodObject<{ type: z.ZodLiteral<"object">; properties: z.ZodOptional>>; required: z.ZodOptional>; }, z.core.$catchall>; outputSchema: z.ZodOptional; properties: z.ZodOptional>>; required: z.ZodOptional>; }, z.core.$catchall>>; annotations: z.ZodOptional; readOnlyHint: z.ZodOptional; destructiveHint: z.ZodOptional; idempotentHint: z.ZodOptional; openWorldHint: z.ZodOptional; }, z.core.$strip>>; execution: z.ZodOptional>; }, z.core.$strip>>; _meta: z.ZodOptional>; icons: z.ZodOptional; sizes: z.ZodOptional>; theme: z.ZodOptional>; }, z.core.$strip>>>; title: z.ZodOptional; name: z.ZodString; }, z.core.$strip>>; sources: z.ZodDefault; url: z.ZodOptional; title: z.ZodOptional; iconUrl: z.ZodOptional; connectedAt: z.ZodNumber; lastSeenAt: z.ZodNumber; toolCount: z.ZodNumber; }, z.core.$strip>>>>; toolSourceMap: z.ZodDefault>>>; type: z.ZodLiteral<"relay/tools-changed">; }, z.core.$strip>]>; /** * Relay server to client message payload. */ type RelayServerToClientMessage = z.infer; //#endregion //#region src/registry.d.ts /** * Internal metadata tracked for each active browser source. */ interface SourceMetadata { sourceId: string; tabId: string; origin: string | undefined; url: string | undefined; title: string | undefined; iconUrl: string | undefined; connectedAt: number; lastSeenAt: number; } /** * Public source metadata exposed by registry APIs. */ interface SourceInfo extends SourceMetadata { toolCount: number; } /** * Aggregated relayed tool metadata across one or more sources. * * Extends {@link RelayTool} with relay-specific fields so new SDK tool * properties are automatically inherited without manual duplication. */ interface AggregatedTool extends RelayTool { originalName: string; sources: SourceInfo[]; } /** * Invocation target selected by the registry. */ interface ResolvedInvocation { connectionId: string; tool: RelayTool; publicToolName: string; } /** * Error thrown when a source attempts to register tools before `hello`. */ declare class HelloRequiredError extends Error { readonly connectionId: string; constructor(connectionId: string); } /** * In-memory source and tool registry used by the relay bridge. */ declare class RelayRegistry { private readonly now; private readonly sourceByConnectionId; private readonly toolsByConnectionId; private readonly providersByPublicToolName; /** * @param now Time provider used for recency ordering. */ constructor(now?: () => number); /** * Upserts source metadata from a browser `hello` message. * * `sourceId` currently matches `connectionId`, but remains conceptually distinct * so stable source identity can be introduced in the future. */ upsertSource(connectionId: string, hello: BrowserHelloMessage): void; /** * Replaces the full tool set for a source connection. */ registerTools(connectionId: string, tools: RelayTool[]): void; /** * Removes a source and all of its tool registrations. */ removeConnection(connectionId: string): void; /** * Marks a source as recently seen without mutating identity metadata. */ touchConnection(connectionId: string): void; /** * Lists active sources that currently publish at least one tool. */ listSources(): SourceInfo[]; /** * Lists aggregated tools ordered by public tool name. */ listTools(): AggregatedTool[]; /** * Resolves a tool invocation to a concrete source provider. * * Resolution order: * 1. `sourceId`: exact source id, then fallback to tab id. * 2. `requestTabId`: strict tab id match with no fallback. * 3. Default: most recently seen provider. */ resolveInvocation(options: { toolName: string; sourceId?: string; requestTabId?: string; }): ResolvedInvocation | null; /** * Converts internal source metadata to public source info. */ private toSourceInfo; /** * Removes all tool providers for a connection. */ private removeConnectionTools; /** * Rebuilds public tool names after source set changes. * * When the same original tool name appears in multiple tabs, names are * disambiguated with a short tab suffix. */ private rebuildPublicNames; /** * Returns providers sorted by source recency. */ private sortProvidersByRecency; /** * Compares two source recency tuples and stabilizes order by source id. */ private compareRecency; } //#endregion //#region src/bridgeServer.d.ts /** * Runtime options for {@link RelayBridgeServer}. */ interface RelayBridgeServerOptions { /** * Network interface used by the local WebSocket server. * @defaultValue `"127.0.0.1"` */ host?: string; /** * Preferred WebSocket port for browser widget connections. * @defaultValue `9333` */ port?: number; /** * Whether the preferred port came from an explicit CLI/API override. * Explicit ports fail if occupied by a non-relay process. * @defaultValue `false` */ portExplicitlySet?: boolean; /** * Inclusive upper bound for automatic port discovery. * @defaultValue `9348` */ portRangeEnd?: number; /** * File path used to cache the last successful relay port. * @defaultValue `~/.webmcp/relay-port.json` */ persistPath?: string; /** * Allowed host page origins reported by browser `hello` messages. * Use `["*"]` to allow all origins. * * Permissive by default for zero-config developer experience — any browser * page can connect and register tools without additional setup. For production * or shared machines, restrict to trusted host origins via the * `--widget-origin` CLI flag or by passing explicit origins here. * * @defaultValue `["*"]` */ allowedOrigins?: string[]; /** * Maximum WebSocket payload size in bytes. * @defaultValue `1000000` */ maxPayloadBytes?: number; /** * Timeout used for browser tool invocations. * @defaultValue `25000` */ invokeTimeoutMs?: number; /** * Human-readable relay label reported in discovery handshakes. */ label?: string; /** * Optional workspace name reported in discovery handshakes. */ workspace?: string; /** * Stable relay identifier used to select between multiple relays. */ relayId?: string; } /** * WebSocket relay between browser widget frames and MCP server calls. * * Operates in two modes: * - **server** (default): Runs a WebSocket server, accepts browser and relay * client connections. * - **client** (fallback on EADDRINUSE): Connects as a WebSocket client to an * existing server relay and proxies tool operations through it. */ declare class RelayBridgeServer extends EventEmitter { /** * Registry for connected sources and aggregated tool definitions. * Only actively used in server mode; remains empty when operating as a client. */ readonly registry: RelayRegistry; private readonly host; private readonly preferredPort; private desiredPort; private readonly portExplicitlySet; private readonly portRangeEnd; private readonly persistPath; private readonly allowedOrigins; private readonly maxPayloadBytes; private readonly invokeTimeoutMs; private readonly label; private readonly workspace; private readonly relayId; private readonly instanceId; private wss; private readonly socketByConnectionId; private readonly pendingInvocations; private readonly relayClientConnectionIds; private readonly heartbeatIntervalByConnectionId; private readonly lastPongByConnectionId; private readonly onStateChangedPushRelay; private _mode; private clientSocket; private clientReconnectTimer; private clientReconnectDelay; /** * Maximum delay for relay-to-relay reconnection backoff in client mode. */ private readonly clientMaxReconnectDelay; private readonly clientMaxReconnectAttempts; private clientReconnectAttempts; private readonly clientPendingInvocations; private clientTools; private clientSources; private clientToolSourceMap; private stopping; /** * Creates a relay bridge server instance. */ constructor(options?: RelayBridgeServerOptions, registry?: RelayRegistry); /** * Current operating mode. */ get mode(): 'server' | 'client'; /** * Resolved listening port. In client mode this is the port of the server * relay being proxied through. */ get port(): number; /** * Tools received from the server relay (client mode only). * Returns an empty array in server mode. */ listToolsFromRelay(): RelayTool[]; /** * Source metadata received from the server relay (client mode only). * Returns an empty array in server mode. */ listSourcesFromRelay(): RelaySourceInfo[]; /** * Tool-to-source mapping received from the server relay (client mode only). * Maps public tool names to arrays of source IDs. * Returns an empty record in server mode. */ getToolSourceMapFromRelay(): Record; /** * Starts the bridge. Attempts to bind a WebSocket server (server mode). * If a compatible relay already owns a candidate port, joins it in client mode. * If a non-relay process owns the port, continues searching the reserved range. */ start(): Promise; private startUsingPortStrategy; private isAddressInUseError; private tryAttachToExistingRelay; /** * Stops all relay resources and rejects any pending invocations. */ stop(): Promise; /** * Sends a reload message to a connected browser source. * Only supported in server mode. */ reloadSource(connectionId: string): void; /** * Invokes a tool either locally (server mode) or through the upstream relay * (client mode). */ invokeTool(toolName: string, args: RelayInvokeArgs, options?: { sourceId?: string; requestTabId?: string; }): Promise; private startAsServer; private buildServerHello; private invokeToolLocally; /** * Handles a raw WebSocket message from a connected source. * * Routes relay-protocol messages (`relay/*`) to the relay client handler * and browser-protocol messages to the existing browser handler. */ private onSocketMessage; /** * Sends an elicitation response back to the browser source that requested it. */ sendElicitationResponse(connectionId: string, callId: string, result: Record): void; /** * Handles relay-protocol messages from relay client connections. */ private onRelayClientMessage; /** * Pushes current tool state to all connected relay clients. */ private pushToolsToRelayClients; /** * Handles source disconnection and rejects in-flight calls owned by that source. */ private onSocketClose; private startHeartbeat; private stopHeartbeat; private startAsClient; private connectToRelayServer; private setupClientHandlers; private sendRelayClientHandshake; private parseRelayServerMessage; private processRelayServerMessage; private scheduleReconnect; /** * Attempts to promote from client to server mode when reconnecting. * Re-runs the same attach-or-bind strategy used during startup. */ private reconnectWithModePromotion; private invokeToolViaRelay; /** * Builds the complete relay response payload including tools and source metadata. */ private buildRelayToolsPayload; /** * Maps aggregated tools to the wire format used by the relay protocol. */ private toWireTools; private isHostOriginAllowed; private sendHelloAccepted; private sendHelloRejected; /** * Validates browser tool results against CallToolResultSchema. * Non-conforming payloads are wrapped as error results with diagnostic text. */ private normalizeCallToolResult; /** * Converts WebSocket raw data variants to a UTF-8 string payload. */ private rawDataToUtf8; } //#endregion //#region src/cli-utils.d.ts /** * Parsed CLI options for relay startup. */ interface CliOptions { host: string; port: number; portExplicitlySet: boolean; allowedOrigins: string[]; label?: string; workspace?: string; relayId?: string; } /** * Parses supported CLI flags for relay startup. */ declare function parseCliOptions(argv: string[]): CliOptions; /** * Prints CLI usage to stderr. */ declare function printHelp(): void; //#endregion //#region src/mcpRelayServer.d.ts /** * Base options shared by all {@link LocalRelayMcpServer} configurations. */ interface LocalRelayMcpServerBaseOptions { /** * MCP server name reported during initialization. */ serverName?: string; /** * MCP server version reported during initialization. */ serverVersion?: string; } /** * Construction options for {@link LocalRelayMcpServer}. * * Provide either an existing `bridge` instance OR `bridgeOptions` to create * one internally — not both. */ type LocalRelayMcpServerOptions = LocalRelayMcpServerBaseOptions & ({ bridge: RelayBridgeServer; bridgeOptions?: never; } | { bridge?: never; bridgeOptions?: RelayBridgeServerOptions; }); /** * MCP server facade that exposes browser-relayed tools over MCP transport. */ declare class LocalRelayMcpServer { /** * Underlying WebSocket bridge used for browser communication. */ readonly bridge: RelayBridgeServer; private readonly mcpServer; private readonly staticToolData; private readonly dynamicToolHandles; private readonly dynamicToolData; private readonly dynamicToolSignature; private syncing; private syncRequested; private connected; /** * Creates a local relay MCP server with static and dynamic tool registration. */ constructor(options?: LocalRelayMcpServerOptions); /** * Starts the browser bridge and synchronizes dynamic MCP tools. */ start(): Promise; /** * Connects the MCP server to a transport. * * This may be called exactly once per instance lifecycle. */ connect(transport: Transport): Promise; /** * Convenience helper that connects the server over stdio transport. */ startStdio(): Promise; /** * Stops MCP transport and bridge resources. */ stop(): Promise; /** * Returns dynamic tool names currently registered in MCP. */ listDynamicToolNames(): string[]; /** * Overrides the SDK's ListTools handler to return real JSON Schema * for dynamic tools instead of the empty `z.object({}).passthrough()` * schema that the SDK would otherwise convert to `{ type: 'object' }`. * * The MCP SDK's McpServer internally runs `toJsonSchemaCompat()` on * registered inputSchema values, which strips plain JSON Schema objects * (non-Zod) to empty schemas. This override bypasses that conversion * for dynamic (relayed) tools while preserving static tools as-is. */ private overrideListToolsHandler; private registerStaticTool; /** * Registers built-in management tools exposed by the relay. */ private registerStaticTools; /** * Builds a concise plain-text list of available tools. */ private buildToolSummary; /** * Opens a URL in the user's default browser using the platform open command. * * Uses the re-serialized `URL.href` to prevent injection of shell metacharacters. * On Windows, PowerShell `Start-Process` is used instead of `cmd /c start` * because cmd.exe interprets `&`, `|`, and other metacharacters in URLs. */ private openInBrowser; /** * Coalesces concurrent sync requests into a single serialized sync loop. */ private syncDynamicTools; /** * Returns the current aggregated tool list, dispatching based on bridge mode. */ private listAggregatedTools; /** * Converts relay client tool descriptors to aggregated tool shape. * Populates per-tool source metadata from the relay's tool-source mapping. */ private buildAggregatedToolsFromRelay; /** * Applies registry tool state to MCP dynamic registrations. */ private applyDynamicTools; /** * Registers a single dynamic tool and returns a removal handle. */ private registerDynamicTool; /** * Builds a display description for relayed tools including source context. * In client mode, source metadata is unavailable, so tools are labeled `[WebMCP relay]`. */ private dynamicToolDescription; /** * Produces a stable signature for change detection of dynamic tool metadata. */ private toolSignature; /** * Logs tool sync errors with full detail. */ private logSyncError; } //#endregion //#region src/naming.d.ts /** * Converts arbitrary text into MCP-safe identifier characters. */ declare function sanitizeName(value: string): string; /** * Extracts and sanitizes a domain label from an origin or URL. */ declare function extractSanitizedDomain(originOrUrl?: string): string; /** * Builds a public tool name for MCP registration. * * Names can include a short tab-id suffix when multiple tabs publish the same * original tool name. */ declare function buildPublicToolName(options: { originalToolName: string; tabId?: string; disambiguate?: boolean; }): string; //#endregion export { type AggregatedTool, type BrowserToRelayMessage, BrowserToRelayMessageSchema, CallToolRequestParamsSchema, type CallToolResult, CallToolResultSchema, type CliOptions, DEFAULT_TOOL_INPUT_SCHEMA, HelloRequiredError, InboundToolSchema, LocalRelayMcpServer, type LocalRelayMcpServerOptions, NormalizedToolSchema, RelayBridgeServer, type RelayBridgeServerOptions, type RelayCallToolResult, type RelayClientToServerMessage, RelayClientToServerMessageSchema, type RelayDescriptor, RelayDescriptorSchema, type RelayHelloAcceptedMessage, RelayHelloAcceptedMessageSchema, type RelayHelloRejectedMessage, RelayHelloRejectedMessageSchema, type RelayInvokeArgs, RelayInvokeArgsSchema, RelayRegistry, type RelayServerToClientMessage, RelayServerToClientMessageSchema, type RelaySourceInfo, RelaySourceInfoSchema, type RelayToBrowserMessage, RelayToBrowserMessageSchema, type RelayTool, type RelayToolAnnotations, type ResolvedInvocation, type ServerHelloMessage, ServerHelloMessageSchema, type SourceInfo, type Tool, type ToolAnnotations, ToolAnnotationsSchema, ToolSchema, buildPublicToolName, extractSanitizedDomain, normalizeInboundTool, parseCliOptions, printHelp, sanitizeName }; //# sourceMappingURL=index.d.mts.map