{"version":3,"file":"mcpRelayServer-DfGkigG5.mjs","names":[],"sources":["../src/portStrategy.ts","../src/protocol.ts","../src/naming.ts","../src/registry.ts","../src/schemas.ts","../src/bridgeServer.ts","../src/cli-utils.ts","../src/mcpRelayServer.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\nexport const DEFAULT_RELAY_PORT = 9333;\nexport const DEFAULT_RELAY_PORT_RANGE_END = 9348;\nconst RELAY_PORT_CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1000;\n\ninterface PersistedRelayPort {\n  host: string;\n  port: number;\n  updatedAt: string;\n}\n\nexport interface PortStrategyOptions {\n  fixedPort?: number;\n  defaultPort: number;\n  rangeEnd: number;\n  host: string;\n  persistPath?: string;\n}\n\nexport interface PortStrategyResult {\n  port: number;\n  wasFixed: boolean;\n  fromCache: boolean;\n}\n\nexport function defaultRelayPortPersistPath(): string {\n  return join(homedir(), '.webmcp', 'relay-port.json');\n}\n\nexport async function persistPort(\n  port: number,\n  path = defaultRelayPortPersistPath(),\n  host = '127.0.0.1',\n  now = Date.now()\n): Promise<void> {\n  const payload: PersistedRelayPort = {\n    port,\n    host,\n    updatedAt: new Date(now).toISOString(),\n  };\n\n  await mkdir(dirname(path), { recursive: true });\n  await writeFile(path, `${JSON.stringify(payload, null, 2)}\\n`, 'utf8');\n}\n\nasync function readPersistedPort(\n  path = defaultRelayPortPersistPath(),\n  options: {\n    expectedHost?: string;\n    maxAgeMs?: number;\n    now?: number;\n  } = {}\n): Promise<number | null> {\n  try {\n    const raw = await readFile(path, 'utf8');\n    const parsed = JSON.parse(raw) as Partial<PersistedRelayPort>;\n    if (\n      typeof parsed.port !== 'number' ||\n      !Number.isInteger(parsed.port) ||\n      parsed.port < 1 ||\n      parsed.port > 65535\n    ) {\n      return null;\n    }\n    if (typeof parsed.host !== 'string' || parsed.host.length === 0) {\n      return null;\n    }\n    if (options.expectedHost && parsed.host !== options.expectedHost) {\n      return null;\n    }\n\n    const maxAgeMs = options.maxAgeMs ?? RELAY_PORT_CACHE_MAX_AGE_MS;\n    const now = options.now ?? Date.now();\n    const updatedAtMs =\n      typeof parsed.updatedAt === 'string' ? Date.parse(parsed.updatedAt) : Number.NaN;\n\n    if (!Number.isFinite(updatedAtMs) || now - updatedAtMs > maxAgeMs) {\n      return null;\n    }\n\n    return parsed.port;\n  } catch {\n    return null;\n  }\n}\n\nexport async function buildPortCandidates(\n  options: PortStrategyOptions\n): Promise<PortStrategyResult[]> {\n  const {\n    defaultPort,\n    fixedPort,\n    host,\n    persistPath = defaultRelayPortPersistPath(),\n    rangeEnd,\n  } = options;\n\n  if (fixedPort !== undefined) {\n    return [{ port: fixedPort, wasFixed: true, fromCache: false }];\n  }\n\n  const cachedPort = await readPersistedPort(persistPath, { expectedHost: host });\n  const seen = new Set<number>();\n  const candidates: PortStrategyResult[] = [];\n\n  const pushCandidate = (port: number, fromCache: boolean): void => {\n    if (port < 1 || port > 65535 || seen.has(port)) {\n      return;\n    }\n    seen.add(port);\n    candidates.push({ port, wasFixed: false, fromCache });\n  };\n\n  if (cachedPort !== null && cachedPort >= defaultPort && cachedPort <= rangeEnd) {\n    pushCandidate(cachedPort, true);\n  }\n\n  pushCandidate(defaultPort, false);\n\n  for (let port = defaultPort + 1; port <= rangeEnd; port += 1) {\n    pushCandidate(port, false);\n  }\n\n  return candidates;\n}\n","import type { CallToolResult, Tool, ToolAnnotations } from '@modelcontextprotocol/server';\nimport {\n  CallToolRequestParamsSchema,\n  CallToolResultSchema,\n  ToolAnnotationsSchema,\n  ToolSchema,\n} from '@modelcontextprotocol/core';\nimport { z } from 'zod/v4';\n\n/**\n * SDK-derived canonical tool schema used internally by the relay.\n */\nexport const NormalizedToolSchema = ToolSchema.extend({\n  name: ToolSchema.shape.name.min(1),\n});\n\n/**\n * SDK-derived argument schema for tool invocation payloads.\n */\nexport const RelayInvokeArgsSchema = CallToolRequestParamsSchema.shape.arguments;\n\n/**\n * Default input schema applied when inbound payload omits or provides\n * a non-object input schema.\n */\nexport const DEFAULT_TOOL_INPUT_SCHEMA: Tool['inputSchema'] = {\n  type: 'object',\n  properties: {},\n};\n\n/** SDK tool schema with a browser-compatible default input schema. */\nexport const InboundToolSchema = NormalizedToolSchema.extend({\n  inputSchema: NormalizedToolSchema.shape.inputSchema.optional(),\n});\n\n/**\n * Canonical normalized relay tool shape.\n */\nexport type RelayTool = z.infer<typeof NormalizedToolSchema>;\n\n/**\n * Canonical relay tool annotations shape.\n */\nexport type RelayToolAnnotations = ToolAnnotations;\n\n/**\n * Canonical relay call result shape.\n */\nexport type RelayCallToolResult = CallToolResult;\n\n/**\n * Invocation argument object shape derived from MCP SDK request params.\n */\nexport type RelayInvokeArgs = Exclude<z.infer<typeof RelayInvokeArgsSchema>, undefined>;\n\n/**\n * Applies the browser default input schema and validates the complete SDK tool.\n */\nexport function normalizeInboundTool(inbound: z.infer<typeof InboundToolSchema>): RelayTool {\n  return NormalizedToolSchema.parse({\n    ...inbound,\n    inputSchema: inbound.inputSchema ?? DEFAULT_TOOL_INPUT_SCHEMA,\n  });\n}\n\nexport { CallToolRequestParamsSchema, CallToolResultSchema, ToolAnnotationsSchema, ToolSchema };\n","/**\n * Maximum tool name length supported across MCP clients.\n */\nexport const MAX_MCP_TOOL_NAME_LENGTH = 128;\n\n/**\n * Number of tab-id characters appended when disambiguation is required.\n */\nconst TAB_ID_DISAMBIGUATION_LENGTH = 4;\n\n/**\n * Converts arbitrary text into MCP-safe identifier characters.\n */\nexport function sanitizeName(value: string): string {\n  return value.replace(/[^a-zA-Z0-9_]/g, '_');\n}\n\n/**\n * Extracts and sanitizes a domain label from an origin or URL.\n */\nexport function extractSanitizedDomain(originOrUrl?: string): string {\n  if (!originOrUrl) {\n    return 'unknown';\n  }\n\n  try {\n    const parsed = new URL(originOrUrl);\n    if (!parsed.hostname) {\n      return 'unknown';\n    }\n\n    const isLocalhost =\n      parsed.hostname === 'localhost' ||\n      parsed.hostname === '127.0.0.1' ||\n      parsed.hostname === '[::1]';\n\n    const domain = isLocalhost ? `localhost_${parsed.port || '80'}` : parsed.hostname;\n    return sanitizeName(domain);\n  } catch {\n    return 'unknown';\n  }\n}\n\n/**\n * Builds a public tool name for MCP registration.\n *\n * Names can include a short tab-id suffix when multiple tabs publish the same\n * original tool name.\n */\nexport function buildPublicToolName(options: {\n  originalToolName: string;\n  tabId?: string;\n  disambiguate?: boolean;\n}): string {\n  const safeName = sanitizeName(options.originalToolName);\n\n  if (!options.disambiguate || !options.tabId) {\n    return safeName.slice(0, MAX_MCP_TOOL_NAME_LENGTH);\n  }\n\n  const shortTab = sanitizeName(options.tabId).slice(0, TAB_ID_DISAMBIGUATION_LENGTH);\n  const suffix = `_${shortTab}`;\n  const available = MAX_MCP_TOOL_NAME_LENGTH - suffix.length;\n  return `${safeName.slice(0, available)}${suffix}`;\n}\n","import { buildPublicToolName, MAX_MCP_TOOL_NAME_LENGTH } from './naming.js';\nimport type { RelayTool } from './protocol.js';\nimport type { BrowserHelloMessage } from './schemas.js';\n\n/**\n * Internal metadata tracked for each active browser source.\n */\ninterface SourceMetadata {\n  sourceId: string;\n  tabId: string;\n  // Optional keys, matching the wire shape in RelaySourceInfoSchema: a browser\n  // source may omit these entirely rather than send them as undefined.\n  origin?: string | undefined;\n  url?: string | undefined;\n  title?: string | undefined;\n  iconUrl?: string | undefined;\n  connectedAt: number;\n  lastSeenAt: number;\n}\n\n/**\n * Public source metadata exposed by registry APIs.\n */\nexport interface SourceInfo extends SourceMetadata {\n  toolCount: number;\n}\n\n/**\n * Aggregated relayed tool metadata across one or more sources.\n *\n * Extends {@link RelayTool} with relay-specific fields so new SDK tool\n * properties are automatically inherited without manual duplication.\n */\nexport interface AggregatedTool extends RelayTool {\n  originalName: string;\n  sources: SourceInfo[];\n}\n\n/**\n * Internal record linking a source to a concrete tool implementation.\n */\ninterface ToolProvider {\n  sourceId: string;\n  tabId: string;\n  tool: RelayTool;\n  publicToolName: string;\n}\n\n/**\n * Invocation target selected by the registry.\n */\nexport interface ResolvedInvocation {\n  connectionId: string;\n  tool: RelayTool;\n  publicToolName: string;\n}\n\n/**\n * Error thrown when a source attempts to register tools before `hello`.\n */\nexport class HelloRequiredError extends Error {\n  readonly connectionId: string;\n\n  constructor(connectionId: string) {\n    super(`Connection ${connectionId} must send hello before tools`);\n    this.name = 'HelloRequiredError';\n    this.connectionId = connectionId;\n  }\n}\n\n/**\n * In-memory source and tool registry used by the relay bridge.\n */\nexport class RelayRegistry {\n  private readonly sourceByConnectionId = new Map<string, SourceMetadata>();\n  private readonly toolsByConnectionId = new Map<string, ToolProvider[]>();\n  private readonly providersByPublicToolName = new Map<string, ToolProvider[]>();\n\n  /**\n   * @param now Time provider used for recency ordering.\n   */\n  constructor(private readonly now: () => number = () => Date.now()) {}\n\n  /**\n   * Upserts source metadata from a browser `hello` message.\n   *\n   * `sourceId` currently matches `connectionId`, but remains conceptually distinct\n   * so stable source identity can be introduced in the future.\n   */\n  upsertSource(connectionId: string, hello: BrowserHelloMessage): void {\n    const now = this.now();\n    const existing = this.sourceByConnectionId.get(connectionId);\n\n    this.sourceByConnectionId.set(connectionId, {\n      sourceId: connectionId,\n      tabId: hello.tabId,\n      origin: hello.origin ?? existing?.origin,\n      url: hello.url ?? existing?.url,\n      title: hello.title ?? existing?.title,\n      iconUrl: hello.iconUrl ?? existing?.iconUrl,\n      connectedAt: existing?.connectedAt ?? now,\n      lastSeenAt: now,\n    });\n\n    if (existing && existing.tabId !== hello.tabId) {\n      for (const provider of this.toolsByConnectionId.get(connectionId) ?? []) {\n        provider.tabId = hello.tabId;\n      }\n      this.rebuildPublicNames();\n    }\n  }\n\n  /**\n   * Replaces the full tool set for a source connection.\n   */\n  registerTools(connectionId: string, tools: RelayTool[]): void {\n    const source = this.sourceByConnectionId.get(connectionId);\n    if (!source) {\n      throw new HelloRequiredError(connectionId);\n    }\n\n    this.touchConnection(connectionId);\n\n    const providers: ToolProvider[] = tools.map((tool) => ({\n      sourceId: connectionId,\n      tabId: source.tabId,\n      tool,\n      publicToolName: '',\n    }));\n\n    this.toolsByConnectionId.set(connectionId, providers);\n    this.rebuildPublicNames();\n  }\n\n  /**\n   * Removes a source and all of its tool registrations.\n   */\n  removeConnection(connectionId: string): void {\n    this.toolsByConnectionId.delete(connectionId);\n    this.sourceByConnectionId.delete(connectionId);\n    this.rebuildPublicNames();\n  }\n\n  /**\n   * Marks a source as recently seen without mutating identity metadata.\n   */\n  touchConnection(connectionId: string): void {\n    const source = this.sourceByConnectionId.get(connectionId);\n    if (!source) {\n      return;\n    }\n\n    source.lastSeenAt = this.now();\n  }\n\n  /**\n   * Lists active sources that currently publish at least one tool.\n   */\n  listSources(): SourceInfo[] {\n    return Array.from(this.sourceByConnectionId.values())\n      .map((source) => this.toSourceInfo(source))\n      .filter((source) => source.toolCount > 0)\n      .sort((a, b) => this.compareRecency(b.lastSeenAt, a.lastSeenAt, b.sourceId, a.sourceId));\n  }\n\n  /**\n   * Lists aggregated tools ordered by public tool name.\n   */\n  listTools(): AggregatedTool[] {\n    const result: AggregatedTool[] = [];\n\n    for (const [publicToolName, providers] of this.providersByPublicToolName.entries()) {\n      const rankedProviders = this.sortProvidersByRecency(providers);\n      const primaryProvider = rankedProviders[0];\n      if (!primaryProvider) {\n        continue;\n      }\n\n      const sources = rankedProviders\n        .map((provider) => {\n          const source = this.sourceByConnectionId.get(provider.sourceId);\n          return source ? this.toSourceInfo(source) : undefined;\n        })\n        .filter((source): source is SourceInfo => Boolean(source));\n\n      result.push({\n        ...primaryProvider.tool,\n        name: publicToolName,\n        originalName: primaryProvider.tool.name,\n        sources,\n      });\n    }\n\n    return result.sort((a, b) => a.name.localeCompare(b.name));\n  }\n\n  /**\n   * Resolves a tool invocation to a concrete source provider.\n   *\n   * Resolution order:\n   * 1. `sourceId`: exact source id, then fallback to tab id.\n   * 2. `requestTabId`: strict tab id match with no fallback.\n   * 3. Default: most recently seen provider.\n   */\n  resolveInvocation(options: {\n    toolName: string;\n    sourceId?: string;\n    requestTabId?: string;\n  }): ResolvedInvocation | null {\n    const providers = this.providersByPublicToolName.get(options.toolName);\n    if (!providers || providers.length === 0) {\n      return null;\n    }\n\n    const rankedProviders = this.sortProvidersByRecency(providers);\n\n    let provider: ToolProvider | undefined;\n    if (options.sourceId) {\n      provider =\n        rankedProviders.find((candidate) => candidate.sourceId === options.sourceId) ??\n        rankedProviders.find((candidate) => candidate.tabId === options.sourceId);\n    } else if (options.requestTabId) {\n      provider = rankedProviders.find((candidate) => candidate.tabId === options.requestTabId);\n    } else {\n      provider = rankedProviders[0];\n    }\n\n    if (!provider) {\n      return null;\n    }\n\n    return {\n      connectionId: provider.sourceId,\n      tool: provider.tool,\n      publicToolName: provider.publicToolName,\n    };\n  }\n\n  /**\n   * Converts internal source metadata to public source info.\n   */\n  private toSourceInfo(source: SourceMetadata): SourceInfo {\n    return {\n      ...source,\n      toolCount: this.toolsByConnectionId.get(source.sourceId)?.length ?? 0,\n    };\n  }\n\n  /**\n   * Rebuilds public tool names after source set changes.\n   *\n   * When the same original tool name appears in multiple tabs, names are\n   * disambiguated with a short tab suffix.\n   */\n  private rebuildPublicNames(): void {\n    const byOriginalName = new Map<string, ToolProvider[]>();\n    for (const providers of this.toolsByConnectionId.values()) {\n      for (const provider of providers) {\n        const key = provider.tool.name;\n        const group = byOriginalName.get(key) ?? [];\n        group.push(provider);\n        byOriginalName.set(key, group);\n      }\n    }\n\n    this.providersByPublicToolName.clear();\n    const allocations: Array<{ candidate: string; key: string; provider: ToolProvider }> = [];\n\n    for (const [originalName, providers] of byOriginalName) {\n      const uniqueTabIds = new Set(providers.map((p) => p.tabId));\n      const disambiguate = uniqueTabIds.size > 1;\n\n      for (const provider of providers) {\n        allocations.push({\n          candidate: buildPublicToolName({\n            originalToolName: originalName,\n            tabId: provider.tabId,\n            disambiguate,\n          }),\n          key: disambiguate ? `${originalName}\\0${provider.tabId}` : originalName,\n          provider,\n        });\n      }\n    }\n\n    const nameByKey = new Map<string, string>();\n    const usedNames = new Set<string>();\n    for (const { candidate, key, provider } of allocations.sort((a, b) =>\n      a.key < b.key ? -1 : a.key > b.key ? 1 : 0\n    )) {\n      let publicToolName = nameByKey.get(key);\n      if (!publicToolName) {\n        publicToolName = candidate;\n        for (let index = 2; usedNames.has(publicToolName); index += 1) {\n          const suffix = `_${String(index)}`;\n          publicToolName = `${candidate.slice(0, MAX_MCP_TOOL_NAME_LENGTH - suffix.length)}${suffix}`;\n        }\n        nameByKey.set(key, publicToolName);\n        usedNames.add(publicToolName);\n      }\n\n      provider.publicToolName = publicToolName;\n\n      const existing = this.providersByPublicToolName.get(publicToolName) ?? [];\n      existing.push(provider);\n      this.providersByPublicToolName.set(publicToolName, existing);\n    }\n  }\n\n  /**\n   * Returns providers sorted by source recency.\n   */\n  private sortProvidersByRecency(providers: ToolProvider[]): ToolProvider[] {\n    return providers.slice().sort((a, b) => {\n      const aSource = this.sourceByConnectionId.get(a.sourceId);\n      const bSource = this.sourceByConnectionId.get(b.sourceId);\n      const aLastSeen = aSource?.lastSeenAt ?? 0;\n      const bLastSeen = bSource?.lastSeenAt ?? 0;\n\n      return this.compareRecency(bLastSeen, aLastSeen, b.sourceId, a.sourceId);\n    });\n  }\n\n  /**\n   * Compares two source recency tuples and stabilizes order by source id.\n   */\n  private compareRecency(\n    leftLastSeen: number,\n    rightLastSeen: number,\n    leftId: string,\n    rightId: string\n  ): number {\n    const timeDiff = leftLastSeen - rightLastSeen;\n    if (timeDiff !== 0) {\n      return timeDiff;\n    }\n    return leftId.localeCompare(rightId);\n  }\n}\n","import { z } from 'zod/v4';\nimport {\n  CallToolResultSchema,\n  InboundToolSchema,\n  NormalizedToolSchema,\n  normalizeInboundTool,\n  RelayInvokeArgsSchema,\n  type RelayTool,\n} from './protocol.js';\n\nfunction normalizeSupportedInboundTools(tools: z.infer<typeof InboundToolSchema>[]): RelayTool[] {\n  return tools\n    .map(normalizeInboundTool)\n    .filter((tool) => tool.execution?.taskSupport !== 'required');\n}\n\nconst BrowserHelloMessageSchema = z.object({\n  type: z.literal('hello'),\n  tabId: z.string().min(1),\n  origin: z.string().optional(),\n  url: z.string().optional(),\n  title: z.string().optional(),\n  iconUrl: z.string().optional(),\n});\n\nconst BrowserToolsListMessageSchema = z.object({\n  type: z.literal('tools/list'),\n  tools: z.array(InboundToolSchema).transform(normalizeSupportedInboundTools),\n});\n\nconst BrowserToolsChangedMessageSchema = z.object({\n  type: z.literal('tools/changed'),\n  tools: z.array(InboundToolSchema).transform(normalizeSupportedInboundTools),\n});\n\nconst BrowserToolResultMessageSchema = z.object({\n  type: z.literal('result'),\n  callId: z.string().min(1),\n  result: z.unknown(),\n});\n\nconst BrowserPongMessageSchema = z.object({\n  type: z.literal('pong'),\n});\n\n/**\n * Union schema for all browser-to-relay protocol messages.\n */\nexport const BrowserToRelayMessageSchema = z.discriminatedUnion('type', [\n  BrowserHelloMessageSchema,\n  BrowserToolsListMessageSchema,\n  BrowserToolsChangedMessageSchema,\n  BrowserToolResultMessageSchema,\n  BrowserPongMessageSchema,\n]);\n\n/**\n * Browser-to-relay message payload.\n */\nexport type BrowserToRelayMessage = z.infer<typeof BrowserToRelayMessageSchema>;\n\n/**\n * Browser source bootstrap message.\n */\nexport type BrowserHelloMessage = z.infer<typeof BrowserHelloMessageSchema>;\n\n/**\n * Shared relay identity used for discovery and attach verification.\n */\nexport const RelayDescriptorSchema = z.object({\n  host: z.string().min(1),\n  instanceId: z.string().min(1),\n  label: z.string().min(1).optional(),\n  port: z.number().int().min(1).max(65535),\n  relayId: z.string().min(1).optional(),\n  workspace: z.string().min(1).optional(),\n});\n\n/**\n * Relay identity used for discovery and attach verification.\n */\nexport type RelayDescriptor = z.infer<typeof RelayDescriptorSchema>;\n\n/**\n * Schema for server hello messages sent immediately after WebSocket connect.\n */\nexport const ServerHelloMessageSchema = z.object({\n  type: z.literal('server-hello'),\n  service: z.literal('webmcp-local-relay'),\n  version: z.literal(1),\n  ...RelayDescriptorSchema.shape,\n});\n\n/**\n * Server hello payload.\n */\nexport type ServerHelloMessage = z.infer<typeof ServerHelloMessageSchema>;\n\n/**\n * Schema for acceptance of a browser source hello message.\n */\nexport const RelayHelloAcceptedMessageSchema = z.object({\n  type: z.literal('hello/accepted'),\n});\n\n/**\n * Acceptance payload for a browser source hello message.\n */\nexport type RelayHelloAcceptedMessage = z.infer<typeof RelayHelloAcceptedMessageSchema>;\n\n/**\n * Schema for rejection of a browser source hello message.\n */\nexport const RelayHelloRejectedMessageSchema = z.object({\n  type: z.literal('hello/rejected'),\n  reason: z.string().min(1),\n  message: z.string().min(1),\n});\n\n/**\n * Rejection payload for a browser source hello message.\n */\nexport type RelayHelloRejectedMessage = z.infer<typeof RelayHelloRejectedMessageSchema>;\n\nconst RelayInvokeMessageSchema = z.object({\n  type: z.literal('invoke'),\n  callId: z.string().min(1),\n  toolName: z.string().min(1),\n  args: RelayInvokeArgsSchema,\n});\n\nconst RelayPingMessageSchema = z.object({\n  type: z.literal('ping'),\n});\n\nconst RelayReloadMessageSchema = z.object({\n  type: z.literal('reload'),\n});\n\n/**\n * Union schema for all relay-to-browser protocol messages.\n */\nexport const RelayToBrowserMessageSchema = z.discriminatedUnion('type', [\n  ServerHelloMessageSchema,\n  RelayHelloAcceptedMessageSchema,\n  RelayHelloRejectedMessageSchema,\n  RelayInvokeMessageSchema,\n  RelayPingMessageSchema,\n  RelayReloadMessageSchema,\n]);\n\n/**\n * Relay-to-browser message payload.\n */\nexport type RelayToBrowserMessage = z.infer<typeof RelayToBrowserMessageSchema>;\n\n/**\n * Schema for source metadata transmitted in relay-to-relay messages.\n */\nexport const RelaySourceInfoSchema = z.object({\n  sourceId: z.string(),\n  tabId: z.string(),\n  origin: z.string().optional(),\n  url: z.string().optional(),\n  title: z.string().optional(),\n  iconUrl: z.string().optional(),\n  connectedAt: z.number(),\n  lastSeenAt: z.number(),\n  toolCount: z.number(),\n});\n\n/**\n * Source metadata transmitted in relay-to-relay messages.\n */\nexport type RelaySourceInfo = z.infer<typeof RelaySourceInfoSchema>;\n\nconst RelayClientHelloSchema = z.object({\n  type: z.literal('relay/hello'),\n});\n\nconst RelayClientListToolsSchema = z.object({\n  type: z.literal('relay/list-tools'),\n});\n\nconst RelayClientInvokeSchema = z.object({\n  type: z.literal('relay/invoke'),\n  callId: z.string().min(1),\n  toolName: z.string().min(1),\n  args: RelayInvokeArgsSchema,\n});\n\n/**\n * Union schema for all relay-client-to-server messages.\n */\nexport const RelayClientToServerMessageSchema = z.discriminatedUnion('type', [\n  RelayClientHelloSchema,\n  RelayClientListToolsSchema,\n  RelayClientInvokeSchema,\n]);\n\n/**\n * Relay client to server message payload.\n */\nexport type RelayClientToServerMessage = z.infer<typeof RelayClientToServerMessageSchema>;\n\nconst RelayToolsPayloadFields = {\n  tools: z.array(NormalizedToolSchema),\n  sources: z.array(RelaySourceInfoSchema),\n  toolSourceMap: z.record(z.string(), z.array(z.string())),\n};\n\nconst RelayServerToolsSchema = z.object({\n  type: z.literal('relay/tools'),\n  ...RelayToolsPayloadFields,\n});\n\nconst RelayServerResultSchema = z.object({\n  type: z.literal('relay/result'),\n  callId: z.string().min(1),\n  result: CallToolResultSchema,\n});\n\nconst RelayServerToolsChangedSchema = z.object({\n  type: z.literal('relay/tools-changed'),\n  ...RelayToolsPayloadFields,\n});\n\n/**\n * Union schema for all relay-server-to-client messages.\n */\nexport const RelayServerToClientMessageSchema = z.discriminatedUnion('type', [\n  ServerHelloMessageSchema,\n  RelayServerToolsSchema,\n  RelayServerResultSchema,\n  RelayServerToolsChangedSchema,\n]);\n\n/**\n * Relay server to client message payload.\n */\nexport type RelayServerToClientMessage = z.infer<typeof RelayServerToClientMessageSchema>;\n","import { randomUUID } from 'node:crypto';\nimport { EventEmitter } from 'node:events';\n\nimport WebSocket, { WebSocketServer } from 'ws';\nimport {\n  buildPortCandidates,\n  DEFAULT_RELAY_PORT,\n  DEFAULT_RELAY_PORT_RANGE_END,\n  defaultRelayPortPersistPath,\n  persistPort,\n} from './portStrategy.js';\nimport {\n  CallToolResultSchema,\n  type RelayCallToolResult,\n  type RelayInvokeArgs,\n  type RelayTool,\n} from './protocol.js';\nimport { RelayRegistry } from './registry.js';\nimport {\n  type BrowserToRelayMessage,\n  BrowserToRelayMessageSchema,\n  type RelayClientToServerMessage,\n  RelayClientToServerMessageSchema,\n  type RelayServerToClientMessage,\n  RelayServerToClientMessageSchema,\n  type RelayHelloAcceptedMessage,\n  type RelayHelloRejectedMessage,\n  type RelaySourceInfo,\n  type RelayToBrowserMessage,\n  type ServerHelloMessage,\n} from './schemas.js';\n\nconst RELAY_BROWSER_PROTOCOL = 'webmcp.v1';\nconst RELAY_DISCOVERY_PROTOCOL = 'webmcp-discovery.v1';\nconst RELAY_INTERNAL_PROTOCOL = 'webmcp-relay.v1';\nconst RELAY_SERVER_MESSAGE_TIMEOUT_MS = 750;\nconst HEARTBEAT_INTERVAL_MS = 15_000;\nconst HEARTBEAT_DEAD_THRESHOLD_MS = 25_000;\nconst SUPPORTED_SUBPROTOCOLS = new Set([\n  RELAY_BROWSER_PROTOCOL,\n  RELAY_DISCOVERY_PROTOCOL,\n  RELAY_INTERNAL_PROTOCOL,\n]);\n\n/**\n * In-flight relay invocation waiting for a browser `result` message.\n */\ninterface PendingInvocation {\n  connectionId: string;\n  timeoutId: ReturnType<typeof setTimeout>;\n  resolve: (result: RelayCallToolResult) => void;\n  reject: (error: Error) => void;\n}\n\nfunction formatPayloadLimit(bytes: number): string {\n  if (bytes >= 1_000_000 && bytes % 1_000_000 === 0) {\n    return `${String(bytes / 1_000_000)}MB`;\n  }\n  return `${String(bytes)} bytes`;\n}\n\n/**\n * Runtime options for {@link RelayBridgeServer}.\n */\nexport interface RelayBridgeServerOptions {\n  /**\n   * Network interface used by the local WebSocket server.\n   * @defaultValue `\"127.0.0.1\"`\n   */\n  host?: string;\n  /**\n   * Preferred WebSocket port for browser widget connections.\n   * @defaultValue `9333`\n   */\n  port?: number;\n  /**\n   * Whether the preferred port came from an explicit CLI/API override.\n   * Explicit ports fail if occupied by a non-relay process.\n   * @defaultValue `false`\n   */\n  portExplicitlySet?: boolean;\n  /**\n   * Inclusive upper bound for automatic port discovery.\n   * @defaultValue `9348`\n   */\n  portRangeEnd?: number;\n  /**\n   * File path used to cache the last successful relay port.\n   * @defaultValue `~/.webmcp/relay-port.json`\n   */\n  persistPath?: string;\n  /**\n   * Allowed host page origins verified from browser WebSocket requests.\n   * Use `[\"*\"]` to allow all origins.\n   *\n   * Permissive by default for zero-config developer experience: any browser\n   * page can connect and register tools without additional setup. For production\n   * or shared machines, restrict to trusted host origins via the\n   * `--widget-origin` CLI flag or by passing explicit origins here.\n   *\n   * @defaultValue `[\"*\"]`\n   */\n  allowedOrigins?: string[];\n  /**\n   * Maximum WebSocket payload size in bytes.\n   * @defaultValue `10000000`\n   */\n  maxPayloadBytes?: number;\n  /**\n   * Timeout used for browser tool invocations.\n   * @defaultValue `65000`\n   */\n  invokeTimeoutMs?: number;\n  /**\n   * Human-readable relay label reported in discovery handshakes.\n   */\n  label?: string;\n  /**\n   * Optional workspace name reported in discovery handshakes.\n   */\n  workspace?: string;\n  /**\n   * Stable relay identifier used to select between multiple relays.\n   */\n  relayId?: string;\n}\n\n/**\n * WebSocket relay between browser widget frames and MCP server calls.\n *\n * Operates in two modes:\n * - **server** (default): Runs a WebSocket server, accepts browser and relay\n *   client connections.\n * - **client** (fallback on EADDRINUSE): Connects as a WebSocket client to an\n *   existing server relay and proxies tool operations through it.\n */\nexport class RelayBridgeServer extends EventEmitter {\n  /**\n   * Registry for connected sources and aggregated tool definitions.\n   * Only actively used in server mode; remains empty when operating as a client.\n   */\n  readonly registry: RelayRegistry;\n\n  private readonly host: string;\n  private readonly preferredPort: number;\n  private desiredPort: number;\n  private readonly portExplicitlySet: boolean;\n  private readonly portRangeEnd: number;\n  private readonly persistPath: string;\n  private readonly allowedOrigins: string[];\n  private readonly maxPayloadBytes: number;\n  private readonly invokeTimeoutMs: number;\n  private readonly label: string | undefined;\n  private readonly workspace: string | undefined;\n  private readonly relayId: string | undefined;\n  private readonly instanceId: string;\n\n  private wss: WebSocketServer | null = null;\n  private readonly socketByConnectionId = new Map<string, WebSocket>();\n  private readonly requestOriginByConnectionId = new Map<string, string>();\n  private readonly pendingInvocations = new Map<string, PendingInvocation>();\n  private readonly browserClientConnectionIds = new Set<string>();\n  private readonly relayClientConnectionIds = new Set<string>();\n  private readonly heartbeatIntervalByConnectionId = new Map<\n    string,\n    ReturnType<typeof setInterval>\n  >();\n  private readonly lastPongByConnectionId = new Map<string, number>();\n  private readonly onStateChangedPushRelay = () => {\n    this.pushToolsToRelayClients();\n  };\n\n  private _mode: 'server' | 'client' = 'server';\n  private clientSocket: WebSocket | null = null;\n  private clientReconnectTimer: ReturnType<typeof setTimeout> | null = null;\n  private clientReconnectDelay = 500;\n  /**\n   * Maximum delay for relay-to-relay reconnection backoff in client mode.\n   */\n  private readonly clientMaxReconnectDelay = 3_000;\n  private readonly clientMaxReconnectAttempts = 100;\n  private clientReconnectAttempts = 0;\n  private readonly clientPendingInvocations = new Map<string, PendingInvocation>();\n  private clientTools: RelayTool[] = [];\n  private clientSources: RelaySourceInfo[] = [];\n  private clientToolSourceMap: Record<string, string[]> = {};\n  private stopping = false;\n\n  /**\n   * Creates a relay bridge server instance.\n   */\n  constructor(options: RelayBridgeServerOptions = {}, registry?: RelayRegistry) {\n    super();\n    this.registry = registry ?? new RelayRegistry();\n\n    this.host = options.host ?? '127.0.0.1';\n    this.preferredPort = options.port ?? DEFAULT_RELAY_PORT;\n    this.desiredPort = this.preferredPort;\n    this.portExplicitlySet = options.portExplicitlySet ?? false;\n    this.portRangeEnd =\n      options.portRangeEnd ?? Math.max(DEFAULT_RELAY_PORT_RANGE_END, this.preferredPort);\n    this.persistPath = options.persistPath ?? defaultRelayPortPersistPath();\n    this.allowedOrigins = options.allowedOrigins ?? ['*'];\n    // 10MB default: large enough for typical JSON API responses while\n    // still protecting the relay process from unbounded memory growth.\n    this.maxPayloadBytes = options.maxPayloadBytes ?? 10_000_000;\n    this.invokeTimeoutMs = options.invokeTimeoutMs ?? 65_000;\n    this.label = options.label;\n    this.workspace = options.workspace;\n    this.relayId = options.relayId;\n    this.instanceId = randomUUID();\n\n    if (\n      !Number.isInteger(this.preferredPort) ||\n      this.preferredPort < 0 ||\n      this.preferredPort > 65535\n    ) {\n      throw new Error(\n        `Invalid port ${this.preferredPort}. Port must be 0 (auto-assign) or between 1 and 65535.`\n      );\n    }\n    if (\n      !Number.isInteger(this.portRangeEnd) ||\n      this.portRangeEnd < 1 ||\n      this.portRangeEnd > 65535 ||\n      (this.portRangeEnd < this.preferredPort && this.preferredPort !== 0)\n    ) {\n      throw new Error(\n        `Invalid port range ${this.preferredPort}-${this.portRangeEnd}. rangeEnd must be an integer between the preferred port and 65535.`\n      );\n    }\n    if (!Number.isInteger(this.maxPayloadBytes) || this.maxPayloadBytes <= 0) {\n      throw new Error(\n        `Invalid maxPayloadBytes ${this.maxPayloadBytes}. Must be a positive integer.`\n      );\n    }\n    if (!Number.isInteger(this.invokeTimeoutMs) || this.invokeTimeoutMs <= 0) {\n      throw new Error(\n        `Invalid invokeTimeoutMs ${this.invokeTimeoutMs}. Must be a positive integer.`\n      );\n    }\n  }\n\n  /**\n   * Current operating mode.\n   */\n  get mode(): 'server' | 'client' {\n    return this._mode;\n  }\n\n  /**\n   * Resolved listening port. In client mode this is the port of the server\n   * relay being proxied through.\n   */\n  get port(): number {\n    return this.desiredPort;\n  }\n\n  /**\n   * Tools received from the server relay (client mode only).\n   * Returns an empty array in server mode.\n   */\n  listToolsFromRelay(): RelayTool[] {\n    return this._mode === 'client' ? [...this.clientTools] : [];\n  }\n\n  /**\n   * Source metadata received from the server relay (client mode only).\n   * Returns an empty array in server mode.\n   */\n  listSourcesFromRelay(): RelaySourceInfo[] {\n    return this._mode === 'client' ? [...this.clientSources] : [];\n  }\n\n  /**\n   * Tool-to-source mapping received from the server relay (client mode only).\n   * Maps public tool names to arrays of source IDs.\n   * Returns an empty record in server mode.\n   */\n  getToolSourceMapFromRelay(): Record<string, string[]> {\n    return this._mode === 'client' ? { ...this.clientToolSourceMap } : {};\n  }\n\n  /**\n   * Starts the bridge. Attempts to bind a WebSocket server (server mode).\n   * If a compatible relay already owns a candidate port, joins it in client mode.\n   * If a non-relay process owns the port, continues searching the reserved range.\n   */\n  async start(): Promise<void> {\n    if (this.wss || this.clientSocket) {\n      return;\n    }\n\n    this.stopping = false;\n    await this.startUsingPortStrategy();\n  }\n\n  private async startUsingPortStrategy(): Promise<void> {\n    if (this.preferredPort === 0) {\n      await this.startAsServer(0);\n      return;\n    }\n\n    const candidates = await buildPortCandidates({\n      defaultPort: this.preferredPort,\n      ...(this.portExplicitlySet ? { fixedPort: this.preferredPort } : {}),\n      host: this.host,\n      persistPath: this.persistPath,\n      rangeEnd: this.portRangeEnd,\n    });\n\n    for (const candidate of candidates) {\n      try {\n        await this.startAsServer(candidate.port);\n        await this.persistSelectedPort();\n        return;\n      } catch (err) {\n        if (!this.isAddressInUseError(err)) {\n          throw err;\n        }\n\n        const attached = await this.tryAttachToExistingRelay(candidate.port);\n        if (attached) {\n          await this.persistSelectedPort();\n          return;\n        }\n\n        if (candidate.wasFixed) {\n          throw new Error(\n            `Port ${candidate.port} is already in use by a non-WebMCP service and cannot be shared.`\n          );\n        }\n\n        process.stderr.write(\n          `[webmcp-local-relay] info: port ${candidate.port} is occupied by a non-relay service, trying next port\\n`\n        );\n      }\n    }\n\n    throw new Error(\n      `No compatible relay port was available in the range ${this.preferredPort}-${this.portRangeEnd}.`\n    );\n  }\n\n  private isAddressInUseError(error: unknown): boolean {\n    return (\n      error instanceof Error &&\n      ('code' in error ? error.code === 'EADDRINUSE' : error.message.includes('EADDRINUSE'))\n    );\n  }\n\n  private async persistSelectedPort(): Promise<void> {\n    try {\n      await persistPort(this.port, this.persistPath, this.host);\n    } catch (error) {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: could not cache relay port: ${error instanceof Error ? error.message : String(error)}\\n`\n      );\n    }\n  }\n\n  private async tryAttachToExistingRelay(port: number): Promise<boolean> {\n    try {\n      await this.startAsClient(port);\n      process.stderr.write(\n        `[webmcp-local-relay] info: discovered compatible relay on port ${port}, switching to client mode\\n`\n      );\n      return true;\n    } catch (error) {\n      // The caller reports every false here as \"occupied by a non-relay service\". A slow\n      // but healthy relay hits the 750ms hello timeout and lands here too, so name the\n      // real reason rather than leaving the operator with a wrong hypothesis.\n      process.stderr.write(\n        `[webmcp-local-relay] info: port ${port} did not complete a relay handshake: ${error instanceof Error ? error.message : String(error)}\\n`\n      );\n      return false;\n    }\n  }\n\n  /**\n   * Stops all relay resources and rejects any pending invocations.\n   */\n  async stop(): Promise<void> {\n    this.stopping = true;\n\n    if (this.clientReconnectTimer) {\n      clearTimeout(this.clientReconnectTimer);\n      this.clientReconnectTimer = null;\n    }\n\n    if (this._mode === 'client') {\n      for (const pending of this.clientPendingInvocations.values()) {\n        clearTimeout(pending.timeoutId);\n        pending.reject(new Error('Relay client stopped'));\n      }\n      this.clientPendingInvocations.clear();\n      this.clientTools = [];\n      this.clientSources = [];\n      this.clientToolSourceMap = {};\n\n      if (this.clientSocket) {\n        try {\n          this.clientSocket.close(1000, 'Relay client shutting down');\n        } catch (err) {\n          process.stderr.write(\n            `[webmcp-local-relay] warn: error closing client socket during shutdown: ${err instanceof Error ? err.message : String(err)}\\n`\n          );\n        }\n        this.clientSocket = null;\n      }\n      return;\n    }\n\n    this.off('stateChanged', this.onStateChangedPushRelay);\n\n    for (const [connectionId, socket] of this.socketByConnectionId) {\n      this.registry.removeConnection(connectionId);\n      try {\n        socket.close(1001, 'Relay shutting down');\n      } catch (err) {\n        process.stderr.write(\n          `[webmcp-local-relay] warn: error closing socket during shutdown: ${err instanceof Error ? err.message : String(err)}\\n`\n        );\n      }\n    }\n\n    for (const intervalId of this.heartbeatIntervalByConnectionId.values()) {\n      clearInterval(intervalId);\n    }\n    this.heartbeatIntervalByConnectionId.clear();\n    this.lastPongByConnectionId.clear();\n\n    this.socketByConnectionId.clear();\n    this.requestOriginByConnectionId.clear();\n    this.browserClientConnectionIds.clear();\n    this.relayClientConnectionIds.clear();\n\n    for (const pending of this.pendingInvocations.values()) {\n      clearTimeout(pending.timeoutId);\n      pending.reject(new Error('Relay server stopped before tool invocation completed'));\n    }\n    this.pendingInvocations.clear();\n\n    const wss = this.wss;\n    this.wss = null;\n\n    if (!wss) {\n      return;\n    }\n\n    await new Promise<void>((resolve) => {\n      wss.close((err?: Error) => {\n        if (err) {\n          process.stderr.write(\n            `[webmcp-local-relay] warn: WebSocket server close error: ${err.message}\\n`\n          );\n        }\n        resolve();\n      });\n    });\n  }\n\n  /**\n   * Sends a reload message to a connected browser source.\n   * Only supported in server mode.\n   */\n  reloadSource(connectionId: string): void {\n    if (this._mode !== 'server') {\n      throw new Error('reloadSource is only supported in server mode');\n    }\n    const socket = this.socketByConnectionId.get(connectionId);\n    if (!socket || socket.readyState !== WebSocket.OPEN) {\n      throw new Error(`Source ${connectionId} is not connected`);\n    }\n    const message: RelayToBrowserMessage = { type: 'reload' };\n    try {\n      socket.send(JSON.stringify(message));\n    } catch (err) {\n      throw new Error(`Failed to send reload: ${err instanceof Error ? err.message : String(err)}`);\n    }\n  }\n\n  /**\n   * Invokes a tool either locally (server mode) or through the upstream relay\n   * (client mode).\n   */\n  async invokeTool(\n    toolName: string,\n    args: RelayInvokeArgs,\n    options: {\n      sourceId?: string;\n      requestTabId?: string;\n    } = {}\n  ): Promise<RelayCallToolResult> {\n    if (this._mode === 'client') {\n      return this.invokeToolViaRelay(toolName, args);\n    }\n\n    return this.invokeToolLocally(toolName, args, options);\n  }\n\n  private async startAsServer(port = this.desiredPort): Promise<void> {\n    const wss = await new Promise<WebSocketServer>((resolve, reject) => {\n      const server = new WebSocketServer({\n        handleProtocols: (protocols) => {\n          for (const protocol of protocols) {\n            if (SUPPORTED_SUBPROTOCOLS.has(protocol)) {\n              return protocol;\n            }\n          }\n          return false;\n        },\n        host: this.host,\n        port,\n        maxPayload: this.maxPayloadBytes,\n      });\n\n      const onListening = () => {\n        server.off('error', onError);\n        resolve(server);\n      };\n      const onError = (err: Error) => {\n        server.off('listening', onListening);\n        reject(err);\n      };\n\n      server.once('listening', onListening);\n      server.once('error', onError);\n    });\n\n    wss.on('connection', (socket: WebSocket, request) => {\n      const requestOrigin = request.headers.origin;\n      if (requestOrigin && socket.protocol === RELAY_INTERNAL_PROTOCOL) {\n        socket.close(1008, 'Browser connections cannot use the relay protocol');\n        return;\n      }\n\n      const connectionId = randomUUID();\n      this.socketByConnectionId.set(connectionId, socket);\n      if (requestOrigin) {\n        this.requestOriginByConnectionId.set(connectionId, requestOrigin);\n      }\n\n      socket.on('message', (raw: WebSocket.RawData) => {\n        this.onSocketMessage(connectionId, raw);\n      });\n\n      socket.on('close', (code: number) => {\n        this.onSocketClose(connectionId, code);\n      });\n\n      socket.on('error', (err: Error) => {\n        process.stderr.write(\n          `[webmcp-local-relay] warn: socket error for connection ${connectionId}: ${err.message}\\n`\n        );\n        const code =\n          'code' in err && err.code === 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH' ? 1009 : undefined;\n        this.onSocketClose(connectionId, code);\n      });\n\n      try {\n        socket.send(JSON.stringify(this.buildServerHello()));\n      } catch (err) {\n        process.stderr.write(\n          `[webmcp-local-relay] warn: failed to send server hello to connection ${connectionId}: ${err instanceof Error ? err.message : String(err)}\\n`\n        );\n        socket.close(1011, 'Failed to send server hello');\n        return;\n      }\n\n      this.startHeartbeat(connectionId);\n    });\n\n    wss.on('error', (err: Error) => {\n      // Logged, not re-emitted: nothing listens for 'error' on this EventEmitter, and\n      // emit('error') without a listener rethrows, killing the relay via uncaughtException.\n      process.stderr.write(`[webmcp-local-relay] error: WebSocket server error: ${err.message}\\n`);\n    });\n\n    this.wss = wss;\n    this._mode = 'server';\n\n    const address = wss.address();\n    if (address && typeof address !== 'string') {\n      this.desiredPort = address.port;\n    }\n\n    this.on('stateChanged', this.onStateChangedPushRelay);\n  }\n\n  private buildServerHello(): ServerHelloMessage {\n    return {\n      type: 'server-hello',\n      service: 'webmcp-local-relay',\n      version: 1,\n      host: this.host,\n      instanceId: this.instanceId,\n      label: this.label,\n      port: this.desiredPort,\n      relayId: this.relayId ?? this.instanceId,\n      workspace: this.workspace,\n    };\n  }\n\n  /**\n   * `async` is load-bearing: {@link onRelayClientMessage} consumes this through\n   * `.then(onResult, onError)`, so a synchronous throw would escape the socket\n   * message handler as an uncaught exception and leave the relay client waiting\n   * for a `relay/result` that never arrives.\n   */\n  private async invokeToolLocally(\n    toolName: string,\n    args: RelayInvokeArgs,\n    options: { sourceId?: string; requestTabId?: string }\n  ): Promise<RelayCallToolResult> {\n    const resolved = this.registry.resolveInvocation({\n      toolName,\n      ...(options.sourceId === undefined ? {} : { sourceId: options.sourceId }),\n      ...(options.requestTabId === undefined ? {} : { requestTabId: options.requestTabId }),\n    });\n\n    if (!resolved) {\n      throw new Error(`No active browser source provides tool \"${toolName}\"`);\n    }\n\n    const socket = this.socketByConnectionId.get(resolved.connectionId);\n    if (!socket || socket.readyState !== WebSocket.OPEN) {\n      throw new Error(\n        `Tool source ${resolved.connectionId} disconnected before invocation of \"${toolName}\"`\n      );\n    }\n\n    const callId = randomUUID();\n\n    return new Promise<RelayCallToolResult>((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        this.pendingInvocations.delete(callId);\n        reject(\n          new Error(`Invocation for tool \"${toolName}\" timed out after ${this.invokeTimeoutMs}ms`)\n        );\n      }, this.invokeTimeoutMs);\n\n      this.pendingInvocations.set(callId, {\n        connectionId: resolved.connectionId,\n        timeoutId,\n        resolve,\n        reject,\n      });\n\n      const message: RelayToBrowserMessage = {\n        type: 'invoke',\n        callId,\n        toolName: resolved.tool.name,\n        args,\n      };\n\n      try {\n        socket.send(JSON.stringify(message));\n      } catch (err) {\n        clearTimeout(timeoutId);\n        this.pendingInvocations.delete(callId);\n        reject(\n          new Error(\n            `Failed to send invocation for tool \"${toolName}\": ${err instanceof Error ? err.message : err}`\n          )\n        );\n      }\n    });\n  }\n\n  /** Handles a raw message according to the negotiated WebSocket protocol. */\n  private onSocketMessage(connectionId: string, raw: WebSocket.RawData): void {\n    const text = this.rawDataToUtf8(raw);\n\n    let parsedJson: unknown;\n    try {\n      parsedJson = JSON.parse(text);\n    } catch (err) {\n      const preview = text.length > 200 ? `${text.slice(0, 200)}...` : text;\n      process.stderr.write(\n        `[webmcp-local-relay] warn: invalid JSON from connection ${connectionId} (${err instanceof Error ? err.message : 'parse error'}): ${preview}\\n`\n      );\n      return;\n    }\n\n    const typeField =\n      typeof parsedJson === 'object' && parsedJson !== null && 'type' in parsedJson\n        ? parsedJson.type\n        : undefined;\n    const socket = this.socketByConnectionId.get(connectionId);\n    if (!socket) {\n      return;\n    }\n\n    if (socket.protocol === RELAY_INTERNAL_PROTOCOL) {\n      const relayMsg = RelayClientToServerMessageSchema.safeParse(parsedJson);\n      if (relayMsg.success) {\n        this.onRelayClientMessage(connectionId, relayMsg.data);\n      } else {\n        process.stderr.write(\n          `[webmcp-local-relay] warn: invalid relay message from ${connectionId}: ${relayMsg.error.message}\\n`\n        );\n      }\n      return;\n    }\n\n    if (typeof typeField === 'string' && typeField.startsWith('relay/')) {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: connection ${connectionId} used the relay protocol without negotiating it\\n`\n      );\n      socket.close(1008, 'Relay protocol was not negotiated');\n      return;\n    }\n\n    const parsedMessage = BrowserToRelayMessageSchema.safeParse(parsedJson);\n    if (!parsedMessage.success) {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: invalid message from connection ${connectionId} (type=${typeField}): ${parsedMessage.error.message}\\n`\n      );\n      return;\n    }\n\n    this.registry.touchConnection(connectionId);\n    this.onBrowserClientMessage(connectionId, parsedMessage.data);\n  }\n\n  private onBrowserClientMessage(connectionId: string, message: BrowserToRelayMessage): void {\n    if (message.type !== 'hello' && !this.browserClientConnectionIds.has(connectionId)) {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: connection ${connectionId} sent ${message.type} before hello, ignoring\\n`\n      );\n      return;\n    }\n\n    switch (message.type) {\n      case 'hello':\n        try {\n          const socket = this.socketByConnectionId.get(connectionId);\n          const origin = this.requestOriginByConnectionId.get(connectionId) ?? message.origin;\n          if (!this.isHostOriginAllowed(origin)) {\n            process.stderr.write(\n              `[webmcp-local-relay] warn: rejecting source ${connectionId} with disallowed host origin: ${origin ?? 'missing'}\\n`\n            );\n            if (socket) {\n              this.sendHelloRejected(\n                socket,\n                {\n                  type: 'hello/rejected',\n                  reason: 'host-origin-not-allowed',\n                  message: 'Host page origin is not allowed by this relay.',\n                },\n                1008,\n                'Host origin not allowed'\n              );\n            }\n            break;\n          }\n          this.registry.upsertSource(connectionId, { ...message, origin });\n          this.browserClientConnectionIds.add(connectionId);\n          if (socket) {\n            this.sendHelloAccepted(socket, { type: 'hello/accepted' });\n          }\n          this.emit('stateChanged');\n        } catch (err) {\n          process.stderr.write(\n            `[webmcp-local-relay] error: failed to process hello from connection ${connectionId}: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}\\n`\n          );\n        }\n        break;\n\n      case 'tools/list':\n      case 'tools/changed':\n        try {\n          this.registry.registerTools(connectionId, message.tools);\n          this.emit('stateChanged');\n        } catch (err) {\n          process.stderr.write(\n            `[webmcp-local-relay] error: failed to register tools for connection ${connectionId}: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}\\n`\n          );\n          this.socketByConnectionId.get(connectionId)?.close(1008, 'Invalid tool list');\n        }\n        break;\n\n      case 'result': {\n        const pending = this.pendingInvocations.get(message.callId);\n        if (!pending) {\n          process.stderr.write(\n            `[webmcp-local-relay] warn: received result for unknown callId ${message.callId}\\n`\n          );\n          break;\n        }\n        if (pending.connectionId !== connectionId) {\n          process.stderr.write(\n            `[webmcp-local-relay] warn: connection ${connectionId} returned result for another source's callId ${message.callId}\\n`\n          );\n          break;\n        }\n\n        clearTimeout(pending.timeoutId);\n        this.pendingInvocations.delete(message.callId);\n        pending.resolve(this.normalizeCallToolResult(message.result));\n        break;\n      }\n\n      case 'pong':\n        this.lastPongByConnectionId.set(connectionId, Date.now());\n        break;\n    }\n  }\n\n  /**\n   * Handles relay-protocol messages from relay client connections.\n   */\n  private onRelayClientMessage(connectionId: string, message: RelayClientToServerMessage): void {\n    if (message.type !== 'relay/hello' && !this.relayClientConnectionIds.has(connectionId)) {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: connection ${connectionId} sent ${message.type} before relay/hello, ignoring\\n`\n      );\n      return;\n    }\n\n    switch (message.type) {\n      case 'relay/hello':\n        this.relayClientConnectionIds.add(connectionId);\n        break;\n\n      case 'relay/list-tools': {\n        const response = this.buildRelayToolsPayload('relay/tools');\n        const socket = this.socketByConnectionId.get(connectionId);\n        if (socket?.readyState === WebSocket.OPEN) {\n          try {\n            socket.send(JSON.stringify(response));\n          } catch (err) {\n            process.stderr.write(\n              `[webmcp-local-relay] warn: failed to send relay tools response to ${connectionId}: ${err instanceof Error ? err.message : String(err)}\\n`\n            );\n          }\n        }\n        break;\n      }\n\n      case 'relay/invoke': {\n        const { callId, toolName, args } = message;\n        void this.invokeToolLocally(toolName, args ?? {}, {}).then(\n          (result) => this.sendRelayResult(connectionId, callId, result),\n          (error: unknown) =>\n            this.sendRelayResult(connectionId, callId, {\n              content: [\n                {\n                  type: 'text',\n                  text: `Relay invocation failed: ${error instanceof Error ? error.message : String(error)}`,\n                },\n              ],\n              isError: true,\n            })\n        );\n        break;\n      }\n    }\n  }\n\n  private sendRelayResult(connectionId: string, callId: string, result: RelayCallToolResult): void {\n    const socket = this.socketByConnectionId.get(connectionId);\n    if (socket?.readyState !== WebSocket.OPEN) {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: relay client ${connectionId} disconnected before result for callId ${callId} could be delivered\\n`\n      );\n      return;\n    }\n\n    try {\n      socket.send(JSON.stringify({ type: 'relay/result', callId, result }));\n    } catch (error) {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: failed to send relay result to ${connectionId}: ${error instanceof Error ? error.message : String(error)}\\n`\n      );\n    }\n  }\n\n  /**\n   * Pushes current tool state to all connected relay clients.\n   */\n  private pushToolsToRelayClients(): void {\n    if (this.relayClientConnectionIds.size === 0) {\n      return;\n    }\n\n    const message = this.buildRelayToolsPayload('relay/tools-changed');\n    const payload = JSON.stringify(message);\n\n    for (const connectionId of this.relayClientConnectionIds) {\n      const socket = this.socketByConnectionId.get(connectionId);\n      if (socket?.readyState === WebSocket.OPEN) {\n        try {\n          socket.send(payload);\n        } catch (err) {\n          process.stderr.write(\n            `[webmcp-local-relay] warn: failed to push tool update to relay client ${connectionId}: ${err instanceof Error ? err.message : String(err)}\\n`\n          );\n        }\n      }\n    }\n  }\n\n  /**\n   * Handles source disconnection and rejects in-flight calls owned by that source.\n   *\n   * Guarded against double-call: both 'error' and 'close' events fire on\n   * socket failure, but cleanup (and the stateChanged emission) runs only once.\n   */\n  private onSocketClose(connectionId: string, code?: number): void {\n    // Guard against double invocation: ws fires both 'error' and 'close' for\n    // maxPayload violations. The second call is a no-op.\n    if (!this.socketByConnectionId.has(connectionId)) return;\n\n    this.stopHeartbeat(connectionId);\n    this.requestOriginByConnectionId.delete(connectionId);\n    this.browserClientConnectionIds.delete(connectionId);\n    this.relayClientConnectionIds.delete(connectionId);\n    this.registry.removeConnection(connectionId);\n    this.socketByConnectionId.delete(connectionId);\n    this.emit('stateChanged');\n\n    // WS close code 1009 = \"Message Too Big\": the browser sent a response\n    // that exceeded maxPayloadBytes. Surface a clear error instead of letting\n    // the invocation time out silently after invokeTimeoutMs.\n    const isPayloadExceeded = code === 1009;\n\n    for (const [callId, pending] of this.pendingInvocations.entries()) {\n      if (pending.connectionId !== connectionId) {\n        continue;\n      }\n\n      clearTimeout(pending.timeoutId);\n      this.pendingInvocations.delete(callId);\n\n      if (isPayloadExceeded) {\n        pending.reject(\n          new Error(\n            `Tool result exceeded maximum payload size (${formatPayloadLimit(this.maxPayloadBytes)}). Use --max-payload to increase the limit.`\n          )\n        );\n      } else {\n        pending.reject(new Error(`Tool source ${connectionId} disconnected during invocation`));\n      }\n    }\n  }\n\n  private startHeartbeat(connectionId: string): void {\n    this.lastPongByConnectionId.set(connectionId, Date.now());\n\n    const intervalId = setInterval(() => {\n      const socket = this.socketByConnectionId.get(connectionId);\n      if (!socket || socket.readyState !== WebSocket.OPEN) {\n        this.stopHeartbeat(connectionId);\n        return;\n      }\n\n      // Skip heartbeat for relay client connections; they have their own reconnect logic.\n      if (this.relayClientConnectionIds.has(connectionId)) {\n        return;\n      }\n\n      const lastPong = this.lastPongByConnectionId.get(connectionId) ?? 0;\n      if (Date.now() - lastPong > HEARTBEAT_DEAD_THRESHOLD_MS) {\n        process.stderr.write(\n          `[webmcp-local-relay] warn: connection ${connectionId} missed heartbeat, closing\\n`\n        );\n        this.stopHeartbeat(connectionId);\n        socket.close(1001, 'Heartbeat timeout');\n        return;\n      }\n\n      try {\n        socket.send(JSON.stringify({ type: 'ping' }));\n      } catch (err) {\n        process.stderr.write(\n          `[webmcp-local-relay] warn: failed to send heartbeat ping to ${connectionId}: ${err instanceof Error ? err.message : String(err)}\\n`\n        );\n      }\n    }, HEARTBEAT_INTERVAL_MS);\n\n    this.heartbeatIntervalByConnectionId.set(connectionId, intervalId);\n  }\n\n  private stopHeartbeat(connectionId: string): void {\n    const intervalId = this.heartbeatIntervalByConnectionId.get(connectionId);\n    if (intervalId !== undefined) {\n      clearInterval(intervalId);\n      this.heartbeatIntervalByConnectionId.delete(connectionId);\n    }\n    this.lastPongByConnectionId.delete(connectionId);\n  }\n\n  private async startAsClient(port = this.desiredPort): Promise<void> {\n    this.stopping = false;\n\n    const previousMode = this._mode;\n    const previousPort = this.desiredPort;\n    this._mode = 'client';\n    this.desiredPort = port;\n\n    try {\n      const { bufferedMessages, socket } = await this.connectToRelayServer(port);\n      this.clientSocket = socket;\n      this.clientReconnectDelay = 500;\n      this.clientReconnectAttempts = 0;\n      this.setupClientHandlers(socket, bufferedMessages);\n    } catch (error) {\n      this._mode = previousMode;\n      this.desiredPort = previousPort;\n      throw error;\n    }\n  }\n\n  private async connectToRelayServer(\n    port: number\n  ): Promise<{ bufferedMessages: RelayServerToClientMessage[]; socket: WebSocket }> {\n    return new Promise((resolve, reject) => {\n      const wsUrl = `ws://${this.host}:${port}`;\n      const ws = new WebSocket(wsUrl, RELAY_INTERNAL_PROTOCOL);\n      const bufferedMessages: RelayServerToClientMessage[] = [];\n\n      const cleanup = () => {\n        clearTimeout(timeoutId);\n        ws.off('close', onCloseBeforeReady);\n        ws.off('error', onErrorBeforeReady);\n        ws.off('message', onMessageBeforeReady);\n        ws.off('open', onOpen);\n      };\n\n      const rejectWith = (error: Error) => {\n        cleanup();\n        ws.once('error', () => {\n          // Ignore late socket errors from ports that failed relay verification.\n        });\n        ws.terminate();\n        reject(error);\n      };\n\n      const finish = () => {\n        cleanup();\n        resolve({ bufferedMessages, socket: ws });\n      };\n\n      const onOpen = () => {\n        try {\n          this.sendRelayClientHandshake(ws);\n        } catch (err) {\n          rejectWith(\n            new Error(\n              `Failed to send handshake to relay server at ${wsUrl}: ${err instanceof Error ? err.message : String(err)}`\n            )\n          );\n        }\n      };\n\n      const onErrorBeforeReady = (err: Error) => {\n        rejectWith(new Error(`Failed to connect to relay server at ${wsUrl}: ${err.message}`));\n      };\n\n      const onCloseBeforeReady = () => {\n        rejectWith(new Error(`Connection to ${wsUrl} closed before relay verification completed`));\n      };\n\n      const onMessageBeforeReady = (raw: WebSocket.RawData) => {\n        const message = this.parseRelayServerMessage(raw);\n        if (!message) {\n          rejectWith(new Error(`Received a non-relay response while probing ${wsUrl}`));\n          return;\n        }\n\n        bufferedMessages.push(message);\n\n        if (message.type === 'server-hello') {\n          if (message.service !== 'webmcp-local-relay') {\n            rejectWith(new Error(`Unexpected relay service \"${message.service}\" at ${wsUrl}`));\n            return;\n          }\n          finish();\n          return;\n        }\n\n        if (message.type === 'relay/tools' || message.type === 'relay/tools-changed') {\n          finish();\n        }\n      };\n\n      const timeoutId = setTimeout(() => {\n        rejectWith(new Error(`Timed out waiting for relay hello from ${wsUrl}`));\n      }, RELAY_SERVER_MESSAGE_TIMEOUT_MS);\n\n      ws.once('open', onOpen);\n      ws.once('error', onErrorBeforeReady);\n      ws.once('close', onCloseBeforeReady);\n      ws.on('message', onMessageBeforeReady);\n    });\n  }\n\n  private setupClientHandlers(\n    ws: WebSocket,\n    bufferedMessages: RelayServerToClientMessage[] = []\n  ): void {\n    for (const message of bufferedMessages) {\n      this.processRelayServerMessage(message);\n    }\n\n    ws.on('message', (raw: WebSocket.RawData) => {\n      const message = this.parseRelayServerMessage(raw);\n      if (!message) {\n        return;\n      }\n\n      this.processRelayServerMessage(message);\n    });\n\n    ws.on('close', () => {\n      this.clientSocket = null;\n      for (const [callId, pending] of this.clientPendingInvocations) {\n        clearTimeout(pending.timeoutId);\n        this.clientPendingInvocations.delete(callId);\n        pending.reject(new Error('Relay server connection lost during invocation'));\n      }\n\n      this.clientTools = [];\n      this.clientSources = [];\n      this.clientToolSourceMap = {};\n      this.emit('stateChanged');\n\n      if (!this.stopping) {\n        this.scheduleReconnect();\n      }\n    });\n\n    ws.on('error', (err: Error) => {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: relay client socket error: ${err.message}\\n`\n      );\n    });\n  }\n\n  private sendRelayClientHandshake(ws: WebSocket): void {\n    ws.send(JSON.stringify({ type: 'relay/hello' }));\n    ws.send(JSON.stringify({ type: 'relay/list-tools' }));\n  }\n\n  private parseRelayServerMessage(raw: WebSocket.RawData): RelayServerToClientMessage | null {\n    const text = this.rawDataToUtf8(raw);\n    let parsed: unknown;\n    try {\n      parsed = JSON.parse(text);\n    } catch (err) {\n      const preview = text.length > 200 ? `${text.slice(0, 200)}...` : text;\n      process.stderr.write(\n        `[webmcp-local-relay] warn: invalid JSON from relay server (${err instanceof Error ? err.message : 'parse error'}): ${preview}\\n`\n      );\n      return null;\n    }\n\n    const message = RelayServerToClientMessageSchema.safeParse(parsed);\n    if (!message.success) {\n      const typeField =\n        typeof parsed === 'object' && parsed !== null && 'type' in parsed ? parsed.type : 'unknown';\n      process.stderr.write(\n        `[webmcp-local-relay] warn: invalid relay server message (type=${typeField}): ${message.error.message}\\n`\n      );\n      return null;\n    }\n\n    return message.data;\n  }\n\n  private processRelayServerMessage(message: RelayServerToClientMessage): void {\n    switch (message.type) {\n      case 'server-hello':\n        break;\n\n      case 'relay/tools':\n      case 'relay/tools-changed':\n        this.clientTools = message.tools;\n        this.clientSources = message.sources;\n        this.clientToolSourceMap = message.toolSourceMap;\n        this.emit('stateChanged');\n        break;\n\n      case 'relay/result': {\n        const pending = this.clientPendingInvocations.get(message.callId);\n        if (!pending) {\n          process.stderr.write(\n            `[webmcp-local-relay] warn: received relay result for unknown callId ${message.callId}\\n`\n          );\n          break;\n        }\n        clearTimeout(pending.timeoutId);\n        this.clientPendingInvocations.delete(message.callId);\n        pending.resolve(message.result);\n        break;\n      }\n    }\n  }\n\n  private scheduleReconnect(): void {\n    if (this.clientReconnectTimer || this.stopping) {\n      return;\n    }\n\n    this.clientReconnectAttempts++;\n    if (this.clientReconnectAttempts >= this.clientMaxReconnectAttempts) {\n      process.stderr.write(\n        `[webmcp-local-relay] error: giving up reconnection after ${this.clientReconnectAttempts} attempts\\n`\n      );\n      return;\n    }\n\n    const delay = this.clientReconnectDelay;\n    this.clientReconnectDelay = Math.min(\n      this.clientReconnectDelay * 1.5,\n      this.clientMaxReconnectDelay\n    );\n\n    this.clientReconnectTimer = setTimeout(() => {\n      this.clientReconnectTimer = null;\n      if (this.stopping) {\n        return;\n      }\n\n      void this.reconnectWithModePromotion();\n    }, delay);\n  }\n\n  /**\n   * Attempts to promote from client to server mode when reconnecting.\n   * Re-runs the same attach-or-bind strategy used during startup.\n   */\n  private async reconnectWithModePromotion(): Promise<void> {\n    try {\n      await this.startUsingPortStrategy();\n      this.clientReconnectDelay = 500;\n      this.clientReconnectAttempts = 0;\n      if (this._mode === 'server') {\n        process.stderr.write('[webmcp-local-relay] info: promoted from client to server mode\\n');\n        this.emit('stateChanged');\n      }\n    } catch (err) {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: reconnection failed: ${err instanceof Error ? err.message : String(err)}\\n`\n      );\n      if (!this.stopping) {\n        this.scheduleReconnect();\n      }\n    }\n  }\n\n  private async invokeToolViaRelay(\n    toolName: string,\n    args: RelayInvokeArgs\n  ): Promise<RelayCallToolResult> {\n    if (!this.clientSocket || this.clientSocket.readyState !== WebSocket.OPEN) {\n      throw new Error('Not connected to relay server');\n    }\n\n    const callId = randomUUID();\n    const socket = this.clientSocket;\n\n    return new Promise<RelayCallToolResult>((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        this.clientPendingInvocations.delete(callId);\n        reject(\n          new Error(\n            `Proxied invocation for tool \"${toolName}\" timed out after ${this.invokeTimeoutMs}ms`\n          )\n        );\n      }, this.invokeTimeoutMs);\n\n      this.clientPendingInvocations.set(callId, {\n        connectionId: 'relay-server',\n        timeoutId,\n        resolve,\n        reject,\n      });\n\n      const message: RelayClientToServerMessage = {\n        type: 'relay/invoke',\n        callId,\n        toolName,\n        args,\n      };\n\n      try {\n        socket.send(JSON.stringify(message));\n      } catch (err) {\n        clearTimeout(timeoutId);\n        this.clientPendingInvocations.delete(callId);\n        reject(\n          new Error(`Failed to send relay invocation: ${err instanceof Error ? err.message : err}`)\n        );\n      }\n    });\n  }\n\n  /**\n   * Builds the complete relay response payload including tools and source metadata.\n   */\n  private buildRelayToolsPayload(\n    type: 'relay/tools' | 'relay/tools-changed'\n  ): RelayServerToClientMessage {\n    const tools = this.registry.listTools();\n    const sources = this.registry.listSources();\n    const toolSourceMap: Record<string, string[]> = {};\n\n    for (const tool of tools) {\n      toolSourceMap[tool.name] = tool.sources.map((s) => s.sourceId);\n    }\n\n    return {\n      type,\n      tools: tools.map(({ originalName: _originalName, sources: _sources, ...tool }) => tool),\n      sources,\n      toolSourceMap,\n    };\n  }\n\n  private isHostOriginAllowed(origin: string | undefined): boolean {\n    if (this.allowedOrigins.includes('*')) {\n      return true;\n    }\n\n    if (!origin) {\n      return false;\n    }\n\n    return this.allowedOrigins.includes(origin);\n  }\n\n  private sendHelloAccepted(socket: WebSocket, message: RelayHelloAcceptedMessage): void {\n    try {\n      socket.send(JSON.stringify(message));\n    } catch (err) {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: failed to send hello acceptance: ${err instanceof Error ? err.message : String(err)}\\n`\n      );\n      socket.close(1011, 'Failed to send hello acceptance');\n    }\n  }\n\n  private sendHelloRejected(\n    socket: WebSocket,\n    message: RelayHelloRejectedMessage,\n    closeCode: number,\n    closeReason: string\n  ): void {\n    try {\n      socket.send(JSON.stringify(message), () => {\n        try {\n          socket.close(closeCode, closeReason);\n        } catch {\n          // Ignore close failures after a rejection send attempt.\n        }\n      });\n    } catch (err) {\n      process.stderr.write(\n        `[webmcp-local-relay] warn: failed to send hello rejection: ${err instanceof Error ? err.message : String(err)}\\n`\n      );\n      socket.close(closeCode, closeReason);\n    }\n  }\n\n  /**\n   * Validates browser tool results against CallToolResultSchema.\n   * Non-conforming payloads are wrapped as error results with diagnostic text.\n   */\n  private normalizeCallToolResult(result: unknown): RelayCallToolResult {\n    const parsed = CallToolResultSchema.safeParse(result);\n    if (parsed.success) {\n      return parsed.data;\n    }\n\n    const preview = JSON.stringify(result)?.slice(0, 500) ?? 'undefined';\n    process.stderr.write(\n      `[webmcp-local-relay] warn: tool returned invalid CallToolResult (${parsed.error.message}), wrapping as error: ${preview}\\n`\n    );\n\n    return {\n      content: [\n        {\n          type: 'text',\n          text: `Tool returned an invalid result (expected {content: [...]}): ${preview}`,\n        },\n      ],\n      isError: true,\n    };\n  }\n\n  /**\n   * Converts WebSocket raw data variants to a UTF-8 string payload.\n   */\n  private rawDataToUtf8(raw: WebSocket.RawData): string {\n    if (Array.isArray(raw)) return Buffer.concat(raw).toString('utf8');\n    if (Buffer.isBuffer(raw)) return raw.toString('utf8');\n    return Buffer.from(raw).toString('utf8');\n  }\n}\n","import { parseArgs } from 'node:util';\n\nimport { DEFAULT_RELAY_PORT } from './portStrategy.js';\n\n/**\n * Parsed CLI options for relay startup.\n */\nexport interface CliOptions {\n  help: boolean;\n  host: string;\n  port: number;\n  portExplicitlySet: boolean;\n  allowedOrigins: string[];\n  label?: string;\n  workspace?: string;\n  relayId?: string;\n  maxPayloadBytes?: number;\n  invokeTimeoutMs?: number;\n}\n\nfunction parsePositiveInteger(name: string, value: string | undefined): number | undefined {\n  if (value === undefined) return undefined;\n  const parsed = Number(value);\n  if (!Number.isInteger(parsed) || parsed <= 0) {\n    throw new Error(`Invalid ${name} \"${value}\". Must be a positive integer.`);\n  }\n  return parsed;\n}\n\n/**\n * Parses supported CLI flags for relay startup.\n */\nexport function parseCliOptions(argv: string[]): CliOptions {\n  const { values } = parseArgs({\n    args: argv,\n    options: {\n      help: { type: 'boolean', short: 'h' },\n      host: { type: 'string', short: 'H' },\n      'allowed-origin': { type: 'string' },\n      'invoke-timeout': { type: 'string' },\n      label: { type: 'string' },\n      'max-payload': { type: 'string' },\n      port: { type: 'string', short: 'p' },\n      'relay-id': { type: 'string' },\n      'widget-origin': { type: 'string' },\n      workspace: { type: 'string' },\n      'ws-origin': { type: 'string' },\n    },\n    strict: true,\n  });\n\n  const port = values.port === undefined ? DEFAULT_RELAY_PORT : Number(values.port);\n  if (!Number.isInteger(port) || port <= 0 || port > 65535) {\n    throw new Error(`Invalid port \"${values.port}\". Port must be an integer between 1 and 65535.`);\n  }\n\n  const invokeTimeoutMs = parsePositiveInteger('invoke-timeout', values['invoke-timeout']);\n  const maxPayloadBytes = parsePositiveInteger('max-payload', values['max-payload']);\n\n  const allowedOrigins = (\n    values['widget-origin'] ??\n    values['allowed-origin'] ??\n    values['ws-origin']\n  )\n    ?.split(',')\n    .map((origin) => origin.trim())\n    .filter(Boolean) ?? ['*'];\n  if (allowedOrigins.length === 0) {\n    throw new Error('--widget-origin must include at least one origin.');\n  }\n\n  return {\n    allowedOrigins,\n    help: values.help ?? false,\n    host: values.host ?? '127.0.0.1',\n    port,\n    portExplicitlySet: values.port !== undefined,\n    ...(values.label === undefined ? {} : { label: values.label }),\n    ...(invokeTimeoutMs === undefined ? {} : { invokeTimeoutMs }),\n    ...(maxPayloadBytes === undefined ? {} : { maxPayloadBytes }),\n    ...(values['relay-id'] === undefined ? {} : { relayId: values['relay-id'] }),\n    ...(values.workspace === undefined ? {} : { workspace: values.workspace }),\n  };\n}\n\n/**\n * Prints CLI usage to stderr.\n */\nexport function printHelp(): void {\n  process.stderr.write(\n    [\n      'webmcp-local-relay',\n      '',\n      'Usage:',\n      '  webmcp-local-relay [--host 127.0.0.1] [--port 9333] [--widget-origin https://myapp.example.com]',\n      '',\n      'Options:',\n      '  --host, -H               Bind host for local websocket relay (default: 127.0.0.1)',\n      '  --port, -p               Preferred root port for the local relay cluster (default: 9333)',\n      '  --widget-origin          Allowed host page origin(s), comma-separated (default: *)',\n      '  --allowed-origin         Deprecated alias for --widget-origin',\n      '  --ws-origin              Deprecated alias for --widget-origin',\n      '  --label                  Human-readable relay label reported during discovery',\n      '  --workspace              Optional workspace name reported during discovery',\n      '  --relay-id               Stable relay identifier reported during discovery',\n      '  --invoke-timeout         Browser tool invocation timeout in milliseconds (default: 65000)',\n      '  --max-payload            Maximum WebSocket payload size in bytes (default: 10000000)',\n      '  --help, -h               Show help',\n      '',\n    ].join('\\n')\n  );\n}\n","import { execFile } from 'node:child_process';\n\nimport {\n  fromJsonSchema,\n  type JsonSchemaType,\n  McpServer,\n  type RegisteredTool,\n  type Transport,\n} from '@modelcontextprotocol/server';\nimport { StdioServerTransport } from '@modelcontextprotocol/server/stdio';\nimport { z } from 'zod/v4';\n\nimport { RelayBridgeServer, type RelayBridgeServerOptions } from './bridgeServer.js';\nimport type { AggregatedTool, SourceInfo } from './registry.js';\n\n/**\n * Base options shared by all {@link LocalRelayMcpServer} configurations.\n */\ninterface LocalRelayMcpServerBaseOptions {\n  /**\n   * MCP server name reported during initialization.\n   */\n  serverName?: string;\n  /**\n   * MCP server version reported during initialization.\n   */\n  serverVersion?: string;\n}\n\n/**\n * Construction options for {@link LocalRelayMcpServer}.\n *\n * Provide either an existing `bridge` instance OR `bridgeOptions` to create\n * one internally — not both.\n */\nexport type LocalRelayMcpServerOptions = LocalRelayMcpServerBaseOptions &\n  (\n    | { bridge: RelayBridgeServer; bridgeOptions?: never }\n    | { bridge?: never; bridgeOptions?: RelayBridgeServerOptions }\n  );\n\n/**\n * MCP server facade that exposes browser-relayed tools over MCP transport.\n */\nexport class LocalRelayMcpServer {\n  /**\n   * Underlying WebSocket bridge used for browser communication.\n   */\n  readonly bridge: RelayBridgeServer;\n\n  private readonly mcpServer: McpServer;\n  private readonly dynamicTools = new Map<string, { handle: RegisteredTool; signature: string }>();\n\n  private syncDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n  private connected = false;\n\n  /**\n   * Creates a local relay MCP server with static and dynamic tool registration.\n   */\n  constructor(options: LocalRelayMcpServerOptions = {}) {\n    this.bridge = options.bridge ?? new RelayBridgeServer(options.bridgeOptions);\n\n    this.mcpServer = new McpServer({\n      name: options.serverName ?? 'webmcp-local-relay',\n      version: options.serverVersion ?? '0.0.0',\n    });\n\n    this.bridge.on('stateChanged', () => {\n      this.debouncedSyncDynamicTools();\n    });\n\n    this.registerStaticTools();\n  }\n\n  /**\n   * Starts the browser bridge and synchronizes dynamic MCP tools.\n   */\n  async start(): Promise<void> {\n    await this.bridge.start();\n    this.syncDynamicTools();\n  }\n\n  /**\n   * Connects the MCP server to a transport.\n   *\n   * This may be called exactly once per instance lifecycle.\n   */\n  async connect(transport: Transport): Promise<void> {\n    if (this.connected) {\n      throw new Error('MCP server transport already connected');\n    }\n\n    await this.mcpServer.connect(transport);\n    this.connected = true;\n\n    this.mcpServer.server.onerror = (error) => {\n      process.stderr.write(\n        `[webmcp-local-relay] error: MCP protocol error: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}\\n`\n      );\n    };\n  }\n\n  /**\n   * Convenience helper that connects the server over stdio transport.\n   */\n  async startStdio(): Promise<void> {\n    await this.connect(new StdioServerTransport());\n  }\n\n  /**\n   * Stops MCP transport and bridge resources.\n   */\n  async stop(): Promise<void> {\n    this.connected = false;\n\n    if (this.syncDebounceTimer) {\n      clearTimeout(this.syncDebounceTimer);\n      this.syncDebounceTimer = null;\n    }\n\n    let mcpCloseError: unknown;\n    try {\n      await this.mcpServer.close();\n    } catch (err) {\n      mcpCloseError = err;\n      process.stderr.write(\n        `[webmcp-local-relay] error: failed to close MCP server: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}\\n`\n      );\n    }\n    await this.bridge.stop();\n    if (mcpCloseError) {\n      process.stderr.write(\n        '[webmcp-local-relay] warn: shutdown completed with errors (MCP server close failed)\\n'\n      );\n    }\n  }\n\n  /**\n   * Returns dynamic tool names currently registered in MCP.\n   */\n  listDynamicToolNames(): string[] {\n    return Array.from(this.dynamicTools.keys()).sort();\n  }\n\n  /**\n   * Registers built-in management tools exposed by the relay.\n   */\n  private registerStaticTools(): void {\n    this.mcpServer.registerTool(\n      'webmcp_list_sources',\n      {\n        description: 'List connected browser tool sources and their metadata.',\n        inputSchema: z.object({}),\n        annotations: {\n          readOnlyHint: true,\n          idempotentHint: true,\n        },\n      },\n      async () => {\n        const clientMode = this.bridge.mode === 'client';\n        const sources = clientMode\n          ? this.bridge.listSourcesFromRelay()\n          : this.bridge.registry.listSources();\n        const info = {\n          ...(clientMode ? { mode: 'client' as const } : {}),\n          count: sources.length,\n          sources,\n        };\n        return {\n          content: [{ type: 'text', text: JSON.stringify(info, null, 2) }],\n          structuredContent: info,\n        };\n      }\n    );\n\n    this.mcpServer.registerTool(\n      'webmcp_list_tools',\n      {\n        description:\n          'List WebMCP tools available from connected browser sources. Returns tool definitions including name, description, input schema, and source info.',\n        inputSchema: z.object({}),\n        annotations: {\n          readOnlyHint: true,\n          idempotentHint: true,\n        },\n      },\n      async () => {\n        const tools = this.listAggregatedTools();\n        const info = { count: tools.length, tools };\n        return {\n          content: [{ type: 'text', text: JSON.stringify(info, null, 2) }],\n          structuredContent: info,\n        };\n      }\n    );\n\n    this.mcpServer.registerTool(\n      'webmcp_open_page',\n      {\n        description:\n          \"Open a URL in the user's default browser, or refresh a connected source page. Use to launch WebMCP-enabled pages or reload stale connections.\",\n        inputSchema: z.object({\n          url: z.string().describe('URL to open or match for refresh.'),\n          refresh: z\n            .boolean()\n            .optional()\n            .describe(\n              'If true, refresh the connected source matching this URL instead of opening a new tab.'\n            ),\n        }),\n        annotations: { readOnlyHint: false },\n      },\n      async ({ url, refresh }) => {\n        let parsed: URL;\n        try {\n          parsed = new URL(url);\n        } catch {\n          return {\n            content: [{ type: 'text' as const, text: `Invalid URL: ${url}` }],\n            isError: true,\n          };\n        }\n\n        if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n          return {\n            content: [\n              {\n                type: 'text' as const,\n                text: `Only http: and https: URLs are allowed. Got: ${parsed.protocol}`,\n              },\n            ],\n            isError: true,\n          };\n        }\n\n        const existing =\n          this.bridge.mode === 'server'\n            ? this.bridge.registry\n                .listSources()\n                .find((source) => source.url && URL.parse(source.url)?.origin === parsed.origin)\n            : undefined;\n\n        if (refresh) {\n          if (this.bridge.mode === 'client') {\n            return {\n              content: [\n                {\n                  type: 'text' as const,\n                  text: 'Refresh is not supported in client mode. Only the server relay can reload sources.',\n                },\n              ],\n              isError: true,\n            };\n          }\n\n          if (!existing) {\n            return {\n              content: [\n                {\n                  type: 'text' as const,\n                  text: `No connected source matches origin ${parsed.origin}. The page may not be open or connected.`,\n                },\n              ],\n              isError: true,\n            };\n          }\n\n          try {\n            this.bridge.reloadSource(existing.sourceId);\n            return {\n              content: [\n                {\n                  type: 'text' as const,\n                  text: `Reload sent to source ${existing.sourceId} (${existing.url ?? existing.origin}).`,\n                },\n              ],\n            };\n          } catch (err) {\n            return {\n              content: [\n                {\n                  type: 'text' as const,\n                  text: `Failed to reload source: ${err instanceof Error ? err.message : String(err)}`,\n                },\n              ],\n              isError: true,\n            };\n          }\n        }\n\n        try {\n          await this.openInBrowser(url);\n        } catch (err) {\n          return {\n            content: [\n              {\n                type: 'text' as const,\n                text: `Failed to open browser: ${err instanceof Error ? err.message : String(err)}`,\n              },\n            ],\n            isError: true,\n          };\n        }\n\n        if (existing) {\n          return {\n            content: [\n              {\n                type: 'text' as const,\n                text: `Opened ${url} in the default browser. Note: a source from ${existing.url ?? existing.origin} is already connected.`,\n              },\n            ],\n          };\n        }\n\n        return {\n          content: [{ type: 'text' as const, text: `Opened ${url} in the default browser.` }],\n        };\n      }\n    );\n  }\n\n  /**\n   * Opens a URL in the user's default browser using the platform open command.\n   *\n   * Passes the re-serialized `URL.href` directly to the platform launcher.\n   * No shell or command-language string is involved.\n   */\n  private openInBrowser(url: string): Promise<void> {\n    const safeUrl = new URL(url).href;\n    const command =\n      process.platform === 'darwin'\n        ? 'open'\n        : process.platform === 'win32'\n          ? 'explorer.exe'\n          : 'xdg-open';\n    return new Promise((resolve, reject) => {\n      execFile(command, [safeUrl], (err) => {\n        if (err) reject(err);\n        else resolve();\n      });\n    });\n  }\n\n  /**\n   * Debounces rapid stateChanged events into a single sync pass.\n   *\n   * Browser reconnections emit multiple stateChanged events in quick\n   * succession (hello, tools/list). Without debouncing, each triggers a\n   * full sync that removes and re-registers tools — sending per-operation\n   * notifications through the stdio transport and overwhelming the agent.\n   */\n  private debouncedSyncDynamicTools(): void {\n    if (this.syncDebounceTimer) {\n      return;\n    }\n\n    this.syncDebounceTimer = setTimeout(() => {\n      this.syncDebounceTimer = null;\n      try {\n        this.syncDynamicTools();\n      } catch (err) {\n        const details = err instanceof Error ? (err.stack ?? err.message) : String(err);\n        process.stderr.write(\n          `[webmcp-local-relay] error: failed to sync dynamic tools: ${details}\\n`\n        );\n      }\n    }, 16);\n  }\n\n  /**\n   * Returns the current aggregated tool list, dispatching based on bridge mode.\n   */\n  private listAggregatedTools(): AggregatedTool[] {\n    return this.bridge.mode === 'client'\n      ? this.buildAggregatedToolsFromRelay()\n      : this.bridge.registry.listTools();\n  }\n\n  /**\n   * Converts relay client tool descriptors to aggregated tool shape.\n   * Populates per-tool source metadata from the relay's tool-source mapping.\n   */\n  private buildAggregatedToolsFromRelay(): AggregatedTool[] {\n    const toolSourceMap = this.bridge.getToolSourceMapFromRelay();\n    const allSources = this.bridge.listSourcesFromRelay();\n    const sourceById = new Map(allSources.map((s) => [s.sourceId, s]));\n\n    return this.bridge\n      .listToolsFromRelay()\n      .map((tool) => {\n        const sourceIds = toolSourceMap[tool.name] ?? [];\n        const sources: SourceInfo[] = [];\n        for (const id of sourceIds) {\n          const source = sourceById.get(id);\n          if (source) {\n            sources.push(source);\n          } else {\n            process.stderr.write(\n              `[webmcp-local-relay] warn: tool \"${tool.name}\" references unknown sourceId \"${id}\"\\n`\n            );\n          }\n        }\n\n        return {\n          ...tool,\n          originalName: tool.name,\n          sources,\n        };\n      })\n      .sort((left, right) => left.name.localeCompare(right.name));\n  }\n\n  /**\n   * Applies current aggregated tool state to MCP dynamic registrations.\n   */\n  private syncDynamicTools(): void {\n    const tools = this.listAggregatedTools();\n    const nextNames = new Set(tools.map((tool) => tool.name));\n\n    for (const [name, registration] of this.dynamicTools) {\n      if (nextNames.has(name)) {\n        continue;\n      }\n\n      registration.handle.remove();\n      this.dynamicTools.delete(name);\n    }\n\n    for (const tool of tools) {\n      const signature = this.toolSignature(tool);\n      const current = this.dynamicTools.get(tool.name);\n\n      if (current?.signature === signature) {\n        continue;\n      }\n\n      if (current) {\n        current.handle.remove();\n        this.dynamicTools.delete(tool.name);\n      }\n\n      try {\n        const handle = this.registerDynamicTool(tool);\n        this.dynamicTools.set(tool.name, { handle, signature });\n      } catch (err) {\n        const details = err instanceof Error ? (err.stack ?? err.message) : String(err);\n        process.stderr.write(\n          `[webmcp-local-relay] warn: skipped dynamic tool \"${tool.name}\" because its schema could not be compiled: ${details}\\n`\n        );\n      }\n    }\n  }\n\n  /**\n   * Registers a single dynamic tool and returns a removal handle.\n   */\n  private registerDynamicTool(tool: AggregatedTool): RegisteredTool {\n    // `AggregatedTool` has already passed the SDK's ToolSchema validation.\n    // JsonSchemaType's exact optional properties are structurally narrower\n    // than the protocol Tool type even though both describe JSON Schema.\n    const inputSchema = fromJsonSchema<Record<string, unknown>>(tool.inputSchema as JsonSchemaType);\n    const outputSchema = tool.outputSchema\n      ? fromJsonSchema(tool.outputSchema as JsonSchemaType)\n      : undefined;\n\n    return this.mcpServer.registerTool(\n      tool.name,\n      {\n        ...(tool.title !== undefined ? { title: tool.title } : {}),\n        description: this.dynamicToolDescription(tool),\n        inputSchema,\n        ...(outputSchema ? { outputSchema } : {}),\n        ...(tool.annotations ? { annotations: tool.annotations } : {}),\n        ...(tool.icons ? { icons: tool.icons } : {}),\n        ...(tool._meta ? { _meta: tool._meta } : {}),\n      },\n      async (args: Record<string, unknown>) => {\n        try {\n          return await this.bridge.invokeTool(tool.name, args);\n        } catch (err) {\n          const message = err instanceof Error ? err.message : String(err);\n          const details = err instanceof Error ? (err.stack ?? err.message) : String(err);\n          process.stderr.write(\n            `[webmcp-local-relay] error: dynamic tool \"${tool.name}\" invocation failed: ${details}\\n`\n          );\n          return {\n            content: [\n              {\n                type: 'text' as const,\n                text: `Failed to invoke relayed tool \"${tool.name}\": ${message}`,\n              },\n            ],\n            isError: true,\n          };\n        }\n      }\n    );\n  }\n\n  /**\n   * Builds a display description for relayed tools including source context.\n   * In client mode, source metadata is unavailable, so tools are labeled `[WebMCP relay]`.\n   */\n  private dynamicToolDescription(tool: AggregatedTool): string {\n    const source = tool.sources[0];\n    const sourceLabel = source\n      ? `[WebMCP ${source.tabId}${source.title ? ` • ${source.title}` : ''}]`\n      : '[WebMCP relay]';\n\n    return `${sourceLabel} ${tool.description ?? `Relayed tool ${tool.originalName}`}`;\n  }\n\n  /**\n   * Produces a stable signature for change detection of dynamic tool metadata.\n   *\n   * Deliberately excludes `sourceId` (which is a per-connection UUID that\n   * changes on every browser reconnect) so that a reconnecting tab with the\n   * same tools does not trigger a needless remove+re-register cycle.\n   */\n  private toolSignature(tool: AggregatedTool): string {\n    return JSON.stringify({\n      originalName: tool.originalName,\n      title: tool.title,\n      description: tool.description,\n      inputSchema: tool.inputSchema,\n      outputSchema: tool.outputSchema,\n      annotations: tool.annotations,\n      _meta: tool._meta,\n      icons: tool.icons,\n      source: tool.sources[0]\n        ? { tabId: tool.sources[0].tabId, title: tool.sources[0].title }\n        : undefined,\n    });\n  }\n}\n"],"mappings":"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"}