{"version":3,"file":"mcpCommand-BaJXXphd.mjs","names":[],"sources":["../src/constants/piMcp.ts","../src/services/directTools/index.ts","../src/services/directToolsEnvironment/index.ts","../src/services/mcpTools/index.ts","../src/services/toolVisibility/index.ts","../src/services/mcpSession/index.ts","../src/types/webMcp.ts","../src/constants/mcp.ts","../src/schemas/mcpHeadlessTool.ts","../src/services/mcpSessionTools/index.ts","../src/services/mcpCommand/index.ts"],"sourcesContent":["export const PACKAGE_SOURCE = '@agimon-ai/doompi-mcp';\n/** Leader binding ids are restricted to `[a-z0-9][a-z0-9._:-]*`, so the scope and slash are dropped. */\nexport const LEADER_BINDING_PREFIX = 'doom-mcp';\n/**\n * Sits under the existing `extension` group, beside `tools` and `config`.\n *\n * A top-level key would have to be unique across every extension, and MCP belongs\n * next to the tool browser a user reaches for anyway. `t` in particular is taken:\n * it is Doom Task's top-level group.\n */\nexport const LEADER_GROUP = { key: 'e', label: 'extension', detail: 'tools, skills and config', order: 50 } as const;\nexport const LEADER_KEY = 'm';\nexport const LEADER_LABEL = 'mcp';\nexport const LEADER_DETAIL = 'servers and tools';\n/**\n * Footer status carrying the session's MCP server names, comma separated.\n *\n * MCP tools are registered under `<server>_<tool>`, a name only known at\n * runtime, so the cockpit's web plugin reads this status to recognise which\n * tool calls are MCP calls. The web half duplicates the literal (it may only\n * import src/types and src/constants), and a test keeps the two in step.\n */\nexport const MCP_STATUS_KEY = 'doom-mcp';\n","const SELECTOR_SEPARATOR = '/';\n\n/**\n * Which downstream tools a child may see.\n *\n * A selector is either a whole server (`pencil`) or one tool of it\n * (`pencil/get_screenshot`).\n */\nexport class DirectToolFilter {\n  private readonly servers = new Set<string>();\n  private readonly tools = new Map<string, Set<string>>();\n\n  constructor(selectors: readonly string[]) {\n    for (const raw of selectors) {\n      const selector = raw.trim().replace(/\\/+$/, '');\n      if (!selector) continue;\n      const separator = selector.indexOf(SELECTOR_SEPARATOR);\n      if (separator === -1) {\n        this.servers.add(selector);\n        continue;\n      }\n      const server = selector.slice(0, separator);\n      const tool = selector.slice(separator + 1);\n      if (!server) continue;\n      if (!tool) {\n        this.servers.add(server);\n        continue;\n      }\n      const selected = this.tools.get(server) ?? new Set<string>();\n      selected.add(tool);\n      this.tools.set(server, selected);\n    }\n  }\n\n  allows(serverName: string, toolName: string): boolean {\n    if (this.servers.has(serverName)) return true;\n    return this.tools.get(serverName)?.has(toolName) ?? false;\n  }\n}\n","import { DIRECT_TOOLS_ENV, NO_DIRECT_TOOLS } from '../../schemas/directTools';\nimport { DirectToolFilter } from '../directTools';\n\n/** Reads a child agent's MCP tool selection from the process environment. */\nexport function readDirectToolFilter(environment: NodeJS.ProcessEnv = process.env): DirectToolFilter | undefined {\n  const raw = environment[DIRECT_TOOLS_ENV];\n  if (raw === undefined || raw === '') return undefined;\n  if (raw === NO_DIRECT_TOOLS) return new DirectToolFilter([]);\n  return new DirectToolFilter(raw.split(','));\n}\n","import type { DoomHeadlessToolResult } from '@agimon-ai/doompi-core/headless';\nimport { definePiTool, type PiToolDeclaration } from '@agimon-ai/doompi-core/piExtension';\nimport type { McpClientManagerService } from '@agimon-ai/mcp-proxy';\nimport type { AgentToolResult, ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { TSchema } from 'typebox';\n\nimport type { CatalogTool } from '../../services/mcpCatalog';\nimport type { McpResultBlock, McpToolDetails } from '../../types/webMcp';\n\n/** Pi requires a schema; a downstream tool that declares none takes any object. */\nconst ANY_OBJECT_SCHEMA = { type: 'object', properties: {} };\n\ntype ContentBlock = CallToolResult['content'][number];\n\n/** The text of a downstream result: its text blocks joined, which is what the model reads. */\nfunction resultText(result: Pick<CallToolResult, 'content'>): string {\n  return (result.content ?? [])\n    .flatMap((block) => (block.type === 'text' ? [block.text] : []))\n    .join('\\n')\n    .trim();\n}\n\n/** The image blocks, re-emitted as Pi's own image content so the model and the cockpit both see them. */\nfunction resultImages(result: CallToolResult): AgentToolResult<McpToolDetails>['content'] {\n  return (result.content ?? []).flatMap((block: ContentBlock) =>\n    block.type === 'image' ? [{ type: 'image' as const, data: block.data, mimeType: block.mimeType }] : [],\n  );\n}\n\n/**\n * Everything else a downstream result carried: audio, resource links, embedded\n * resources, and the structured content. Pi's content cannot hold them, so\n * they ride the result's details for the cockpit's MCP message to render.\n */\nfunction resultBlocks(result: CallToolResult): McpResultBlock[] {\n  const blocks: McpResultBlock[] = [];\n  for (const block of result.content ?? []) {\n    if (block.type === 'audio') blocks.push({ type: 'audio', data: block.data, mimeType: block.mimeType });\n    else if (block.type === 'resource_link') {\n      blocks.push({\n        type: 'resource_link',\n        uri: block.uri,\n        name: block.name,\n        ...(block.title === undefined ? {} : { title: block.title }),\n        ...(block.description === undefined ? {} : { description: block.description }),\n        ...(block.mimeType === undefined ? {} : { mimeType: block.mimeType }),\n      });\n    } else if (block.type === 'resource') {\n      const resource = block.resource;\n      blocks.push({\n        type: 'resource',\n        uri: resource.uri,\n        ...(resource.mimeType === undefined ? {} : { mimeType: resource.mimeType }),\n        ...('text' in resource && typeof resource.text === 'string' ? { text: resource.text } : {}),\n        ...('blob' in resource && typeof resource.blob === 'string' ? { blob: resource.blob } : {}),\n      });\n    }\n  }\n  if (typeof result.structuredContent === 'object' && result.structuredContent !== null) {\n    blocks.push({ type: 'structured', value: result.structuredContent });\n  }\n  return blocks;\n}\n\n/**\n * Turns a downstream result into a Pi tool result.\n *\n * `isError` is raised rather than returned: Pi shows a thrown message as a failed\n * call, and returning the text would present a server-side error as a success.\n * The text is what the model reads; images join it as Pi content, and every\n * other block kind reaches the cockpit through the details.\n */\nexport function toAgentToolResult(tool: CatalogTool, result: CallToolResult): AgentToolResult<McpToolDetails> {\n  const normalized = toHeadlessToolResult(tool, result);\n  if (normalized.isError) throw new Error(resultText(normalized));\n  return normalized;\n}\n\n/** Remote MCP preserves error flags and public structured results instead of Pi's thrown-error convention. */\nexport function toHeadlessToolResult(\n  tool: CatalogTool,\n  result: CallToolResult,\n): DoomHeadlessToolResult & { details: McpToolDetails } {\n  const text =\n    resultText(result) ||\n    (result.structuredContent === undefined ? 'No output.' : JSON.stringify(result.structuredContent));\n  const blocks = resultBlocks(result);\n  return {\n    content: [{ type: 'text', text }, ...resultImages(result)],\n    ...(result.structuredContent === undefined ? {} : { structuredContent: result.structuredContent }),\n    ...(result.isError === undefined ? {} : { isError: result.isError }),\n    details: { server: tool.serverName, tool: tool.toolName, ...(blocks.length > 0 ? { blocks } : {}) },\n  };\n}\n\n/**\n * Supplies the live client manager, or nothing before the runtime has started.\n *\n * A getter rather than the manager itself: tools are registered from the cached\n * catalog before any container exists, and the same registration has to reach\n * whichever container is live when the tool is finally called.\n */\nexport type McpToolRenderers = Pick<ToolDefinition<TSchema, McpToolDetails>, 'renderCall' | 'renderResult'>;\n\nexport type ClientManagerSource = () => McpClientManagerService | undefined;\nexport type McpToolAvailability = (tool: CatalogTool) => boolean;\n\nconst ALWAYS_AVAILABLE: McpToolAvailability = () => true;\n\n/**\n * Registers one downstream tool with Pi.\n *\n * Registration is permanent for the session: Pi 0.84 has no `unregisterTool`, so\n * visibility is controlled through a tool-surface restriction instead. The connection is\n * resolved at execution time rather than captured, so a server that reconnects\n * underneath keeps working.\n */\nexport function createMcpTool(\n  clientManagerSource: ClientManagerSource,\n  tool: CatalogTool,\n  isAvailable: McpToolAvailability = ALWAYS_AVAILABLE,\n  renderers: McpToolRenderers = {},\n): PiToolDeclaration {\n  return definePiTool({\n    name: tool.piName,\n    label: `${tool.serverName}: ${tool.toolName}`,\n    description: tool.description ?? `${tool.toolName} on the ${tool.serverName} MCP server.`,\n    // The schema arrives as JSON Schema at runtime, so it is wrapped rather than\n    // built: TypeBox validates the shape without it having to be declared here.\n    // Type.Unsafe only brands this runtime JSON Schema object. A type cast keeps\n    // cached stub registration from evaluating the whole TypeBox package.\n    parameters: (Object.keys(tool.inputSchema).length > 0 ? tool.inputSchema : ANY_OBJECT_SCHEMA) as TSchema,\n    renderShell: 'self',\n    ...renderers,\n    async execute(_toolCallId, params) {\n      if (!isAvailable(tool)) {\n        throw new Error(`MCP tool ${tool.piName} is not available in the current session configuration.`);\n      }\n      const clientManager = clientManagerSource();\n      if (!clientManager) {\n        throw new Error(`The MCP runtime is not ready, so ${tool.serverName} cannot be reached yet.`);\n      }\n      const connection = await clientManager.ensureConnected(tool.serverName);\n      const timeout = clientManager.getServerRequestTimeout(tool.serverName);\n      const result = await connection.callTool(\n        tool.toolName,\n        (params ?? {}) as Record<string, unknown>,\n        timeout === undefined ? undefined : { timeout },\n      );\n      return toAgentToolResult(tool, result);\n    },\n  });\n}\n","import type { DoomToolRestriction } from '@agimon-ai/doompi-core/toolSurface';\n\nimport type { McpCatalog } from '../mcpCatalog';\n/**\n * Hides every wrapper this extension owns that the catalog does not currently offer.\n *\n * The surface recomputes from the whole registered inventory, so this only ever\n * removes: a server that reconnected is already in `incoming` and nothing has to\n * put it back. Historical ownership matters after reconfiguration because Pi\n * cannot unregister a wrapper the new domain no longer selects.\n *\n * The visible set is read once, here, so the returned function stays pure and a\n * later re-apply by another owner cannot see half a catalog change.\n */\nexport function mcpToolRestriction(\n  catalog: McpCatalog,\n  historicallyOwnedNames: ReadonlySet<string> = new Set(catalog.allTools().map((tool) => tool.piName)),\n  incompatibleNames: ReadonlySet<string> = new Set(),\n): DoomToolRestriction {\n  const visible = new Set(catalog.activeToolNames().filter((name) => !incompatibleNames.has(name)));\n  return (incoming) => incoming.filter((name) => !historicallyOwnedNames.has(name) || visible.has(name));\n}\n","import type { McpStatusSnapshot } from '@agimon-ai/doompi-core/mcpStatus';\nimport type { DoomMcpResolvedToolSelection } from '@agimon-ai/doompi-core/mcpToolResolver';\nimport type {\n  DoomToolRestriction,\n  DoomToolRestrictionHandle,\n  DoomToolSurfaceService,\n} from '@agimon-ai/doompi-core/toolSurface';\nimport type { McpClientManagerService, McpServerStateChange, TokenStore } from '@agimon-ai/mcp-proxy';\n\nimport { PACKAGE_SOURCE } from '../../constants/piMcp';\nimport type { McpResourceView, McpServerView } from '../../types/mcp';\nimport type { McpConfigGroups, McpConfigSource, McpSessionConfig } from '../../types/mcpConfig';\nimport { buildMcpConfigGroups } from '../configSources';\nimport { readDirectToolFilter } from '../directToolsEnvironment';\nimport { type CatalogTool, McpCatalog } from '../mcpCatalog';\nimport { type McpRuntimeOwner, readCachedCatalog } from '../mcpRuntime';\nimport { toHeadlessToolResult } from '../mcpTools';\nimport { readSessionConfig } from '../sessionConfig';\nimport { mcpToolRestriction } from '../toolVisibility';\n\n/** Raised by anything needing a live container before one has been built. */\nconst RUNTIME_NOT_STARTED = 'The MCP runtime has not started yet.';\nconst AUTHORIZATION_URL_NOT_READY = 'No authorization page is waiting for this MCP server.';\n\nfunction canonicalJson(value: unknown): string {\n  const normalize = (candidate: unknown): unknown => {\n    if (Array.isArray(candidate)) return candidate.map(normalize);\n    if (typeof candidate !== 'object' || candidate === null) return candidate;\n    return Object.fromEntries(\n      Object.entries(candidate as Record<string, unknown>)\n        .sort(([left], [right]) => left.localeCompare(right))\n        .map(([key, child]) => [key, normalize(child)]),\n    );\n  };\n  return JSON.stringify(normalize(value));\n}\n\nexport function mcpConfigurationFingerprint(configuration: McpSessionConfig): string {\n  return canonicalJson({\n    enabled: configuration.enabled ?? true,\n    repoRoot: configuration.repoRoot,\n    stagingDirectory: configuration.stagingDirectory,\n    generatedConfigPath: configuration.generatedConfigPath,\n    pluginConfigPaths: configuration.pluginConfigPaths ?? [],\n    sources: configuration.sources ?? [],\n    allowlist: {\n      servers: [...(configuration.allowlist?.servers ?? [])].sort((left, right) => left.localeCompare(right)),\n      proxy: [...(configuration.allowlist?.proxy ?? [])].sort((left, right) => left.localeCompare(right)),\n    },\n  });\n}\n\nfunction toolRegistrationFingerprint(tool: CatalogTool): string {\n  return canonicalJson({\n    serverName: tool.serverName,\n    toolName: tool.toolName,\n    inputSchema: tool.inputSchema,\n  });\n}\n\nexport interface McpSessionOptions {\n  environment?: NodeJS.ProcessEnv;\n  /** Surfaces an OAuth URL, opening it when an explicit authorization requested that. */\n  onAuthorizationUrl?: (url: URL, serverName: string, options: { openBrowser: boolean }) => void | Promise<void>;\n  /** Overrides the OS keyring store, for tests. */\n  tokenStore?: TokenStore;\n}\n\n/**\n * The MCP picture for one Pi session.\n *\n * Install is synchronous and cheap: the previous run's catalog is read off disk and\n * its tools registered, so Pi's first turn already has them. Connecting happens on\n * a detached promise afterwards, and each server folds into the active tool set as\n * it lands. Nothing on this path waits for a socket.\n */\nexport class McpSession {\n  /** Created after session_start, never while Pi is importing extensions. */\n  private runtime: McpRuntimeOwner | undefined;\n  private catalog: McpCatalog;\n  private groups: McpConfigGroups = {\n    shared: { configSources: [], configPaths: [], serverNames: [] },\n    sessionLocal: { configSources: [], configPaths: [], serverNames: [] },\n    droppedServers: [],\n    diagnostics: [],\n  };\n  private readonly options: McpSessionOptions;\n  /** Credential persistence used by the active runtime and explicit reauthorization. */\n  private tokenStore: TokenStore | undefined;\n  /** Resources per server, listed on demand. Errors are never cached, so a retry re-dials. */\n  private readonly resourceCache = new Map<string, readonly McpResourceView[]>();\n  private readonly changeListeners = new Set<() => void>();\n  /** Authorization URLs waiting to be opened, by server. */\n  private readonly authorizationUrls = new Map<string, string>();\n  /** Servers whose explicit auth action should launch the browser when its URL arrives. */\n  private readonly browserAuthorizationRequests = new Set<string>();\n  /** Explicit session disconnects fence late discovery and stale tool invocations. */\n  private readonly disconnectedServers = new Set<string>();\n  /** Invalidates deferred startup work when a session reloads or shuts down. */\n  private lifecycleGeneration = 0;\n  private configurationFingerprint: string | undefined;\n  private workspaceRoot: string | undefined;\n  private executionCwd: string | undefined;\n  /** Pi wrappers survive configuration changes because the host cannot unregister them. */\n  private readonly retainedTools = new Map<string, CatalogTool>();\n  private readonly registeredToolFingerprints = new Map<string, string>();\n  private readonly historicallyOwnedNames = new Set<string>();\n  private readonly incompatibleNames = new Set<string>();\n  /** The session's slot in the tool surface, held only while a session fiber is up. */\n  private toolRestriction: DoomToolRestrictionHandle | undefined;\n\n  /** Resolved per tool call, so a registration outlives the container it was made under. */\n  readonly getClientManager = (): McpClientManagerService | undefined => this.runtime?.getServices()?.clientManager;\n\n  constructor(options: McpSessionOptions) {\n    this.options = options;\n    this.catalog = this.createCatalog();\n  }\n\n  /**\n   * Puts this session's tool visibility under the Doom tool surface.\n   *\n   * Registering applies the current restriction immediately, which is the first\n   * point the session can express that nothing has connected yet: the surface\n   * only exists once a session fiber is up, while the cached tools were\n   * registered back at install. Dropping the handle restores every wrapper, so\n   * nothing here keeps a snapshot of the tool list.\n   */\n  bindToolSurface(surface: DoomToolSurfaceService): () => void {\n    const handle = surface.register({ source: PACKAGE_SOURCE, restrict: this.currentRestriction() });\n    this.toolRestriction = handle;\n    return () => {\n      if (this.toolRestriction !== handle) return;\n      this.toolRestriction = undefined;\n      handle.dispose();\n    };\n  }\n\n  private createCatalog(): McpCatalog {\n    return new McpCatalog(readDirectToolFilter(this.options.environment));\n  }\n\n  /**\n   * Registers the cached catalog with Pi. Runs at extension install.\n   *\n   * Returns the servers it seeded, so a caller can report what the session started\n   * with before anything connected.\n   */\n  install(configuration: McpSessionConfig = readSessionConfig(this.options.environment)): McpStatusSnapshot {\n    this.executionCwd = configuration.repoRoot;\n    this.bindConfiguration(configuration);\n    this.emitChange();\n    return this.catalog.toSnapshot();\n  }\n\n  /** Replaces the complete MCP projection and retires the previous live owner. */\n  async reconfigure(\n    configuration: McpSessionConfig,\n    executionCwd = configuration.repoRoot,\n    workspaceRoot = configuration.repoRoot,\n  ): Promise<void> {\n    const fingerprint = mcpConfigurationFingerprint(configuration);\n    if (\n      fingerprint === this.configurationFingerprint &&\n      executionCwd === this.executionCwd &&\n      workspaceRoot === this.workspaceRoot\n    ) {\n      if (!this.runtime?.getServices()) this.startDetached();\n      return;\n    }\n\n    const generation = ++this.lifecycleGeneration;\n    const retiredRuntime = this.runtime;\n    this.runtime = undefined;\n    await retiredRuntime?.dispose();\n    if (generation !== this.lifecycleGeneration) return;\n    this.resourceCache.clear();\n    this.authorizationUrls.clear();\n    this.browserAuthorizationRequests.clear();\n    this.executionCwd = executionCwd;\n    this.bindConfiguration(configuration);\n    this.workspaceRoot = workspaceRoot;\n    this.emitChange();\n    this.updateToolVisibility();\n    this.startDetached();\n  }\n\n  private bindConfiguration(configuration: McpSessionConfig): void {\n    this.workspaceRoot = configuration.repoRoot;\n    this.configurationFingerprint = mcpConfigurationFingerprint(configuration);\n    this.groups = buildMcpConfigGroups(configuration);\n    this.disconnectedServers.clear();\n    this.catalog = this.createCatalog();\n    // Doom embeds the client runtime, so upstreams referenced by a proxy wrapper\n    // remain individual servers in the catalog rather than collapsing into it.\n    const configuredServers = [\n      ...new Set([...this.groups.sessionLocal.serverNames, ...this.groups.shared.serverNames]),\n    ];\n    this.catalog.seed(readCachedCatalog(this.configSources()), configuredServers);\n    for (const diagnostic of this.groups.diagnostics) this.catalog.addDiagnostic(diagnostic);\n    this.trackTools(this.catalog.allTools());\n  }\n\n  private trackTools(tools: readonly CatalogTool[]): void {\n    for (const tool of tools) {\n      const fingerprint = toolRegistrationFingerprint(tool);\n      const registered = this.registeredToolFingerprints.get(tool.piName);\n      this.historicallyOwnedNames.add(tool.piName);\n      if (registered === undefined) {\n        this.registeredToolFingerprints.set(tool.piName, fingerprint);\n        this.incompatibleNames.delete(tool.piName);\n        this.retainedTools.set(tool.piName, tool);\n        continue;\n      }\n      if (registered === fingerprint) {\n        this.incompatibleNames.delete(tool.piName);\n        continue;\n      }\n      this.incompatibleNames.add(tool.piName);\n      this.catalog.addDiagnostic(\n        `MCP tool \"${tool.piName}\" changed identity or input schema and is hidden until Pi is relaunched.`,\n      );\n    }\n  }\n\n  /** Tools the session currently permits on both local and remote surfaces. */\n  activeToolDefinitions(): readonly CatalogTool[] {\n    const active = new Set(this.catalog.activeToolNames());\n    // Retain Pi's declaration identity while publishing current remote metadata.\n    return this.toolDefinitions().flatMap((tool) => {\n      const current = this.catalog.findTool(tool.piName);\n      return active.has(tool.piName) && current !== undefined ? [current] : [];\n    });\n  }\n\n  toolDefinitions(): readonly CatalogTool[] {\n    return [...this.retainedTools.values()].filter(\n      (tool) =>\n        this.catalog.findTool(tool.piName) !== undefined &&\n        !this.incompatibleNames.has(tool.piName) &&\n        !this.disconnectedServers.has(tool.serverName),\n    );\n  }\n\n  isToolAvailable(registeredTool: CatalogTool): boolean {\n    if (!this.catalog.activeToolNames().includes(registeredTool.piName)) return false;\n    const current = this.catalog.findTool(registeredTool.piName);\n    return (\n      current !== undefined && toolRegistrationFingerprint(current) === toolRegistrationFingerprint(registeredTool)\n    );\n  }\n\n  /** Executes through this session's existing manager, never a remote replacement runtime. */\n  async invokeTool(\n    name: string,\n    parameters: Record<string, unknown>,\n    signal?: AbortSignal,\n  ): Promise<import('@agimon-ai/doompi-core/headless').DoomHeadlessToolResult> {\n    const tool = this.activeToolDefinitions().find((candidate) => candidate.piName === name);\n    if (!tool || !this.isToolAvailable(tool))\n      throw new Error(`MCP tool ${name} is not available in the current session configuration.`);\n    const runtime = this.runtime;\n    const services = runtime?.getServices();\n    if (!runtime || !services) throw new Error(RUNTIME_NOT_STARTED);\n    signal?.throwIfAborted();\n    const connection = await services.clientManager.ensureConnected(tool.serverName);\n    signal?.throwIfAborted();\n    if (!runtime.isCurrent(services) || !this.isToolAvailable(tool))\n      throw new Error(`MCP tool ${name} is no longer available in the current session configuration.`);\n    const timeout = services.clientManager.getServerRequestTimeout(tool.serverName);\n    const result = await connection.callTool(\n      tool.toolName,\n      parameters,\n      timeout === undefined ? undefined : { timeout },\n    );\n    return toHeadlessToolResult(tool, result);\n  }\n\n  /**\n   * What this extension hides right now.\n   *\n   * Rebuilt from scratch every time, so a server that failed drops out and one\n   * that reconnected comes back.\n   */\n  private currentRestriction(): DoomToolRestriction {\n    const unavailable = new Set(this.incompatibleNames);\n    for (const tool of this.catalog.allTools()) {\n      if (this.disconnectedServers.has(tool.serverName)) unavailable.add(tool.piName);\n    }\n    return mcpToolRestriction(this.catalog, this.historicallyOwnedNames, unavailable);\n  }\n\n  private updateToolVisibility(): void {\n    this.toolRestriction?.update(this.currentRestriction());\n  }\n\n  private startDetached(): void {\n    void this.start().catch((error: unknown) => {\n      this.catalog.addDiagnostic(\n        `Could not start the MCP runtime: ${error instanceof Error ? error.message : String(error)}`,\n      );\n      this.emitChange();\n    });\n  }\n\n  /**\n   * Starts connecting. Never awaited on Pi's critical path.\n   *\n   * Resolves once the container exists, not once servers are reachable. A start\n   * that a newer generation superseded resolves to nothing and registers nothing.\n   */\n  async start(): Promise<void> {\n    const generation = ++this.lifecycleGeneration;\n    this.disconnectedServers.clear();\n    // Explicit disabled and empty Doom projections must not instantiate any\n    // runtime collaborator, including the keyring-backed token store.\n    if (this.configuredServerNames().length === 0) return;\n    const [{ createTokenStore }, { McpRuntimeOwner }] = await Promise.all([\n      import('../keyringTokenStore'),\n      import('../mcpRuntime'),\n    ]);\n    if (generation !== this.lifecycleGeneration) return;\n    this.runtime ??= new McpRuntimeOwner();\n    const runtime = this.runtime;\n    // The container is about to be replaced, so every resource list read from the\n    // old one is now hearsay.\n    this.resourceCache.clear();\n    const configSources = this.configSources();\n    const tokenStore = this.options.tokenStore ?? (await createTokenStore());\n    this.tokenStore = tokenStore;\n    await runtime.start({\n      configSources,\n      workspaceRoot: this.workspaceRoot,\n      executionCwd: this.executionCwd,\n      environment: this.options.environment,\n      tokenStore,\n      onAuthorizationUrl: (url, serverName) => this.onAuthorizationUrl(url, serverName, generation),\n      onServerStateChange: (change) => this.onServerStateChange(change, generation),\n    });\n    // Shutdown can land while the proxy package or token store is loading. Make\n    // sure that late container cannot survive and mutate a closed Pi session.\n    if (generation !== this.lifecycleGeneration) await runtime.dispose();\n  }\n\n  /**\n   * Records the URL a flow is waiting on, then passes it to the host.\n   *\n   * Kept here as well as announced, because the announcement lands in the\n   * transcript and the panel a user starts the flow from covers it. Host work is\n   * detached so a failed desktop browser launch never cancels a still-usable OAuth\n   * callback; the overlay retains a clickable fallback and a retry action.\n   */\n  private onAuthorizationUrl(url: URL, serverName: string, generation: number): void {\n    if (generation !== this.lifecycleGeneration || this.disconnectedServers.has(serverName)) return;\n    this.authorizationUrls.set(serverName, url.toString());\n    this.emitChange();\n    const openBrowser = this.browserAuthorizationRequests.has(serverName);\n    void Promise.resolve()\n      .then(() => {\n        if (generation !== this.lifecycleGeneration || this.disconnectedServers.has(serverName)) return;\n        return this.options.onAuthorizationUrl?.(url, serverName, { openBrowser });\n      })\n      .catch((error: unknown) => {\n        if (generation !== this.lifecycleGeneration) return;\n        const detail = error instanceof Error ? error.message : String(error);\n        this.catalog.addDiagnostic(`Could not open authorization page for \"${serverName}\": ${detail}`);\n        this.emitChange();\n      });\n  }\n\n  /** Ordered layers for the one in-process client container. */\n  private configSources(): McpConfigSource[] {\n    return [...this.groups.sessionLocal.configSources, ...this.groups.shared.configSources];\n  }\n\n  private configuredServerNames(): string[] {\n    return [...new Set([...this.groups.sessionLocal.serverNames, ...this.groups.shared.serverNames])];\n  }\n\n  /** Closes only this session's connection. Saved OAuth credentials are untouched. */\n  async disconnect(serverName: string): Promise<void> {\n    if (!this.configuredServerNames().includes(serverName)) throw new Error(`Unknown MCP server: ${serverName}`);\n    const clientManager = this.getClientManager();\n    if (!clientManager) throw new Error(RUNTIME_NOT_STARTED);\n    const generation = this.lifecycleGeneration;\n    this.disconnectedServers.add(serverName);\n    try {\n      await clientManager.disconnectServer(serverName);\n    } catch (error) {\n      if (generation === this.lifecycleGeneration) this.disconnectedServers.delete(serverName);\n      throw error;\n    }\n    if (generation !== this.lifecycleGeneration) return;\n    this.resourceCache.delete(serverName);\n    this.authorizationUrls.delete(serverName);\n    this.browserAuthorizationRequests.delete(serverName);\n    this.catalog.applyStateChange({ serverName, state: 'closed' }, []);\n    this.emitChange();\n    this.updateToolVisibility();\n  }\n\n  /**\n   * Reconnects one server with a fresh OAuth registration.\n   *\n   * The connection is dropped before credentials are cleared so a failed disconnect\n   * does not silently sign the user out. Clearing both tokens and dynamic client\n   * information prevents a server-side registration reset from replaying a stale\n   * `client_id` forever.\n   */\n  async reauthorize(serverName: string): Promise<void> {\n    const clientManager = this.getClientManager();\n    if (!clientManager) throw new Error(RUNTIME_NOT_STARTED);\n    const generation = this.lifecycleGeneration;\n    const tokenStore = this.tokenStore;\n    this.disconnectedServers.delete(serverName);\n    // What this server offers is exactly what the reconnect is about to settle.\n    this.resourceCache.delete(serverName);\n    if (this.authorizationUrls.delete(serverName)) this.emitChange();\n    this.browserAuthorizationRequests.add(serverName);\n    try {\n      await clientManager.disconnectServer(serverName);\n      if (generation !== this.lifecycleGeneration) return;\n      await tokenStore?.clear(serverName);\n      if (generation !== this.lifecycleGeneration) return;\n      await clientManager.ensureConnected(serverName);\n    } finally {\n      if (generation === this.lifecycleGeneration) this.browserAuthorizationRequests.delete(serverName);\n    }\n  }\n\n  /** Reopens the URL already reserved for a flow without restarting that flow. */\n  async openAuthorizationPage(serverName: string): Promise<void> {\n    const authorizationUrl = this.authorizationUrls.get(serverName);\n    if (!authorizationUrl) throw new Error(AUTHORIZATION_URL_NOT_READY);\n    const onAuthorizationUrl = this.options.onAuthorizationUrl;\n    if (!onAuthorizationUrl) throw new Error('This host cannot open authorization pages.');\n    await onAuthorizationUrl(new URL(authorizationUrl), serverName, { openBrowser: true });\n  }\n\n  getSnapshot(): McpStatusSnapshot {\n    return this.catalog.toSnapshot();\n  }\n\n  resolveToolSelectors(selectors: readonly string[]): readonly DoomMcpResolvedToolSelection[] {\n    return this.catalog.resolveToolSelectors(selectors);\n  }\n\n  /** The fuller picture the overlay renders, with tool names and descriptions. */\n  getServers(): readonly McpServerView[] {\n    return this.catalog.toView().map((server) => {\n      const authorizationUrl = this.authorizationUrls.get(server.name);\n      return authorizationUrl ? { ...server, authorizationUrl } : server;\n    });\n  }\n\n  /**\n   * Hides or restores a server's tools for the rest of this session.\n   *\n   * Deliberately does not disconnect: this is a session visibility control, so a\n   * later enable is instant and does not discard an authenticated live connection.\n   * Because each catalog row is now an actual downstream server, the control acts\n   * on only that server's tools rather than on an aggregate proxy group.\n   *\n   * Nothing is re-registered on the way back: Pi 0.84 cannot unregister a tool, so\n   * every tool stays registered and only the restriction moves.\n   */\n  setEnabled(serverName: string, enabled: boolean): void {\n    this.catalog.setDisabled(serverName, !enabled);\n    this.emitChange();\n    this.updateToolVisibility();\n  }\n\n  /**\n   * Lists one server's resources, from cache unless asked for a fresh call.\n   *\n   * The cache lives here rather than in the overlay so closing and reopening the\n   * panel does not re-dial. A rejection is never cached, so a server that has no\n   * `resources/list` capability, or one that was briefly unreachable, is retried by\n   * the next request rather than remembered as empty.\n   */\n  async listResources(serverName: string, options: { refresh?: boolean } = {}): Promise<readonly McpResourceView[]> {\n    if (this.disconnectedServers.has(serverName)) throw new Error(`MCP server is disconnected: ${serverName}`);\n    if (!options.refresh) {\n      const cached = this.resourceCache.get(serverName);\n      if (cached) return cached;\n    }\n    const runtime = this.runtime;\n    const services = runtime?.getServices();\n    if (!runtime || !services) throw new Error(RUNTIME_NOT_STARTED);\n    const connection = await services.clientManager.ensureConnected(serverName);\n    const resources = await connection.listResources();\n    // A reload that landed while this was in flight retired the container it was\n    // read from, so the answer is returned to the caller but never written down.\n    if (!runtime.isCurrent(services)) return resources;\n    this.resourceCache.set(serverName, resources);\n    this.catalog.setResourceCount(serverName, resources.length);\n    this.emitChange();\n    return resources;\n  }\n\n  /** Fires whenever the server picture changes. Returns its own disposer. */\n  onChange(listener: () => void): () => void {\n    this.changeListeners.add(listener);\n    return () => {\n      this.changeListeners.delete(listener);\n    };\n  }\n\n  /**\n   * Announces a change to whoever is watching.\n   *\n   * Listener failures are contained rather than propagated: this runs inside the\n   * continuation that folds a server into Pi's tool set, and a throw escaping here\n   * would abandon that fold, leaving the session silently short of tools because\n   * something failed to repaint.\n   */\n  private emitChange(): void {\n    for (const listener of this.changeListeners) {\n      try {\n        listener();\n      } catch (error) {\n        // Recorded rather than rethrown: a watcher that cannot render is a defect\n        // worth seeing, but not one worth abandoning the tool set over.\n        this.catalog.addDiagnostic(\n          `An MCP change listener failed: ${error instanceof Error ? error.message : String(error)}`,\n        );\n      }\n    }\n  }\n\n  getDiagnostics(): readonly string[] {\n    return this.catalog.getDiagnostics();\n  }\n\n  async dispose(): Promise<void> {\n    ++this.lifecycleGeneration;\n    this.browserAuthorizationRequests.clear();\n    this.authorizationUrls.clear();\n    this.resourceCache.clear();\n    const retiredRuntime = this.runtime;\n    this.runtime = undefined;\n    await retiredRuntime?.dispose();\n  }\n\n  /**\n   * Folds one server transition into Pi's tool set.\n   *\n   * The tool list is read from the live connection rather than the state event,\n   * which carries no tools; a server that is not readable contributes none and its\n   * cached tools simply stay inactive.\n   *\n   * `ensureConnected` rather than `getClient`: the manager announces `connected`\n   * before it registers the client, so a listener that looks the client up\n   * synchronously finds nothing and the server lands with an empty tool list.\n   * This handler runs detached from the connect, so awaiting it cannot deadlock.\n   */\n  private onServerStateChange(change: McpServerStateChange, generation: number): void {\n    if (generation !== this.lifecycleGeneration || this.disconnectedServers.has(change.serverName)) return;\n    // The flow this URL belonged to is over, one way or the other: a server that\n    // reached a terminal state is not still waiting on a redirect.\n    if (change.state !== 'connecting' && change.state !== 'needs-auth') {\n      this.authorizationUrls.delete(change.serverName);\n    }\n    const runtime = this.runtime;\n    const services = runtime?.getServices();\n    const tools =\n      change.state === 'connected' && services\n        ? services.clientManager.ensureConnected(change.serverName).then((connection) => connection.listTools())\n        : Promise.resolve([]);\n    void tools\n      .catch(() => [])\n      .then((tools) => {\n        if (\n          generation !== this.lifecycleGeneration ||\n          !runtime?.isCurrent(services) ||\n          this.disconnectedServers.has(change.serverName)\n        )\n          return;\n        this.catalog.applyStateChange(change, tools);\n        this.trackTools(this.catalog.allTools());\n        this.emitChange();\n        this.updateToolVisibility();\n      });\n  }\n}\n","/**\n * What an MCP tool result carries beyond its text, shared by this package's\n * Pi adapter (which attaches it as the result's details) and its web plugin\n * (which renders it). Wire JSON only: images ride Pi's own content blocks,\n * so they are not repeated here.\n */\n\nexport type McpResultBlock =\n  | { type: 'audio'; data: string; mimeType: string }\n  | { type: 'resource_link'; uri: string; name: string; title?: string; description?: string; mimeType?: string }\n  | { type: 'resource'; uri: string; mimeType?: string; text?: string; blob?: string }\n  | { type: 'structured'; value: Record<string, unknown> };\n\nexport interface McpToolDetails {\n  server: string;\n  tool: string;\n  /** Present only when the downstream result carried something beyond text and images. */\n  blocks?: McpResultBlock[];\n}\n\nexport const MCP_SESSION_AUTH_STATUS_KEY = 'doom-mcp-session-auth';\n\nconst ANSI_ESCAPE_PATTERN = new RegExp(`${String.fromCharCode(27)}\\\\[[0-?]*[ -/]*[@-~]`, 'gu');\nconst MAX_SESSION_AUTH_SERVERS = 128;\nconst MAX_AUTHORIZATION_URL_LENGTH = 8192;\nconst SESSION_AUTH_STATES = [\n  'not-connected',\n  'connecting',\n  'connected',\n  'degraded',\n  'needs-auth',\n  'failed',\n  'closed',\n  'disabled',\n] as const;\nexport type McpSessionAuthState = (typeof SESSION_AUTH_STATES)[number];\n\nfunction isSessionAuthState(value: unknown): value is McpSessionAuthState {\n  return SESSION_AUTH_STATES.some((state) => state === value);\n}\n\nexport interface McpSessionAuthStatusItem {\n  readonly name: string;\n  readonly state: McpSessionAuthState;\n  readonly authorizationUrl?: string;\n}\n\ninterface McpSessionServerStatusSource {\n  readonly name: string;\n  readonly state: string;\n  readonly authorizationUrl?: unknown;\n}\n\n/** Keeps servers visible before discovery and after failures, without diagnostics or credentials. */\nexport function formatMcpSessionAuthStatus<T extends McpSessionServerStatusSource>(\n  servers: readonly T[],\n): string | undefined {\n  const items: McpSessionAuthStatusItem[] = servers.flatMap((server) => {\n    if (!isSessionAuthState(server.state)) return [];\n    const item: McpSessionAuthStatusItem = {\n      name: server.name,\n      state: server.state,\n      ...(isAuthorizationUrl(server.authorizationUrl) ? { authorizationUrl: server.authorizationUrl } : {}),\n    };\n    return [item];\n  });\n  return items.length === 0 ? undefined : JSON.stringify(items);\n}\n\n/** Reads the live-session status defensively. Empty is the browser's active-session clear value. */\nexport function parseMcpSessionAuthStatus(raw: string | undefined): McpSessionAuthStatusItem[] | undefined {\n  if (raw === undefined || raw.trim() === '') return undefined;\n  try {\n    const value: unknown = JSON.parse(raw.replace(ANSI_ESCAPE_PATTERN, ''));\n    if (!Array.isArray(value) || value.length === 0 || value.length > MAX_SESSION_AUTH_SERVERS) return undefined;\n\n    const names = new Set<string>();\n    for (const item of value) {\n      if (!isSessionAuthStatusItem(item) || names.has(item.name)) return undefined;\n      names.add(item.name);\n    }\n    return value;\n  } catch {\n    return undefined;\n  }\n}\n\nfunction hasControlCharacter(value: string): boolean {\n  for (const character of value) {\n    const codePoint = character.codePointAt(0);\n    if (codePoint !== undefined && (codePoint < 32 || (codePoint >= 127 && codePoint <= 159))) return true;\n  }\n  return false;\n}\n\nfunction isAuthorizationUrl(value: unknown): value is string {\n  if (typeof value !== 'string' || value.length > MAX_AUTHORIZATION_URL_LENGTH || hasControlCharacter(value)) {\n    return false;\n  }\n  try {\n    const url = new URL(value);\n    return (url.protocol === 'http:' || url.protocol === 'https:') && url.username === '' && url.password === '';\n  } catch {\n    return false;\n  }\n}\n\nfunction isSessionAuthStatusItem(value: unknown): value is McpSessionAuthStatusItem {\n  if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n  const record = value as Record<string, unknown>;\n  return (\n    Object.keys(record).every((key) => key === 'name' || key === 'state' || key === 'authorizationUrl') &&\n    (!('authorizationUrl' in record) || isAuthorizationUrl(record.authorizationUrl)) &&\n    typeof record.name === 'string' &&\n    record.name.trim() !== '' &&\n    !hasControlCharacter(record.name) &&\n    isSessionAuthState(record.state)\n  );\n}\n\n/** Hub API paths for repository-scoped MCP management. */\nexport const MCP_REPOSITORY_API_PATH = '/repository';\nexport const MCP_DISCOVERY_API_PATH = '/repository/discover';\nexport const MCP_AUTHORIZATION_API_PATH = '/repository/authorize';\n/** The repository every route is asked about, and the flow segment the two flow routes carry. */\nexport const MCP_REPOSITORY_ID_QUERY = 'repositoryId';\nexport const MCP_FLOW_ID_PARAM = 'flowId';\n\nexport type McpRepositoryServerState =\n  | 'not-connected'\n  | 'connecting'\n  | 'connected'\n  | 'degraded'\n  | 'needs-auth'\n  | 'failed'\n  | 'closed';\n\nexport interface McpRepositoryTool {\n  name: string;\n  piName: string;\n  description?: string;\n}\n\nexport interface McpRepositoryServer {\n  name: string;\n  state: McpRepositoryServerState;\n  source: 'cached' | 'live' | 'configured';\n  credentialPresent: boolean;\n  tools: McpRepositoryTool[];\n  error?: string;\n}\n\nexport interface McpRepositoryCatalog {\n  repositoryId: string;\n  sync: {\n    fresh: boolean;\n    reasons: string[];\n  };\n  servers: McpRepositoryServer[];\n  droppedServers: string[];\n  diagnostics: string[];\n}\n\nexport type McpAuthorizationStatus = 'starting' | 'waiting' | 'completed' | 'failed' | 'cancelled' | 'expired';\n\nexport interface McpAuthorizationFlow {\n  id: string;\n  repositoryId: string;\n  serverName: string;\n  status: McpAuthorizationStatus;\n  authorizationUrl?: string;\n  error?: string;\n  expiresAt: number;\n}\n","export const COMMAND_NAME = 'mcp';\nexport const COMMAND_DESCRIPTION = 'Browse this session MCP servers: authorize, enable, disable, tools and resources';\nexport const SERVER_COMMAND_DESCRIPTION = 'Show MCP configuration or begin an authorization request.';\n","import { Type } from 'typebox';\n\nexport const McpHeadlessToolParameters = Type.Object({\n  server: Type.String({ minLength: 1 }),\n  tool: Type.String({ minLength: 1 }),\n  arguments: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n});\n","import type { DoomChildSessionTool } from '@agimon-ai/doompi-core/childSession';\nimport type { DoomHeadlessToolResult } from '@agimon-ai/doompi-core/headless';\nimport type { Static } from 'typebox';\nimport { Value } from 'typebox/value';\n\nimport { McpHeadlessToolParameters } from '../../schemas/mcpHeadlessTool';\nimport type { CatalogTool } from '../mcpCatalog';\nimport type { McpSession } from '../mcpSession';\n\nexport const MCP_SESSION_TOOLS_SERVICE = 'doom/mcp-session-tools';\n\n/** Narrow cross-root access to the Pi session's existing upstream MCP runtime. */\nexport interface McpSessionToolsService {\n  readonly generation: string;\n  snapshot(): readonly CatalogTool[];\n  onChange(listener: () => void): () => void;\n  invoke(name: string, parameters: Record<string, unknown>, signal?: AbortSignal): Promise<DoomHeadlessToolResult>;\n}\n\nexport function createMcpSessionToolsService(session: McpSession, generation: string): McpSessionToolsService {\n  return Object.freeze({\n    generation,\n    snapshot: () => session.activeToolDefinitions(),\n    onChange: (listener: () => void) => session.onChange(listener),\n    invoke: (name: string, parameters: Record<string, unknown>, signal?: AbortSignal) =>\n      session.invokeTool(name, parameters, signal),\n  });\n}\n\n/** Borrow an existing MCP runtime; a child never starts or disposes its own upstream connections. */\nexport function createMcpChildTool(\n  invoke: (\n    parameters: Static<typeof McpHeadlessToolParameters>,\n    signal?: AbortSignal,\n  ) => Promise<DoomHeadlessToolResult>,\n): DoomChildSessionTool {\n  return {\n    name: 'mcp',\n    description: 'Call a tool exposed by a connected MCP server.',\n    parameters: McpHeadlessToolParameters,\n    async execute(_toolCallId, parameters, signal) {\n      signal?.throwIfAborted();\n      if (!Value.Check(McpHeadlessToolParameters, parameters)) throw new Error('Invalid MCP tool arguments.');\n      const result = await invoke(parameters, signal);\n      signal?.throwIfAborted();\n      return result;\n    },\n  };\n}\n","import type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { COMMAND_NAME, COMMAND_DESCRIPTION } from '../../constants/mcp';\nimport type { McpCommandTarget } from '../../types/mcp';\n\ninterface McpCommandDeps {\n  openOverlay(ctx: ExtensionContext): Promise<void>;\n}\n\nconst INFO = 'info';\nconst WARNING = 'warning';\n\nconst SUBCOMMAND = { status: 'status', auth: 'auth', disconnect: 'disconnect', reload: 'reload' } as const;\nconst SUBCOMMANDS = Object.values(SUBCOMMAND).join(', ');\n\n/** `/mcp <subcommand> [argument]`, with the bare command showing status. */\nfunction parseArguments(args: string): { subcommand: string; argument: string } {\n  const [subcommand = SUBCOMMAND.status, ...rest] = args.trim().split(/\\s+/).filter(Boolean);\n  return { subcommand, argument: rest.join(' ') };\n}\n\n/** One line per server: its state, and how many tools it currently offers. */\nexport function formatStatus(session: McpCommandTarget): string {\n  const { servers } = session.getSnapshot();\n  if (servers.length === 0) return 'No MCP servers are configured for this session.';\n  const lines = servers.map((server) => {\n    const detail = server.error ? ` (${server.error})` : '';\n    return `${server.name}: ${server.state} · ${server.tools.length} tools${detail}`;\n  });\n  return [...lines, ...session.getDiagnostics()].join('\\n');\n}\n\nasync function runAuth(session: McpCommandTarget, serverName: string, ctx: ExtensionContext): Promise<void> {\n  if (!serverName) {\n    ctx.ui.notify('Name the server to authorize, for example /mcp auth boomlink.', WARNING);\n    return;\n  }\n  try {\n    // Reconnecting is what drives the flow: the OAuth provider surfaces the\n    // authorization URL through the handler this extension installed.\n    await session.reauthorize(serverName);\n    ctx.ui.notify(`${serverName} is authorized.`, INFO);\n  } catch (error) {\n    ctx.ui.notify(\n      `Could not authorize ${serverName}: ${error instanceof Error ? error.message : 'unknown error'}`,\n      WARNING,\n    );\n  }\n}\n\nexport function createMcpCommand(\n  session: McpCommandTarget,\n  deps: McpCommandDeps,\n): readonly [string, Parameters<ExtensionAPI['registerCommand']>[1]] {\n  return [\n    COMMAND_NAME,\n    {\n      description: COMMAND_DESCRIPTION,\n      handler: async (args, ctx) => {\n        const raw = typeof args === 'string' ? args : '';\n        // The bare command opens the browser, where the same information can be acted\n        // on. The subcommands stay because an overlay needs a terminal, and a headless\n        // or scripted session still has to be able to ask.\n        if (raw.trim() === '' && ctx.hasUI) {\n          await deps.openOverlay(ctx);\n          return;\n        }\n        const { subcommand, argument } = parseArguments(raw);\n        if (subcommand === SUBCOMMAND.auth) {\n          await runAuth(session, argument, ctx);\n          return;\n        }\n        if (subcommand === SUBCOMMAND.disconnect) {\n          if (!argument) {\n            ctx.ui.notify('Name the server to disconnect, for example /mcp disconnect boomlink.', WARNING);\n            return;\n          }\n          try {\n            await session.disconnect(argument);\n            ctx.ui.notify(`${argument} is disconnected from this session. Saved credentials were kept.`, INFO);\n          } catch (error) {\n            ctx.ui.notify(\n              `Could not disconnect ${argument}: ${error instanceof Error ? error.message : 'unknown error'}`,\n              WARNING,\n            );\n          }\n          return;\n        }\n        if (subcommand === SUBCOMMAND.reload) {\n          ctx.ui.notify('Reconnecting MCP servers.', INFO);\n          // Not awaited: a server that never answers must not wedge the command.\n          void session.start();\n          return;\n        }\n        if (subcommand !== SUBCOMMAND.status) {\n          ctx.ui.notify(`Unknown /${COMMAND_NAME} subcommand \"${subcommand}\". Use ${SUBCOMMANDS}.`, WARNING);\n          return;\n        }\n        ctx.ui.notify(formatStatus(session), INFO);\n      },\n    },\n  ];\n}\n"],"mappings":"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"}