{"version":3,"file":"server-CJou5KHd.mjs","names":["sep","osSep","packageJson.version"],"sources":["../package.json","../src/auth.ts","../src/browser-rpc.ts","../src/http-options.ts","../src/jsx-preprocess.ts","../src/mcp-sessions.ts","../src/result.ts","../src/tool/output.ts","../src/tool/schema.ts","../src/tool/registration.ts","../src/server.ts"],"sourcesContent":["","export function bearerToken(header: string | undefined | null): string | null {\n  return header?.startsWith('Bearer ') ? header.slice('Bearer '.length) : null\n}\n\nexport function mcpRequestToken(\n  authorization: string | undefined | null,\n  headerToken: string | undefined | null\n): string | null {\n  return bearerToken(authorization) ?? headerToken ?? null\n}\n\nexport function isAuthorized(provided: string | null, expected: string | null): boolean {\n  return expected === null || provided === expected\n}\n","import { randomUUID } from 'node:crypto'\n\nimport type { WebSocket } from 'ws'\n\nimport type { RpcJsonObject } from '#mcp/json'\nimport type { PendingRequest } from '#mcp/rpc-types'\n\nconst RPC_TIMEOUT = 30_000\n\nconst APP_NOT_CONNECTED_MESSAGE =\n  'OpenPencil app is not connected. STOP and tell the user: \"The OpenPencil desktop app is not running, no document is open, or the desktop app is connected to a different MCP server. Please start OpenPencil, open a document, and try again.\" Do NOT attempt to start the app yourself or retry automatically.'\n\ntype BrowserRpcBridgeOptions = {\n  authToken: string | null\n  onConnectionChange: () => void\n}\n\ntype BrowserMessage = {\n  type: string\n  id?: string\n  token?: string\n  result?: unknown\n  error?: string\n  ok?: boolean\n}\n\nfunction stripEnvelope(msg: BrowserMessage): Record<string, unknown> {\n  const { type: _type, id: _id, ...body } = msg\n  return body\n}\n\nfunction responsePayload(result: unknown): Record<string, unknown> {\n  if (result && typeof result === 'object' && !Array.isArray(result)) {\n    return result as RpcJsonObject\n  }\n  return { result }\n}\n\nfunction sendJson(ws: WebSocket, body: Record<string, unknown>) {\n  if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(body))\n}\n\nexport function createBrowserRpcBridge({ authToken, onConnectionChange }: BrowserRpcBridgeOptions) {\n  const pending = new Map<string, PendingRequest>()\n  const clients = new Set<WebSocket>()\n  let browserWs: WebSocket | null = null\n  let browserToken: string | null = null\n  let browserRegistered = false\n\n  function currentRpcToken(): string | null {\n    return authToken ?? browserToken\n  }\n\n  function isConnected(): boolean {\n    return Boolean(browserWs && browserRegistered)\n  }\n\n  function rejectAllPending(reason: string) {\n    for (const [id, req] of pending) {\n      clearTimeout(req.timer)\n      req.reject(new Error(reason))\n      pending.delete(id)\n    }\n  }\n\n  function sendRegisterToken(ws: WebSocket) {\n    const token = currentRpcToken()\n    if (token) sendJson(ws, { type: 'register', token })\n  }\n\n  function broadcastRegisterToken() {\n    for (const client of clients) sendRegisterToken(client)\n  }\n\n  function handleConnection(ws: WebSocket) {\n    clients.add(ws)\n    sendRegisterToken(ws)\n  }\n\n  function sendRpc(body: Record<string, unknown>): Promise<unknown> {\n    return new Promise((resolve, reject) => {\n      if (!browserWs || browserWs.readyState !== browserWs.OPEN || !browserRegistered) {\n        reject(new Error(APP_NOT_CONNECTED_MESSAGE))\n        return\n      }\n      const id = randomUUID()\n      const timer = setTimeout(() => {\n        pending.delete(id)\n        reject(new Error('RPC timeout (30s)'))\n      }, RPC_TIMEOUT)\n      pending.set(id, { resolve, reject, timer })\n      browserWs.send(JSON.stringify({ type: 'request', id, ...body }))\n    })\n  }\n\n  async function handleClientRequest(ws: WebSocket, msg: BrowserMessage) {\n    if (!msg.id) return\n    try {\n      const result = await sendRpc(stripEnvelope(msg))\n      sendJson(ws, { type: 'response', id: msg.id, ok: true, ...responsePayload(result) })\n    } catch (e) {\n      sendJson(ws, {\n        type: 'response',\n        id: msg.id,\n        ok: false,\n        error: e instanceof Error ? e.message : String(e)\n      })\n    }\n  }\n\n  function registerBrowser(ws: WebSocket, token: string) {\n    if (authToken && token !== authToken) {\n      ws.close()\n      return\n    }\n    const previousBrowserWs = browserWs\n    browserWs = ws\n    browserToken = token\n    browserRegistered = true\n    if (previousBrowserWs && previousBrowserWs !== ws && previousBrowserWs.readyState === ws.OPEN) {\n      previousBrowserWs.close()\n      rejectAllPending('Browser reconnected')\n    }\n    onConnectionChange()\n    broadcastRegisterToken()\n  }\n\n  function handleBrowserResponse(msg: BrowserMessage, ws: WebSocket) {\n    if (!browserRegistered || browserWs !== ws || !msg.id) return\n    const req = pending.get(msg.id)\n    if (!req) return\n    pending.delete(msg.id)\n    clearTimeout(req.timer)\n    if (msg.ok === false) req.reject(new Error(msg.error ?? 'RPC failed'))\n    else req.resolve(stripEnvelope(msg))\n  }\n\n  function handleMessage(data: string, ws: WebSocket) {\n    let msg: BrowserMessage\n    try {\n      msg = JSON.parse(data) as BrowserMessage\n    } catch (e) {\n      console.warn('Malformed automation message:', e)\n      return\n    }\n\n    if (msg.type === 'register' && msg.token) {\n      registerBrowser(ws, msg.token)\n      return\n    }\n    if (msg.type === 'request') {\n      void handleClientRequest(ws, msg)\n      return\n    }\n    if (msg.type === 'response') handleBrowserResponse(msg, ws)\n  }\n\n  function handleClose(ws: WebSocket) {\n    clients.delete(ws)\n    if (browserWs !== ws) return\n    browserWs = null\n    browserToken = null\n    browserRegistered = false\n    rejectAllPending('Browser disconnected')\n    onConnectionChange()\n  }\n\n  function close() {\n    rejectAllPending('Server shutting down')\n    clients.clear()\n  }\n\n  return {\n    close,\n    currentRpcToken,\n    handleClose,\n    handleConnection,\n    handleMessage,\n    isConnected,\n    sendRpc\n  }\n}\n","export const MCP_CORS_METHODS = ['GET', 'POST', 'DELETE', 'OPTIONS']\n\nexport const MCP_CORS_HEADERS = [\n  'Content-Type',\n  'Authorization',\n  'x-mcp-token',\n  'mcp-session-id',\n  'Last-Event-ID',\n  'mcp-protocol-version'\n]\n\nexport const MCP_EXPOSED_HEADERS = ['mcp-session-id', 'mcp-protocol-version']\n","import { buildComponent, createElement, resolveToTree } from '@open-pencil/core/design-jsx'\n\nexport function preprocessRpc(body: Record<string, unknown>): Record<string, unknown> {\n  if (body.command !== 'tool') return body\n  const args = body.args as { name?: string; args?: Record<string, unknown> } | undefined\n  if (args?.name !== 'render' || !args.args?.jsx) return body\n  try {\n    const Component = buildComponent(args.args.jsx as string)\n    const element = createElement(Component, null)\n    const tree = resolveToTree(element)\n    return {\n      ...body,\n      args: { ...args, args: { ...args.args, jsx: undefined, tree } }\n    }\n  } catch (e) {\n    console.warn('JSX preprocessing failed, passing raw:', e instanceof Error ? e.message : e)\n    return body\n  }\n}\n","import { randomUUID } from 'node:crypto'\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js'\n\nexport type MCPTransport = { handleRequest: (request: Request) => Promise<Response> }\n\ntype MCPSession = {\n  transport: MCPTransport\n  server: McpServer\n  lastSeen: number\n}\n\ntype McpSessionManagerOptions = {\n  serverVersion: string\n  registerTools: (server: McpServer) => void\n}\n\nconst MAX_MCP_SESSIONS = 10\nconst MCP_SESSION_TTL_MS = 15 * 60_000\n\nexport function createMcpSessionManager({\n  serverVersion,\n  registerTools\n}: McpSessionManagerOptions) {\n  const sessions = new Map<string, MCPSession>()\n\n  function notifyToolsChanged() {\n    for (const session of sessions.values()) {\n      try {\n        session.server.sendToolListChanged()\n      } catch {\n        continue\n      }\n    }\n  }\n\n  function cleanupExpired() {\n    const now = Date.now()\n    for (const [id, session] of sessions) {\n      if (now - session.lastSeen > MCP_SESSION_TTL_MS) {\n        sessions.delete(id)\n      }\n    }\n  }\n\n  function createSession(id: string): MCPTransport {\n    const server = new McpServer({ name: 'open-pencil', version: serverVersion })\n    registerTools(server)\n\n    const transport = new WebStandardStreamableHTTPServerTransport({\n      sessionIdGenerator: () => id\n    })\n    void server.connect(transport)\n    sessions.set(id, { transport, server, lastSeen: Date.now() })\n    return transport\n  }\n\n  function resolveTransport(sessionId: string | undefined): MCPTransport | { error: 'too_many' } {\n    cleanupExpired()\n    const existing = sessionId ? sessions.get(sessionId) : undefined\n    if (!existing && sessions.size >= MAX_MCP_SESSIONS) {\n      return { error: 'too_many' }\n    }\n    return existing?.transport ?? createSession(sessionId ?? randomUUID())\n  }\n\n  function touch(sessionId: string | undefined, transport: MCPTransport) {\n    const resolvedSessionId =\n      sessionId ?? [...sessions.entries()].find(([, entry]) => entry.transport === transport)?.[0]\n    if (!resolvedSessionId) return\n    const session = sessions.get(resolvedSessionId)\n    if (session) session.lastSeen = Date.now()\n  }\n\n  function deleteSession(sessionId: string | undefined) {\n    if (sessionId) sessions.delete(sessionId)\n  }\n\n  function clear() {\n    sessions.clear()\n  }\n\n  return { clear, deleteSession, notifyToolsChanged, resolveTransport, touch }\n}\n","export type MCPContent =\n  | { type: 'text'; text: string }\n  | { type: 'image'; data: string; mimeType: string }\n\nexport type MCPResult = { content: MCPContent[]; isError?: boolean }\n\nexport function ok(data: unknown): MCPResult {\n  return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }\n}\n\nexport function fail(e: unknown): MCPResult {\n  const msg = e instanceof Error ? e.message : String(e)\n  return { content: [{ type: 'text', text: JSON.stringify({ error: msg }) }], isError: true }\n}\n","import { mkdir, writeFile } from 'node:fs/promises'\nimport { dirname, resolve, sep as osSep } from 'node:path'\n\nimport { ok } from '#mcp/result'\nimport type { MCPResult } from '#mcp/result'\n\nexport function resolveSafePath(filePath: string, root: string): string {\n  const resolved = resolve(filePath)\n  const sep = root.endsWith('/') || root.endsWith('\\\\') ? '' : osSep\n  if (!resolved.startsWith(root + sep) && resolved !== root) {\n    throw new Error(`Path is outside the allowed root: ${root}`)\n  }\n  return resolved\n}\n\nexport async function writeToolOutput(\n  toolName: string,\n  result: Record<string, unknown>,\n  filePath: string,\n  root: string\n): Promise<MCPResult | null> {\n  const resolved = resolveSafePath(filePath, root)\n  await mkdir(dirname(resolved), { recursive: true })\n  if (toolName === 'export_svg' && typeof result.svg === 'string') {\n    await writeFile(resolved, result.svg, 'utf8')\n    return ok({ written: resolved, byteLength: Buffer.byteLength(result.svg, 'utf8') })\n  }\n  if (toolName === 'export_image' && typeof result.base64 === 'string') {\n    await writeFile(resolved, Buffer.from(result.base64, 'base64'))\n    return ok({ written: resolved, byteLength: result.byteLength ?? null })\n  }\n  if (toolName === 'get_jsx' && typeof result.jsx === 'string') {\n    await writeFile(resolved, result.jsx, 'utf8')\n    return ok({ written: resolved, byteLength: Buffer.byteLength(result.jsx, 'utf8') })\n  }\n  return null\n}\n","import { z } from 'zod'\n\nimport type { ParamDef, ParamType } from '@open-pencil/core/tools'\n\nexport function paramToZod(param: ParamDef): z.ZodType {\n  const typeMap: Record<ParamType, () => z.ZodType> = {\n    string: () =>\n      param.enum\n        ? z.enum(param.enum as [string, ...string[]]).describe(param.description)\n        : z.string().describe(param.description),\n    number: () => {\n      let schema = z.coerce.number()\n      if (param.min !== undefined) schema = schema.min(param.min)\n      if (param.max !== undefined) schema = schema.max(param.max)\n      return schema.describe(param.description)\n    },\n    boolean: () => z.boolean().describe(param.description),\n    color: () => z.string().describe(param.description),\n    'string[]': () => z.array(z.string()).min(1).describe(param.description)\n  }\n\n  const schema = typeMap[param.type]()\n  return param.required ? schema : schema.optional()\n}\n","import { resolve } from 'node:path'\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\n\nimport { ALL_TOOLS, CODEGEN_PROMPT } from '@open-pencil/core/tools'\n\nimport type { RpcJsonObject } from '#mcp/json'\nimport { fail, ok } from '#mcp/result'\n\nimport { resolveSafePath, writeToolOutput } from './output'\nimport { paramToZod } from './schema'\n\nexport type RpcSender = (body: Record<string, unknown>) => Promise<unknown>\n\nexport interface RegisterToolsOptions {\n  enableEval: boolean\n  mcpRoot?: string | null\n  sendRpc: RpcSender\n}\n\nexport function registerTools(mcpServer: McpServer, options: RegisterToolsOptions) {\n  const { enableEval, sendRpc } = options\n  const resolvedRoot = options.mcpRoot ? resolve(options.mcpRoot) : null\n  const register = mcpServer.registerTool.bind(mcpServer) as (...a: unknown[]) => void\n\n  for (const def of ALL_TOOLS) {\n    if (!enableEval && def.name === 'eval') continue\n    const shape: Record<string, z.ZodType> = {}\n    for (const [key, param] of Object.entries(def.params)) {\n      shape[key] = paramToZod(param)\n    }\n    register(\n      def.name,\n      { description: def.description, inputSchema: z.object(shape) },\n      async (args: Record<string, unknown>) => {\n        try {\n          const result = await sendRpc({ command: 'tool', args: { name: def.name, args } })\n          const res = result as { ok?: boolean; result?: unknown; error?: string }\n          if (res.ok === false) return fail(new Error(res.error))\n          const r = res.result as RpcJsonObject | undefined\n          const filePath = typeof args.path === 'string' ? args.path : null\n          if (r && filePath && resolvedRoot) {\n            const written = await writeToolOutput(def.name, r, filePath, resolvedRoot)\n            if (written) return written\n          }\n          if (r && 'base64' in r && 'mimeType' in r) {\n            return {\n              content: [\n                {\n                  type: 'image' as const,\n                  data: r.base64 as string,\n                  mimeType: r.mimeType as string\n                }\n              ]\n            }\n          }\n          return ok(r)\n        } catch (e) {\n          return fail(e)\n        }\n      }\n    )\n  }\n\n  register(\n    'save_file',\n    {\n      description: resolvedRoot\n        ? `Save the current document to disk. If path is provided, it must be inside ${resolvedRoot}.`\n        : 'Save the current document to disk. Uses the existing file path if available, otherwise prompts for a location.',\n      inputSchema: resolvedRoot\n        ? z.object({\n            path: z.string().describe('Optional absolute path for the .fig file').optional()\n          })\n        : z.object({})\n    },\n    async (args: { path?: string }) => {\n      try {\n        const safePath =\n          args.path && resolvedRoot ? resolveSafePath(args.path, resolvedRoot) : undefined\n        const result = await sendRpc({ command: 'save_file', args: { path: safePath } })\n        const res = result as { ok?: boolean; error?: string }\n        if (res.ok === false) return fail(new Error(res.error))\n        return ok({ saved: true, ...(safePath ? { path: safePath } : {}) })\n      } catch (e) {\n        return fail(e)\n      }\n    }\n  )\n\n  if (resolvedRoot) {\n    register(\n      'open_file',\n      {\n        description: `Open a .fig or .pen file from disk into a new tab. Path must be inside ${resolvedRoot}.`,\n        inputSchema: z.object({\n          path: z.string().describe('Absolute path to the design file')\n        })\n      },\n      async (args: { path: string }) => {\n        try {\n          const safe = resolveSafePath(args.path, resolvedRoot)\n          const result = await sendRpc({ command: 'open_file', args: { path: safe } })\n          const res = result as { ok?: boolean; error?: string }\n          if (res.ok === false) return fail(new Error(res.error))\n          return ok({ opened: true })\n        } catch (e) {\n          return fail(e)\n        }\n      }\n    )\n\n    register(\n      'new_document',\n      {\n        description: `Create a new empty document. Optionally set a save path inside ${resolvedRoot}.`,\n        inputSchema: z.object({\n          path: z.string().describe('Optional absolute path for the new file').optional()\n        })\n      },\n      async (args: { path?: string }) => {\n        try {\n          const safePath = args.path ? resolveSafePath(args.path, resolvedRoot) : undefined\n          const result = await sendRpc({ command: 'new_document', args: { path: safePath } })\n          const res = result as { ok?: boolean; error?: string }\n          if (res.ok === false) return fail(new Error(res.error))\n          return ok({ created: true })\n        } catch (e) {\n          return fail(e)\n        }\n      }\n    )\n  }\n\n  register(\n    'get_codegen_prompt',\n    {\n      description:\n        'Get design-to-code generation guidelines. Call before generating frontend code.',\n      inputSchema: z.object({})\n    },\n    async () => ok({ prompt: CODEGEN_PROMPT })\n  )\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { Hono } from 'hono'\nimport { cors } from 'hono/cors'\nimport { resolveCommand } from 'package-manager-detector/commands'\nimport { detect, getUserAgent } from 'package-manager-detector/detect'\nimport { WebSocketServer } from 'ws'\n\nimport type { RpcJsonObject } from '#mcp/json'\n\nimport packageJson from '../package.json' with { type: 'json' }\nimport { bearerToken, isAuthorized, mcpRequestToken } from './auth'\nimport { createBrowserRpcBridge } from './browser-rpc'\nimport { MCP_CORS_HEADERS, MCP_CORS_METHODS, MCP_EXPOSED_HEADERS } from './http-options'\nimport { preprocessRpc } from './jsx-preprocess'\nimport { createMcpSessionManager } from './mcp-sessions'\nimport { registerTools } from './tool/registration'\n\nexport const MCP_VERSION: string = packageJson.version\n\nlet installCommandPromise: Promise<string> | null = null\n\nasync function resolveMcpInstallCommand(): Promise<string> {\n  const agent =\n    getUserAgent() ??\n    (\n      await detect({\n        strategies: ['install-metadata', 'lockfile', 'packageManager-field', 'devEngines-field']\n      })\n    )?.agent ??\n    'npm'\n  const resolved = resolveCommand(agent, 'global', [`@open-pencil/mcp@${MCP_VERSION}`])\n  if (!resolved) return `npm install -g @open-pencil/mcp@${MCP_VERSION}`\n  return [resolved.command, ...resolved.args].join(' ')\n}\n\nfunction mcpInstallCommand(): Promise<string> {\n  installCommandPromise ??= resolveMcpInstallCommand()\n  return installCommandPromise\n}\n\nexport { fail, ok, type MCPContent, type MCPResult } from './result'\n\nexport { registerTools, type RegisterToolsOptions, type RpcSender } from './tool/registration'\nexport { paramToZod } from './tool/schema'\n\nexport interface ServerOptions {\n  httpPort?: number\n  wsPort?: number\n  enableEval?: boolean\n  mcpRoot?: string | null\n  authToken?: string | null\n  corsOrigin?: string | null\n}\n\nexport function startServer(options: ServerOptions = {}) {\n  const httpPort = options.httpPort ?? 7600\n  const wsPort = options.wsPort ?? 7601\n  const enableEval = options.enableEval ?? false\n  const mcpRoot = options.mcpRoot ?? null\n  const authToken = options.authToken ?? null\n  const corsOrigin = options.corsOrigin ?? null\n\n  const mcpSessions = createMcpSessionManager({\n    serverVersion: MCP_VERSION,\n    registerTools: (mcpServer: McpServer) =>\n      registerTools(mcpServer, { enableEval, mcpRoot, sendRpc: sendToBrowser })\n  })\n  const browserRpc = createBrowserRpcBridge({\n    authToken,\n    onConnectionChange: mcpSessions.notifyToolsChanged\n  })\n  const sendToBrowser = browserRpc.sendRpc\n\n  // --- WebSocket: browser connects here ---\n\n  const wss = new WebSocketServer({ port: wsPort, host: '127.0.0.1' })\n\n  wss.on('connection', (ws) => {\n    browserRpc.handleConnection(ws)\n\n    ws.on('message', (raw) => {\n      const data = typeof raw === 'string' ? raw : Buffer.from(raw as Buffer).toString('utf-8')\n      browserRpc.handleMessage(data, ws)\n    })\n\n    ws.on('close', () => {\n      browserRpc.handleClose(ws)\n    })\n  })\n\n  // --- HTTP server ---\n\n  const app = new Hono()\n\n  if (corsOrigin) {\n    app.use(\n      '*',\n      cors({\n        origin: corsOrigin,\n        allowMethods: MCP_CORS_METHODS,\n        allowHeaders: MCP_CORS_HEADERS,\n        exposeHeaders: MCP_EXPOSED_HEADERS\n      })\n    )\n  }\n\n  app.get('/health', async (c) =>\n    c.json({\n      status: browserRpc.isConnected() ? 'ok' : 'no_app',\n      version: MCP_VERSION,\n      installCommand: await mcpInstallCommand(),\n      authRequired: authToken !== null,\n      ...(browserRpc.currentRpcToken() ? { token: browserRpc.currentRpcToken() } : {})\n    })\n  )\n\n  app.use('/rpc', async (c, next) => {\n    const rpcToken = browserRpc.currentRpcToken()\n    if (!browserRpc.isConnected() || !rpcToken) {\n      return c.json({ error: 'OpenPencil app is not connected. Is a document open?' }, 503)\n    }\n    const provided = bearerToken(c.req.header('authorization'))\n    if (!isAuthorized(provided, rpcToken)) {\n      return c.json({ error: 'Unauthorized' }, 401)\n    }\n    return next()\n  })\n\n  app.post('/rpc', async (c) => {\n    let body = await c.req.json().catch(() => null)\n    if (!body || typeof body !== 'object') {\n      return c.json({ error: 'Invalid request body' }, 400)\n    }\n    try {\n      body = preprocessRpc(body as RpcJsonObject)\n      const result = await sendToBrowser(body as RpcJsonObject)\n      return c.json(result)\n    } catch (e) {\n      const msg = e instanceof Error ? e.message : String(e)\n      return c.json({ ok: false, error: msg }, 502)\n    }\n  })\n\n  // --- MCP Streamable HTTP ---\n\n  app.all('/mcp', async (c) => {\n    if (authToken) {\n      const token = mcpRequestToken(c.req.header('authorization'), c.req.header('x-mcp-token'))\n      if (!isAuthorized(token, authToken)) {\n        return c.json({ error: 'Unauthorized' }, 401)\n      }\n    }\n    const sessionId = c.req.header('mcp-session-id') ?? undefined\n    const transport = mcpSessions.resolveTransport(sessionId)\n    if ('error' in transport) {\n      return c.json(\n        { error: 'Too many active MCP sessions' },\n        { status: 503, headers: { 'Retry-After': '5' } }\n      )\n    }\n    mcpSessions.touch(sessionId, transport)\n    const response = await transport.handleRequest(c.req.raw)\n    if (c.req.method === 'DELETE') {\n      mcpSessions.deleteSession(sessionId)\n    }\n    return response\n  })\n\n  function close() {\n    browserRpc.close()\n    mcpSessions.clear()\n    wss.close()\n  }\n\n  return { app, wss, httpPort, close }\n}\n"],"mappings":"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"}