@agimon-ai/po-mcp 0.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +223 -0
  3. package/dist/apiContracts.cjs +269 -0
  4. package/dist/apiContracts.cjs.map +1 -0
  5. package/dist/apiContracts.d.mts +137 -0
  6. package/dist/apiContracts.d.mts.map +1 -0
  7. package/dist/apiContracts.mjs +258 -0
  8. package/dist/apiContracts.mjs.map +1 -0
  9. package/dist/extensions/mcp-ui.mjs +31 -0
  10. package/dist/extensions/mcp-ui.mjs.map +1 -0
  11. package/dist/extensions/mcp.cjs +104 -0
  12. package/dist/extensions/mcp.cjs.map +1 -0
  13. package/dist/extensions/mcp.d.mts +5 -0
  14. package/dist/extensions/mcp.d.mts.map +1 -0
  15. package/dist/extensions/mcp.mjs +99 -0
  16. package/dist/extensions/mcp.mjs.map +1 -0
  17. package/dist/extensions/server.cjs +2852 -0
  18. package/dist/extensions/server.cjs.map +1 -0
  19. package/dist/extensions/server.d.mts +5 -0
  20. package/dist/extensions/server.d.mts.map +1 -0
  21. package/dist/extensions/server.mjs +2839 -0
  22. package/dist/extensions/server.mjs.map +1 -0
  23. package/dist/extensions/web.mjs +2200 -0
  24. package/dist/extensions/web.mjs.map +1 -0
  25. package/dist/index.cjs +18 -0
  26. package/dist/index.cjs.map +1 -0
  27. package/dist/index.d.mts +89 -0
  28. package/dist/index.d.mts.map +1 -0
  29. package/dist/index.mjs +9 -0
  30. package/dist/index.mjs.map +1 -0
  31. package/dist/mcpCatalog-6Tpt6Gqn.cjs +900 -0
  32. package/dist/mcpCatalog-6Tpt6Gqn.cjs.map +1 -0
  33. package/dist/mcpCatalog-SlqWS-sb.mjs +806 -0
  34. package/dist/mcpCatalog-SlqWS-sb.mjs.map +1 -0
  35. package/dist/mcpConfig-BYESy-zP.d.mts +57 -0
  36. package/dist/mcpConfig-BYESy-zP.d.mts.map +1 -0
  37. package/dist/projection-gyAA2jRB.mjs +43 -0
  38. package/dist/projection-gyAA2jRB.mjs.map +1 -0
  39. package/dist/projection-w3XxXmVi.cjs +51 -0
  40. package/dist/projection-w3XxXmVi.cjs.map +1 -0
  41. package/dist/projection.cjs +17 -0
  42. package/dist/projection.d.mts +12 -0
  43. package/dist/projection.d.mts.map +1 -0
  44. package/dist/projection.mjs +4 -0
  45. package/dist/rolldown-runtime-C0BPl7ul.cjs +43 -0
  46. package/llms.txt +9 -0
  47. package/package.json +157 -0
  48. package/src/prompts/po-use-mcp/SKILL.md +79 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.mjs","names":["routes","isRecord","api","repositorySettingsPanelMcp","fillMcpAuth","lifecycleStart","toolMcp"],"sources":["../../src/types/webMcp.ts","../../src/types/apiRoutes.ts","../../generated/client.ts","../../src/extensions/workspaces/(frontend)/repository-settings-panel/_lib/mcpSettingsApi.ts","../../src/extensions/workspaces/(frontend)/repository-settings-panel/_lib/mcpSettingsStore.ts","../../src/extensions/workspaces/(frontend)/repository-settings-panel/_components/McpRepositorySettingsPanel.tsx","../../src/extensions/workspaces/(frontend)/repository-settings-panel/mcp.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/mcpSessionToolApi.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/McpToolDetailDialog.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/McpSessionAuthSection.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/McpAuth.context.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/mcpAppRuntime.ts","../../src/extensions/workspaces/sessions/(frontend)/lifecycle/start.web.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/mcpToolMatch.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/mcpAppSandbox.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/mcpOpenAiBootstrap.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/McpInlineApp.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/McpToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/mcp.web.tsx","../../generated/web.ts"],"sourcesContent":["/**\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 */\nimport type { ContextToolWarning } from '@agimon-ai/po-core/contextApi';\nimport type { CallToolResult } from '@modelcontextprotocol/server';\n\n/** Shared browser/server payload validated by the mcp.apps.open wire schema. */\nexport interface McpAppOpenResult {\n leaseId: string;\n html: string;\n resourceUri: string;\n protocol: 'mcp' | 'openai';\n resourceMeta: Record<string, unknown>;\n tool: {\n name: string;\n description: string;\n inputSchema: { type: 'object'; [key: string]: unknown };\n _meta: Record<string, unknown>;\n };\n args: Record<string, unknown>;\n result: { content: unknown[]; structuredContent?: unknown; _meta?: Record<string, unknown>; isError?: boolean };\n state: unknown;\n readOnly: boolean;\n}\n\n/** Private presentation payload, never appended to model content. */\nexport interface McpAppPresentation {\n version: 1;\n resourceUri?: string;\n protocol?: 'mcp' | 'openai';\n result: CallToolResult;\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 app?: McpAppPresentation;\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 MAX_SERVER_TOOLS = 512;\nconst MAX_TOOL_NAME_LENGTH = 256;\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 /** Available tools and their estimated direct-schema cost, not a second context inventory. */\n readonly tools?: readonly McpSessionReachableTool[];\n}\n\nexport interface McpSessionReachableTool {\n /** Original downstream name, used with the configured server for detail lookup. */\n readonly name: string;\n /** Actual registered name. Optional for older live-session status producers. */\n readonly piName?: string;\n readonly tokens?: number;\n}\n\n/** A session's view of one reachable tool: what the dialog shows when a row is opened. */\nexport interface McpSessionToolDetail {\n readonly server: string;\n readonly tool: string;\n readonly piName: string;\n readonly description?: string;\n readonly inputSchema: Record<string, unknown>;\n readonly tokens: number;\n readonly warnings?: readonly ContextToolWarning[];\n readonly _meta?: Record<string, unknown>;\n}\n\n/** Session route for one reachable tool's description and schema. */\nexport const MCP_SESSION_TOOL_API_PATH = '/tool';\nexport const MCP_SESSION_TOOL_SERVER_QUERY = 'server';\nexport const MCP_SESSION_TOOL_NAME_QUERY = 'tool';\n\ninterface McpSessionServerStatusSource {\n readonly name: string;\n readonly state: string;\n readonly authorizationUrl?: unknown;\n readonly tools?: readonly {\n readonly toolName: string;\n readonly piName?: string;\n readonly active: boolean;\n readonly tokens?: number;\n }[];\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 tools = (server.tools ?? [])\n .filter((tool) => tool.active && isToolName(tool.toolName))\n .map((tool): McpSessionReachableTool => ({\n name: tool.toolName,\n ...(isToolName(tool.piName) ? { piName: tool.piName } : {}),\n ...(isTokenCount(tool.tokens) ? { tokens: tool.tokens } : {}),\n }))\n .slice(0, MAX_SERVER_TOOLS);\n const item: McpSessionAuthStatusItem = {\n name: server.name,\n state: server.state,\n ...(isAuthorizationUrl(server.authorizationUrl) ? { authorizationUrl: server.authorizationUrl } : {}),\n ...(tools.length === 0 ? {} : { tools }),\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 isToolName(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n value.trim() !== '' &&\n value.length <= MAX_TOOL_NAME_LENGTH &&\n !hasControlCharacter(value)\n );\n}\n\nfunction isTokenCount(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0;\n}\n\nfunction isReachableTool(value: unknown): value is McpSessionReachableTool {\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 === 'piName' || key === 'tokens') &&\n isToolName(record.name) &&\n (!('piName' in record) || isToolName(record.piName)) &&\n (!('tokens' in record) || isTokenCount(record.tokens))\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(\n (key) => key === 'name' || key === 'state' || key === 'authorizationUrl' || key === 'tools',\n ) &&\n (!('authorizationUrl' in record) || isAuthorizationUrl(record.authorizationUrl)) &&\n (!('tools' in record) ||\n (Array.isArray(record.tools) &&\n record.tools.length <= MAX_SERVER_TOOLS &&\n record.tools.every(isReachableTool))) &&\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","import { apiResponse, defineApiRoutes } from '@agimon-ai/po-core/web';\n\nimport {\n MCP_AUTHORIZATION_API_PATH,\n MCP_DISCOVERY_API_PATH,\n MCP_FLOW_ID_PARAM,\n MCP_REPOSITORY_API_PATH,\n MCP_REPOSITORY_ID_QUERY,\n MCP_SESSION_TOOL_API_PATH,\n MCP_SESSION_TOOL_NAME_QUERY,\n MCP_SESSION_TOOL_SERVER_QUERY,\n type McpAuthorizationFlow,\n type McpRepositoryCatalog,\n type McpSessionToolDetail,\n} from './webMcp';\n\n/** One authorization flow, addressed by id below the flow collection. */\nconst AUTHORIZATION_FLOW_PATH = `${MCP_AUTHORIZATION_API_PATH}/:${MCP_FLOW_ID_PARAM}`;\n\n/**\n * This package's routes, as data.\n *\n * No scope and no base path. The build reads both off\n * `src/extensions/(backend)/api/mcp/`, so the mount is stated once, by the\n * folder that creates it. The sub-paths come from `webMcp`, which already owned\n * them, so this table names where a route sits and nothing else.\n *\n * This is the one file the hub handler and the settings panel both read, so a\n * path cannot move on one side alone. The handler matches on these strings\n * rather than parsing its own copies of them.\n *\n * `:flowId` is the client's parameter syntax; the handler reads the segment off\n * the same path, so the two cannot disagree about where the id sits.\n */\nexport default defineApiRoutes({\n catalog: {\n method: 'GET',\n path: MCP_REPOSITORY_API_PATH,\n query: [MCP_REPOSITORY_ID_QUERY],\n response: apiResponse<McpRepositoryCatalog>(),\n },\n discover: {\n method: 'POST',\n path: MCP_DISCOVERY_API_PATH,\n response: apiResponse<McpRepositoryCatalog>(),\n },\n authorize: {\n method: 'POST',\n path: MCP_AUTHORIZATION_API_PATH,\n response: apiResponse<McpAuthorizationFlow>(),\n },\n readAuthorization: {\n method: 'GET',\n path: AUTHORIZATION_FLOW_PATH,\n query: [MCP_REPOSITORY_ID_QUERY],\n response: apiResponse<McpAuthorizationFlow>(),\n },\n /** The same path as `readAuthorization`; the method is the whole of the difference. */\n cancelAuthorization: {\n method: 'DELETE',\n path: AUTHORIZATION_FLOW_PATH,\n query: [MCP_REPOSITORY_ID_QUERY],\n response: apiResponse<McpAuthorizationFlow>(),\n },\n /** Session scope: one available tool's registered name, description and schema. */\n sessionTool: {\n method: 'GET',\n path: MCP_SESSION_TOOL_API_PATH,\n query: [MCP_SESSION_TOOL_SERVER_QUERY, MCP_SESSION_TOOL_NAME_QUERY],\n response: apiResponse<McpSessionToolDetail>(),\n },\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { createApiClient, sessionApiAddress } from '@agimon-ai/po-core/web';\nimport { sealedTransport } from '@agimon-ai/po-web-security/browser';\n\nimport routes from '../src/types/apiRoutes';\n\n/** Scopes the tree mounts 'mcp' at for the mcp mount. */\nexport const mcpScopes = ['global', 'workspace', 'session'] as const;\n\nexport const mcp = createApiClient(routes, {\n scopes: mcpScopes,\n basePath: 'mcp',\n transport: (input, init) => sealedTransport.fetch(input, init),\n sessionAddress: sessionApiAddress,\n});\n\n/** Scopes the tree mounts 'mcp-session' at for the mcp-session mount. */\nexport const mcpSessionScopes = ['session'] as const;\n\nexport const mcpSession = createApiClient(routes, {\n scopes: mcpSessionScopes,\n basePath: 'mcp-session',\n transport: (input, init) => sealedTransport.fetch(input, init),\n sessionAddress: sessionApiAddress,\n});\n","import { mcp as api } from '../../../../../../generated/client';\nimport {\n MCP_FLOW_ID_PARAM,\n MCP_REPOSITORY_ID_QUERY,\n type McpAuthorizationFlow,\n type McpRepositoryCatalog,\n} from '../../../../../types/webMcp';\n\n/**\n * The panel's half of this package's repository API.\n *\n * The generated client owns every URL, addressed at the workspace scope the\n * repository names, so nothing here spells a mount. The workspace prefix, the\n * plugins segment and the base path used to be concatenated at the top of this\n * file, the only copy of that shape outside the host, and it agreed with the\n * route by inspection alone.\n *\n * The transport stays injected, which is the one way this package differs from\n * its siblings. Every write here is step-up gated: the panel passes the\n * elevated request for discovery, authorization and cancellation and the plain\n * one for reads, and that choice belongs to the caller. So the client is asked\n * for the URL and the method, and the caller's own request issues them.\n */\n\nconst JSON_HEADERS = { 'content-type': 'application/json' };\n\nexport type McpRequest = (input: string, init?: RequestInit) => Promise<Response>;\nexport type McpApiResult<T> = { value: T } | { error: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nasync function resultOf<T>(response: Response, fallback: string): Promise<McpApiResult<T>> {\n let body: unknown;\n try {\n body = (await response.json()) as unknown;\n } catch {\n body = undefined;\n }\n if (!response.ok) {\n return { error: isRecord(body) && typeof body.error === 'string' ? body.error : fallback };\n }\n return { value: body as T };\n}\n\nexport async function readMcpCatalog(\n request: McpRequest,\n repositoryId: string,\n): Promise<McpApiResult<McpRepositoryCatalog>> {\n const route = api.workspace(repositoryId).catalog;\n const response = await request(route.url({ query: { [MCP_REPOSITORY_ID_QUERY]: repositoryId } }));\n return await resultOf(response, 'The synced MCP catalog could not be read.');\n}\n\nexport async function discoverMcpCatalog(\n requestWithStepUp: McpRequest,\n repositoryId: string,\n): Promise<McpApiResult<McpRepositoryCatalog>> {\n const route = api.workspace(repositoryId).discover;\n const response = await requestWithStepUp(route.url(), {\n method: route.spec.method,\n headers: JSON_HEADERS,\n body: JSON.stringify({ repositoryId }),\n });\n return await resultOf(response, 'MCP discovery could not be completed.');\n}\n\nexport async function startMcpAuthorization(\n requestWithStepUp: McpRequest,\n repositoryId: string,\n serverName: string,\n): Promise<McpApiResult<McpAuthorizationFlow>> {\n const route = api.workspace(repositoryId).authorize;\n const response = await requestWithStepUp(route.url(), {\n method: route.spec.method,\n headers: JSON_HEADERS,\n body: JSON.stringify({ repositoryId, serverName }),\n });\n return await resultOf(response, 'MCP authorization could not be started.');\n}\n\nexport async function readMcpAuthorization(\n request: McpRequest,\n repositoryId: string,\n flowId: string,\n): Promise<McpApiResult<McpAuthorizationFlow>> {\n const route = api.workspace(repositoryId).readAuthorization;\n const response = await request(\n route.url({ params: { [MCP_FLOW_ID_PARAM]: flowId }, query: { [MCP_REPOSITORY_ID_QUERY]: repositoryId } }),\n );\n return await resultOf(response, 'The authorization state could not be read.');\n}\n\nexport async function cancelMcpAuthorization(\n requestWithStepUp: McpRequest,\n repositoryId: string,\n flowId: string,\n): Promise<McpApiResult<McpAuthorizationFlow>> {\n const route = api.workspace(repositoryId).cancelAuthorization;\n const response = await requestWithStepUp(\n route.url({ params: { [MCP_FLOW_ID_PARAM]: flowId }, query: { [MCP_REPOSITORY_ID_QUERY]: repositoryId } }),\n { method: route.spec.method },\n );\n return await resultOf(response, 'The authorization flow could not be cancelled.');\n}\n","import { Store } from '@tanstack/store';\n\nimport type { McpAuthorizationFlow, McpRepositoryCatalog } from '../../../../../types/webMcp';\nimport {\n cancelMcpAuthorization,\n discoverMcpCatalog,\n type McpRequest,\n readMcpAuthorization,\n readMcpCatalog,\n startMcpAuthorization,\n} from './mcpSettingsApi';\n\nexport interface McpSettingsState {\n repositoryId: string | undefined;\n catalog: McpRepositoryCatalog | undefined;\n authorization: McpAuthorizationFlow | undefined;\n busy: 'loading' | 'discovering' | 'authorizing' | 'cancelling' | undefined;\n error: string | undefined;\n}\n\nexport const mcpSettings = new Store<McpSettingsState>({\n repositoryId: undefined,\n catalog: undefined,\n authorization: undefined,\n busy: undefined,\n error: undefined,\n});\n\nfunction selectRepository(repositoryId: string): void {\n if (mcpSettings.state.repositoryId === repositoryId) return;\n mcpSettings.setState(() => ({\n repositoryId,\n catalog: undefined,\n authorization: undefined,\n busy: undefined,\n error: undefined,\n }));\n}\n\nfunction applyFor(repositoryId: string, update: (current: McpSettingsState) => McpSettingsState): void {\n if (mcpSettings.state.repositoryId !== repositoryId) return;\n mcpSettings.setState(update);\n}\n\nexport async function loadMcpSettings(request: McpRequest, repositoryId: string): Promise<void> {\n selectRepository(repositoryId);\n mcpSettings.setState((current) => ({ ...current, busy: 'loading', error: undefined }));\n try {\n const result = await readMcpCatalog(request, repositoryId);\n applyFor(repositoryId, (current) =>\n 'error' in result\n ? { ...current, busy: undefined, error: result.error }\n : { ...current, busy: undefined, catalog: result.value, error: undefined },\n );\n } catch {\n applyFor(repositoryId, (current) => ({ ...current, busy: undefined, error: 'The cockpit hub is unreachable.' }));\n }\n}\n\nexport async function discoverMcpSettings(requestWithStepUp: McpRequest, repositoryId: string): Promise<void> {\n selectRepository(repositoryId);\n mcpSettings.setState((current) => ({ ...current, busy: 'discovering', error: undefined }));\n try {\n const result = await discoverMcpCatalog(requestWithStepUp, repositoryId);\n applyFor(repositoryId, (current) =>\n 'error' in result\n ? { ...current, busy: undefined, error: result.error }\n : { ...current, busy: undefined, catalog: result.value, error: undefined },\n );\n } catch {\n applyFor(repositoryId, (current) => ({ ...current, busy: undefined, error: 'The cockpit hub is unreachable.' }));\n }\n}\n\nexport async function authorizeMcpServer(\n requestWithStepUp: McpRequest,\n repositoryId: string,\n serverName: string,\n): Promise<void> {\n selectRepository(repositoryId);\n mcpSettings.setState((current) => ({ ...current, busy: 'authorizing', error: undefined }));\n try {\n const result = await startMcpAuthorization(requestWithStepUp, repositoryId, serverName);\n applyFor(repositoryId, (current) =>\n 'error' in result\n ? { ...current, busy: undefined, error: result.error }\n : { ...current, busy: undefined, authorization: result.value, error: undefined },\n );\n } catch {\n applyFor(repositoryId, (current) => ({ ...current, busy: undefined, error: 'The cockpit hub is unreachable.' }));\n }\n}\n\nexport function followMcpAuthorization(\n request: McpRequest,\n repositoryId: string,\n flowId: string,\n onCompleted: () => void,\n): () => void {\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const poll = async (): Promise<void> => {\n if (stopped) return;\n try {\n const result = await readMcpAuthorization(request, repositoryId, flowId);\n if (stopped) return;\n if ('error' in result) {\n applyFor(repositoryId, (current) => ({ ...current, error: result.error }));\n return;\n }\n applyFor(repositoryId, (current) => ({ ...current, authorization: result.value, error: undefined }));\n if (result.value.status === 'completed') {\n onCompleted();\n return;\n }\n if (['failed', 'cancelled', 'expired'].includes(result.value.status)) return;\n timer = setTimeout(() => void poll(), 1000);\n } catch {\n applyFor(repositoryId, (current) => ({ ...current, error: 'The authorization status could not be refreshed.' }));\n }\n };\n void poll();\n return () => {\n stopped = true;\n if (timer) clearTimeout(timer);\n };\n}\n\nexport async function cancelMcpFlow(\n requestWithStepUp: McpRequest,\n repositoryId: string,\n flowId: string,\n): Promise<void> {\n mcpSettings.setState((current) => ({ ...current, busy: 'cancelling', error: undefined }));\n try {\n const result = await cancelMcpAuthorization(requestWithStepUp, repositoryId, flowId);\n applyFor(repositoryId, (current) =>\n 'error' in result\n ? { ...current, busy: undefined, error: result.error }\n : { ...current, busy: undefined, authorization: result.value, error: undefined },\n );\n } catch {\n applyFor(repositoryId, (current) => ({ ...current, busy: undefined, error: 'The cockpit hub is unreachable.' }));\n }\n}\n","import type { RepositorySettingsPanelProps } from '@agimon-ai/po-core/web';\nimport {\n Button,\n ChevronRightIcon,\n ExternalLinkIcon,\n SettingsActions,\n SettingsCard,\n SettingsNote,\n SettingsRow,\n SettingsRowDescription,\n SettingsRowText,\n SettingsRowTitle,\n SettingsSection,\n SettingsSectionHeader,\n SettingsSectionTitle,\n} from '@agimon-ai/po-web-components';\nimport { useStore } from '@tanstack/react-store';\nimport { useEffect, useState } from 'react';\n\nimport type {\n McpAuthorizationStatus,\n McpRepositoryServer,\n McpRepositoryServerState,\n} from '../../../../../types/webMcp';\nimport {\n authorizeMcpServer,\n cancelMcpFlow,\n discoverMcpSettings,\n followMcpAuthorization,\n loadMcpSettings,\n mcpSettings,\n} from '../_lib/mcpSettingsStore';\n\nconst TERMINAL_AUTHORIZATION = new Set(['completed', 'failed', 'cancelled', 'expired']);\n\nconst SYNC_REASON: Readonly<Record<string, string>> = {\n 'never-synced': 'this repository has never been synced',\n 'configuration-changed': 'the configuration changed since the last sync',\n 'cockpit-bundle-missing': 'the cockpit bundle is missing',\n 'package-apis-missing': 'package APIs are missing',\n};\n\nconst SERVER_STATE: Readonly<Record<McpRepositoryServerState, string>> = {\n 'not-connected': 'Not connected',\n connecting: 'Connecting',\n connected: 'Connected',\n degraded: 'Degraded',\n 'needs-auth': 'Needs sign-in',\n failed: 'Failed',\n closed: 'Closed',\n};\n\nconst AUTHORIZATION_STATUS: Readonly<Record<McpAuthorizationStatus, string>> = {\n starting: 'Starting sign-in.',\n waiting: 'Waiting for you to finish signing in.',\n completed: 'Signed in.',\n failed: \"Sign-in didn't finish.\",\n cancelled: 'Sign-in was cancelled.',\n expired: 'Sign-in expired before it finished.',\n};\n\nfunction syncReasons(reasons: readonly string[]): string {\n const said = reasons.map((reason) => SYNC_REASON[reason] ?? reason).join(', ');\n return `${said || 'the last sync is out of date'}. Run po sync, then refresh.`;\n}\n\n/** One server: its state and credential on the left, Authorize on the right, cached tools folded underneath. */\nfunction ServerRow({\n server,\n busy,\n canAct,\n confirming,\n onAuthorize,\n onConfirm,\n onCancel,\n}: {\n server: McpRepositoryServer;\n busy: boolean;\n canAct: boolean;\n confirming: boolean;\n onAuthorize: () => void;\n onConfirm: () => void;\n onCancel: () => void;\n}) {\n const toolCount = server.tools.length;\n return (\n <SettingsRow asChild className=\"items-start\">\n <li data-testid={`mcp-server-${server.name}`}>\n <SettingsRowText>\n <SettingsRowTitle className=\"font-mono first-letter:normal-case\">{server.name}</SettingsRowTitle>\n <SettingsRowDescription>\n {SERVER_STATE[server.state]}. {server.credentialPresent ? 'Credential saved.' : 'No credential saved.'}\n </SettingsRowDescription>\n {server.error === undefined ? null : (\n <SettingsRowDescription className=\"text-doom-red\">{server.error}</SettingsRowDescription>\n )}\n </SettingsRowText>\n {confirming ? null : (\n <Button variant=\"outline\" size=\"sm\" disabled={busy || !canAct} onClick={onAuthorize}>\n Authorize\n </Button>\n )}\n {confirming ? (\n <div className=\"flex basis-full flex-wrap items-center gap-x-4 gap-y-2 rounded-md bg-doom-bg px-4 py-3\">\n <span className=\"min-w-0 flex-1 text-base leading-relaxed text-doom-text\">\n Start a short OAuth sign-in for {server.name}? A passkey may be required.\n </span>\n <SettingsActions>\n <Button variant=\"primary\" size=\"sm\" disabled={busy} onClick={onConfirm}>\n Continue\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n Cancel\n </Button>\n </SettingsActions>\n </div>\n ) : null}\n <details className=\"group basis-full\">\n <summary className=\"flex w-fit cursor-pointer list-none items-center gap-1 text-base font-medium text-doom-text hover:text-doom-hi [&::-webkit-details-marker]:hidden\">\n <ChevronRightIcon aria-hidden className=\"size-3.5 transition-transform group-open:rotate-90\" />\n {toolCount === 1 ? '1 tool' : `${String(toolCount)} tools`}, {server.source}\n </summary>\n <ul className=\"mt-3 flex flex-col gap-1.5 border-l border-doom-border-soft pl-4\">\n {toolCount === 0 ? (\n <li className=\"text-sm text-doom-dim\">Run discovery to see what this server offers.</li>\n ) : (\n server.tools.map((tool) => (\n <li key={tool.piName} className=\"flex min-w-0 items-baseline gap-3 text-base\">\n <code title={tool.piName} className=\"min-w-0 shrink-0 truncate font-mono text-doom-hi\">\n {tool.piName}\n </code>\n <span className=\"min-w-0 truncate text-doom-dim\">{tool.description ?? ''}</span>\n </li>\n ))\n )}\n </ul>\n </details>\n </li>\n </SettingsRow>\n );\n}\n\nexport function McpRepositorySettingsPanel({ repository, request, requestWithStepUp }: RepositorySettingsPanelProps) {\n const state = useStore(mcpSettings);\n const [confirmDiscovery, setConfirmDiscovery] = useState(false);\n const [confirmAuthorization, setConfirmAuthorization] = useState<string | undefined>();\n const repositoryId = repository?.id;\n\n useEffect(() => {\n // Loading a repository's catalog is the external sync; the two resets clear the\n // confirmations that belonged to the repository being navigated away from.\n // oxlint-disable-next-line react/set-state-in-effect\n setConfirmDiscovery(false);\n setConfirmAuthorization(undefined);\n if (repositoryId) void loadMcpSettings(request, repositoryId);\n }, [repositoryId, request]);\n\n const authorization = state.repositoryId === repositoryId ? state.authorization : undefined;\n // Only the id and status decide the subscription, so the effect reads those two\n // primitives rather than the authorization object it belongs to.\n const authorizationId = authorization?.id;\n const authorizationStatus = authorization?.status;\n useEffect(() => {\n if (!repositoryId || authorizationId === undefined) return;\n if (authorizationStatus !== undefined && TERMINAL_AUTHORIZATION.has(authorizationStatus)) return;\n return followMcpAuthorization(request, repositoryId, authorizationId, () => {\n void loadMcpSettings(request, repositoryId);\n });\n }, [authorizationId, authorizationStatus, repositoryId, request]);\n\n if (!repository) {\n return (\n <SettingsCard data-testid=\"mcp-repository-settings\">\n <SettingsRow>\n <SettingsRowText>\n <SettingsRowTitle>No repository picked</SettingsRowTitle>\n <SettingsRowDescription>Pick a repository above to see its MCP servers.</SettingsRowDescription>\n </SettingsRowText>\n </SettingsRow>\n </SettingsCard>\n );\n }\n\n const catalog = state.repositoryId === repository.id ? state.catalog : undefined;\n const busy = state.repositoryId === repository.id ? state.busy : undefined;\n const error = state.repositoryId === repository.id ? state.error : undefined;\n const fresh = catalog?.sync.fresh === true;\n const servers = catalog?.servers ?? [];\n const dropped = catalog?.droppedServers ?? [];\n\n return (\n <div className=\"flex min-w-0 flex-col gap-10\" data-testid=\"mcp-repository-settings\">\n <SettingsSection>\n <SettingsSectionHeader>\n <SettingsSectionTitle>Catalog</SettingsSectionTitle>\n </SettingsSectionHeader>\n <SettingsCard>\n <SettingsRow>\n <SettingsRowText>\n <SettingsRowTitle>\n {fresh ? 'Up to date' : catalog ? 'Needs a sync' : 'Reading the catalog'}\n </SettingsRowTitle>\n <SettingsRowDescription>\n {fresh\n ? 'Po reads the cached catalog on this machine. Discovery contacts each configured server.'\n : catalog\n ? syncReasons(catalog.sync.reasons)\n : 'Reading what the last sync recorded.'}\n </SettingsRowDescription>\n </SettingsRowText>\n <SettingsActions>\n <Button\n variant=\"outline\"\n size=\"sm\"\n loading={busy === 'loading'}\n disabled={busy !== undefined}\n onClick={() => void loadMcpSettings(request, repository.id)}\n >\n Refresh\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n loading={busy === 'discovering'}\n disabled={busy !== undefined || !fresh || confirmDiscovery}\n onClick={() => setConfirmDiscovery(true)}\n >\n Discover servers\n </Button>\n </SettingsActions>\n </SettingsRow>\n {confirmDiscovery ? (\n <SettingsRow>\n <SettingsRowText>\n <SettingsRowTitle>Discover servers now?</SettingsRowTitle>\n <SettingsRowDescription>\n Discovery starts the configured processes and contacts remote MCP servers.\n </SettingsRowDescription>\n </SettingsRowText>\n <SettingsActions>\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={busy !== undefined}\n onClick={() => {\n setConfirmDiscovery(false);\n void discoverMcpSettings(requestWithStepUp, repository.id);\n }}\n >\n Discover\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setConfirmDiscovery(false)}>\n Cancel\n </Button>\n </SettingsActions>\n </SettingsRow>\n ) : null}\n {error === undefined ? null : (\n <SettingsRow role=\"alert\">\n <SettingsRowText>\n <SettingsRowTitle>Po couldn't finish that just now</SettingsRowTitle>\n <SettingsRowDescription>{error}</SettingsRowDescription>\n </SettingsRowText>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy !== undefined}\n onClick={() => void loadMcpSettings(request, repository.id)}\n >\n Try again\n </Button>\n </SettingsRow>\n )}\n </SettingsCard>\n </SettingsSection>\n\n {authorization ? (\n <SettingsSection>\n <SettingsSectionHeader>\n <SettingsSectionTitle>Sign-in</SettingsSectionTitle>\n </SettingsSectionHeader>\n <SettingsCard>\n <SettingsRow>\n <SettingsRowText>\n <SettingsRowTitle className=\"font-mono first-letter:normal-case\">\n {authorization.serverName}\n </SettingsRowTitle>\n <SettingsRowDescription>{AUTHORIZATION_STATUS[authorization.status]}</SettingsRowDescription>\n {authorization.error ? (\n <SettingsRowDescription className=\"text-doom-red\">{authorization.error}</SettingsRowDescription>\n ) : null}\n </SettingsRowText>\n <SettingsActions>\n {authorization.authorizationUrl ? (\n <Button variant=\"primary\" size=\"sm\" asChild>\n <a href={authorization.authorizationUrl} target=\"_blank\" rel=\"noreferrer noopener\">\n Open sign-in page\n <ExternalLinkIcon aria-hidden className=\"size-3.5\" />\n </a>\n </Button>\n ) : null}\n {TERMINAL_AUTHORIZATION.has(authorization.status) ? null : (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n loading={busy === 'cancelling'}\n disabled={busy !== undefined}\n onClick={() => void cancelMcpFlow(requestWithStepUp, repository.id, authorization.id)}\n >\n Cancel\n </Button>\n )}\n </SettingsActions>\n </SettingsRow>\n </SettingsCard>\n </SettingsSection>\n ) : null}\n\n <SettingsSection>\n <SettingsSectionHeader>\n <SettingsSectionTitle>Servers</SettingsSectionTitle>\n {servers.length === 0 ? null : (\n <span className=\"text-sm text-doom-dim\">\n {servers.length === 1 ? '1 server' : `${String(servers.length)} servers`}\n </span>\n )}\n </SettingsSectionHeader>\n <SettingsCard asChild>\n <ul>\n {servers.length === 0 ? (\n <SettingsRow asChild>\n <li>\n <SettingsRowText>\n <SettingsRowTitle>{busy === 'loading' ? 'Reading the catalog' : 'No servers yet'}</SettingsRowTitle>\n <SettingsRowDescription>\n {busy === 'loading' ? 'This takes a moment.' : \"None are enabled in this repository's last sync.\"}\n </SettingsRowDescription>\n </SettingsRowText>\n </li>\n </SettingsRow>\n ) : (\n servers.map((server) => (\n <ServerRow\n key={server.name}\n server={server}\n busy={busy !== undefined}\n canAct={fresh}\n confirming={confirmAuthorization === server.name}\n onAuthorize={() => setConfirmAuthorization(server.name)}\n onConfirm={() => {\n setConfirmAuthorization(undefined);\n void authorizeMcpServer(requestWithStepUp, repository.id, server.name);\n }}\n onCancel={() => setConfirmAuthorization(undefined)}\n />\n ))\n )}\n </ul>\n </SettingsCard>\n {dropped.length === 0 ? null : <SettingsNote>{`Left out by policy: ${dropped.join(', ')}.`}</SettingsNote>}\n {catalog?.diagnostics.map((diagnostic) => (\n <SettingsNote key={diagnostic} className=\"text-doom-red\">\n {diagnostic}\n </SettingsNote>\n ))}\n </SettingsSection>\n </div>\n );\n}\n","import { defineRepositorySettingsPanel } from '@agimon-ai/po-core/web';\n\nimport { McpRepositorySettingsPanel } from './_components/McpRepositorySettingsPanel';\nexport default defineRepositorySettingsPanel({\n label: 'MCP servers',\n detail: \"The MCP servers this repository's sessions can use, what each one offers, and where to sign in.\",\n order: 100,\n component: McpRepositorySettingsPanel,\n});\n","import { mcpSession } from '../../../../../../../generated/client';\nimport {\n MCP_SESSION_TOOL_NAME_QUERY,\n MCP_SESSION_TOOL_SERVER_QUERY,\n type McpSessionToolDetail,\n} from '../../../../../../types/webMcp';\n\nexport type FetchSessionToolResult = { ok: true; detail: McpSessionToolDetail } | { ok: false; error: string };\n\n/** One available session tool: its registered name, description, schema and token estimate. */\nexport async function fetchSessionTool(\n sessionId: string,\n server: string,\n tool: string,\n): Promise<FetchSessionToolResult> {\n const result = await mcpSession\n .session(sessionId)\n .sessionTool({ query: { [MCP_SESSION_TOOL_SERVER_QUERY]: server, [MCP_SESSION_TOOL_NAME_QUERY]: tool } });\n if (!result.ok) {\n if (result.status === 0) return { ok: false, error: 'The session is unreachable.' };\n return { ok: false, error: result.error === '' ? `The session answered ${result.status}.` : result.error };\n }\n return { ok: true, detail: result.data };\n}\n","import {\n Dialog,\n DialogBody,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '@agimon-ai/po-web-components';\nimport { useEffect, useState } from 'react';\n\nimport type { McpSessionToolDetail } from '../../../../../../types/webMcp';\nimport { fetchSessionTool } from '../_lib/mcpSessionToolApi';\n\nexport interface McpToolTarget {\n sessionId: string;\n server: string;\n tool: string;\n piName?: string;\n inContext?: boolean;\n}\n\ntype Loaded = { key: string; detail?: McpSessionToolDetail; error?: string };\n\nfunction keyOf(target: McpToolTarget): string {\n return `${target.sessionId}\\u0000${target.server}\\u0000${target.tool}`;\n}\n\n/** One MCP declaration's description, complete input schema and estimated context cost. */\nexport function McpToolDetailDialog({ target, onClose }: { target: McpToolTarget | null; onClose: () => void }) {\n const [loaded, setLoaded] = useState<Loaded | null>(null);\n\n useEffect(() => {\n if (target === null) return;\n let live = true;\n const key = keyOf(target);\n void fetchSessionTool(target.sessionId, target.server, target.tool).then((result) => {\n if (!live) return;\n setLoaded(result.ok ? { key, detail: result.detail } : { key, error: result.error });\n });\n return () => {\n live = false;\n };\n }, [target]);\n\n // A response for another row is never shown under this one's title.\n const current = target !== null && loaded?.key === keyOf(target) ? loaded : null;\n const detail = current?.detail;\n return (\n <Dialog\n open={target !== null}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n <DialogContent data-testid=\"mcp-tool-detail-dialog\">\n <DialogHeader className=\"items-start px-4 py-4 sm:px-5\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\">\n <DialogTitle className=\"break-words leading-snug\">\n {detail?.piName ?? target?.piName ?? (target === null ? '' : `${target.server} · ${target.tool}`)}\n </DialogTitle>\n <DialogDescription>\n {target === null ? '' : `${target.server} / ${target.tool}. `}\n {target?.inContext === false ? 'Not in the model context. ' : ''}\n {detail === undefined\n ? 'Description and complete input schema.'\n : `Estimated schema cost: ~${detail.tokens.toLocaleString()} tokens.`}\n </DialogDescription>\n </div>\n </DialogHeader>\n <DialogBody className=\"flex flex-col gap-3 px-4 py-4 sm:px-5 sm:py-5\">\n {current === null ? <output className=\"text-sm text-doom-dim\">Loading the tool...</output> : null}\n {current?.error === undefined ? null : <output className=\"text-sm text-doom-dim\">{current.error}</output>}\n {detail === undefined ? null : (\n <>\n <section className=\"flex flex-col gap-1\">\n <p className=\"text-sm font-semibold text-doom-dim\">description</p>\n <p className=\"whitespace-pre-wrap text-base text-doom-text\">\n {detail.description ?? 'No description.'}\n </p>\n </section>\n {detail.warnings?.length ? (\n <section aria-label=\"Tool warnings\" className=\"flex flex-col gap-1 text-base text-doom-yellow\">\n {detail.warnings.map((warning) => (\n <p key={`${warning.source}:${warning.path}:${warning.message}`}>\n {warning.source} {warning.path}: {warning.message}\n </p>\n ))}\n </section>\n ) : null}\n <section className=\"flex min-h-0 flex-col gap-1\">\n <p className=\"text-sm font-semibold text-doom-dim\">input schema</p>\n <pre\n data-testid=\"mcp-tool-detail-schema\"\n className=\"max-h-96 overflow-auto rounded border border-doom-border-soft p-2 font-mono text-sm text-doom-text\"\n >\n {JSON.stringify(detail.inputSchema, null, 2)}\n </pre>\n </section>\n </>\n )}\n </DialogBody>\n </DialogContent>\n </Dialog>\n );\n}\n","import type { SessionFrameSender, WebPluginSlotProps } from '@agimon-ai/po-core/web';\nimport {\n Button,\n Dialog,\n DialogBody,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n} from '@agimon-ai/po-web-components';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { MCP_SESSION_AUTH_STATUS_KEY, parseMcpSessionAuthStatus } from '../../../../../../types/webMcp';\nimport { McpToolDetailDialog, type McpToolTarget } from './McpToolDetailDialog';\n\n/** Requests authorization through Pi's command frame, never through a shell. */\nexport function requestMcpSessionAuthorization(\n sendSessionFrame: SessionFrameSender,\n sessionId: string,\n serverName: string,\n): void {\n sendSessionFrame(sessionId, { type: 'prompt', message: `/mcp auth ${serverName}` });\n}\n\nfunction tokenEstimate(value: number | null): string {\n return value === null ? '-' : `~${value.toLocaleString()}`;\n}\n\n/** Keep configured servers actionable even before they have discovered any tools. */\nexport function McpSessionAuthSection({\n sessionId,\n statuses,\n sendSessionFrame,\n contextInventory = [],\n}: WebPluginSlotProps) {\n const servers = parseMcpSessionAuthStatus(statuses[MCP_SESSION_AUTH_STATUS_KEY]) ?? [];\n const [target, setTarget] = useState<{ sessionId: string; name: string } | null>(null);\n const [copyFeedback, setCopyFeedback] = useState('');\n const [popupBlocked, setPopupBlocked] = useState(false);\n const [toolTarget, setToolTarget] = useState<McpToolTarget | null>(null);\n // Only retain a tab while it is our blank placeholder. Never close the provider's page.\n const pendingTab = useRef<Window | null>(null);\n const selected = target?.sessionId === sessionId ? target : null;\n const server = servers.find((item) => item.name === selected?.name);\n const authorizationUrl = server?.authorizationUrl;\n\n const closePendingTab = () => {\n pendingTab.current?.close();\n pendingTab.current = null;\n };\n\n useEffect(() => {\n const tab = pendingTab.current;\n if (!selected || !authorizationUrl || !tab || tab.closed) return;\n tab.location.replace(authorizationUrl);\n pendingTab.current = null;\n }, [selected, authorizationUrl]);\n\n useEffect(\n () => () => {\n pendingTab.current?.close();\n pendingTab.current = null;\n },\n [sessionId],\n );\n\n const authorize = (name: string) => {\n if (sessionId === null) return;\n const current = servers.find((item) => item.name === name);\n closePendingTab();\n setTarget({ sessionId, name });\n setCopyFeedback('');\n // Reserve the tab during the click. Opening it after asynchronous discovery is blocked by browsers.\n const tab = window.open('about:blank', '_blank');\n setPopupBlocked(tab === null);\n if (tab) {\n tab.opener = null;\n if (current?.authorizationUrl) {\n tab.location.replace(current.authorizationUrl);\n } else {\n tab.document.title = 'MCP authorization';\n tab.document.body.textContent = 'Preparing authorization. Return to Po for progress or manual sign-in.';\n pendingTab.current = tab;\n }\n }\n if (!current?.authorizationUrl && current?.state !== 'connecting') {\n requestMcpSessionAuthorization(sendSessionFrame, sessionId, name);\n }\n };\n\n const copyLink = async () => {\n if (!authorizationUrl) return;\n try {\n await navigator.clipboard.writeText(authorizationUrl);\n setCopyFeedback('Link copied.');\n } catch {\n setCopyFeedback('Clipboard unavailable. Select the link above and copy it manually.');\n }\n };\n\n return (\n <>\n {servers.length === 0 ? null : (\n <section data-testid=\"context-mcp-auth\" className=\"flex flex-col gap-2 border-b border-doom-border px-3 py-3\">\n <div className=\"flex flex-col gap-0.5\">\n <p className=\"text-sm font-semibold text-doom-dim\">MCP servers</p>\n <p className=\"text-sm leading-relaxed text-doom-dim\">\n Open sign-in in a new tab, or copy the link from the authorization dialog.\n </p>\n </div>\n <ul aria-label=\"MCP servers\" className=\"flex flex-col gap-2\">\n {servers.map((item) => {\n // Only the context inventory measures what is actually emitted to the model.\n const tools = contextInventory.filter(\n (inventoryItem) => inventoryItem.source === 'mcp' && inventoryItem.owner === item.name,\n );\n const reachable = item.tools ?? [];\n return (\n <li key={item.name} className=\"flex min-w-0 flex-col gap-1 px-1 py-0.5\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"min-w-0 flex-1 truncate text-base font-semibold text-doom-hi\">{item.name}</span>\n <span className=\"text-sm font-semibold text-doom-dim\">{item.state.replace(/-/g, ' ')}</span>\n <Button\n variant=\"subtle\"\n size=\"xs\"\n data-testid={`context-mcp-auth-${item.name}`}\n aria-label={`${item.state === 'connected' ? 'Manage' : 'Authorize'} ${item.name}`}\n disabled={sessionId === null || item.state === 'disabled'}\n onClick={() => {\n if (item.state !== 'connected') {\n authorize(item.name);\n } else if (sessionId !== null) {\n closePendingTab();\n setCopyFeedback('');\n setPopupBlocked(false);\n setTarget({ sessionId, name: item.name });\n }\n }}\n className=\"shrink-0 \"\n >\n {item.state === 'connected' ? 'manage' : 'authorize'}\n </Button>\n </div>\n {tools.length > 0 ? (\n <ul aria-label={`${item.name} tools and skills`} className=\"flex flex-col\">\n {tools.map((tool) => {\n const identity = reachable.find((candidate) => candidate.piName === tool.name);\n return (\n <li\n key={`${tool.itemKind}:${tool.name}`}\n data-active={tool.active}\n className=\"flex min-w-0 items-center gap-2 py-px pl-3\"\n >\n <abbr\n title={tool.itemKind}\n className={`w-3 shrink-0 text-2xs font-semibold no-underline ${tool.active ? 'text-doom-violet' : 'text-doom-dim'}`}\n >\n {tool.itemKind === 'skill' ? 'S' : 'T'}\n </abbr>\n {tool.itemKind === 'tool' ? (\n <Button\n variant=\"ghost\"\n size=\"card\"\n aria-label={`Open schema for ${tool.name}`}\n data-testid={`context-mcp-tool-${tool.name}`}\n disabled={sessionId === null || identity === undefined}\n onClick={() => {\n if (sessionId !== null && identity !== undefined)\n setToolTarget({\n sessionId,\n server: item.name,\n tool: identity.name,\n piName: identity.piName,\n inContext: tool.active,\n });\n }}\n className={`min-w-0 flex-1 truncate rounded-none py-0 text-left text-base ${tool.active ? 'text-doom-hi' : 'text-doom-dim'}`}\n >\n {tool.name}\n </Button>\n ) : (\n <span className=\"min-w-0 flex-1 truncate text-base text-doom-dim\">{tool.name}</span>\n )}\n <span\n className={`w-14 shrink-0 text-right text-sm ${tool.active ? 'text-doom-text' : 'text-doom-dim'}`}\n >\n {tool.active ? tokenEstimate(tool.tokens) : `(${tokenEstimate(tool.tokens)})`}\n </span>\n </li>\n );\n })}\n </ul>\n ) : reachable.length > 0 ? (\n <div className=\"flex flex-col\">\n <p className=\"pl-3 text-sm text-doom-dim\">\n {`${reachable.length} available ${reachable.length === 1 ? 'tool' : 'tools'}, not in context`}\n </p>\n <ul aria-label={`${item.name} reachable tools`} className=\"flex flex-col\">\n {reachable.map((tool) => (\n <li key={tool.name} className=\"flex min-w-0\">\n <Button\n variant=\"ghost\"\n size=\"card\"\n data-testid={`context-mcp-reachable-${item.name}-${tool.name}`}\n title=\"open the tool's description and schema\"\n disabled={sessionId === null}\n onClick={() => {\n if (sessionId !== null)\n setToolTarget({\n sessionId,\n server: item.name,\n tool: tool.name,\n piName: tool.piName,\n inContext: false,\n });\n }}\n className=\"min-w-0 flex-1 flex-row items-center gap-2 rounded-none py-px pr-0 pl-3\"\n >\n <abbr\n title=\"tool\"\n className=\"w-3 shrink-0 text-2xs font-semibold text-doom-violet no-underline\"\n >\n T\n </abbr>\n <span className=\"min-w-0 flex-1 truncate text-left text-base text-doom-text\">\n {tool.piName ?? tool.name}\n </span>\n <span\n title=\"what the schema would cost if added to context directly\"\n className=\"w-14 shrink-0 text-right text-sm text-doom-dim\"\n >\n {tool.tokens === undefined ? '(-)' : `(~${tool.tokens.toLocaleString()})`}\n </span>\n </Button>\n </li>\n ))}\n </ul>\n </div>\n ) : (\n <p className=\"pl-3 text-sm text-doom-dim\">no tools or skills reported</p>\n )}\n </li>\n );\n })}\n </ul>\n </section>\n )}\n <McpToolDetailDialog target={toolTarget} onClose={() => setToolTarget(null)} />\n <Dialog\n open={selected !== null}\n onOpenChange={(open) => {\n if (!open) {\n closePendingTab();\n setTarget(null);\n }\n }}\n >\n <DialogContent data-testid=\"mcp-authorization-dialog\" onInteractOutside={(event) => event.preventDefault()}>\n <DialogHeader className=\"items-start px-4 py-4 sm:px-5\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\">\n <DialogTitle className=\"break-words leading-snug\">\n {server?.state === 'connected' ? 'Manage' : 'Authorize'} {selected?.name}\n </DialogTitle>\n <DialogDescription className=\"max-w-2xl\">\n {server?.state === 'connected'\n ? 'Disconnect this session without deleting saved credentials, or reauthorize to sign in again.'\n : \"Complete sign-in in the provider's tab. You can also open or copy the link below.\"}\n </DialogDescription>\n </div>\n </DialogHeader>\n <DialogBody className=\"px-4 py-4 sm:px-5 sm:py-5\">\n <output className=\"text-sm text-doom-dim\">\n {server?.state === 'connected'\n ? 'Authorization complete. This server is connected.'\n : server?.state === 'closed'\n ? 'Disconnected from this session. Saved credentials were kept.'\n : authorizationUrl\n ? 'Waiting for you to complete authorization.'\n : server?.state === 'failed'\n ? 'Connection failed. Retry authorization; details are in the session transcript.'\n : server\n ? 'Preparing the authorization link...'\n : 'This server is no longer available in the session.'}\n </output>\n {popupBlocked ? (\n <p className=\"text-sm text-doom-dim\">\n The browser blocked the new tab. Open the link below when it is ready.\n </p>\n ) : null}\n {authorizationUrl ? (\n <div className=\"flex flex-col gap-2\">\n <Input\n aria-label=\"OAuth authorization URL\"\n readOnly\n value={authorizationUrl}\n onFocus={(event) => event.currentTarget.select()}\n />\n <a\n href={authorizationUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-base font-medium text-doom-blue underline underline-offset-2\"\n >\n open authorization page\n </a>\n <Button variant=\"outline\" size=\"xs\" onClick={() => void copyLink()}>\n copy link\n </Button>\n </div>\n ) : null}\n {copyFeedback ? <output className=\"text-sm text-doom-dim\">{copyFeedback}</output> : null}\n </DialogBody>\n <DialogFooter className=\"flex-wrap justify-end border-t border-doom-border-soft px-4 py-3 sm:px-5\">\n {server?.state === 'connected' && selected ? (\n <Button\n variant=\"outline\"\n size=\"md\"\n onClick={() => {\n closePendingTab();\n setCopyFeedback('');\n setPopupBlocked(false);\n sendSessionFrame(selected.sessionId, { type: 'prompt', message: `/mcp disconnect ${selected.name}` });\n }}\n >\n disconnect\n </Button>\n ) : null}\n {(server?.state === 'failed' || server?.state === 'connected' || server?.state === 'closed') && selected ? (\n <Button size=\"md\" onClick={() => authorize(selected.name)}>\n {server.state === 'failed' ? 'retry authorization' : 'reauthorize'}\n </Button>\n ) : null}\n <Button\n variant=\"ghost\"\n size=\"md\"\n onClick={() => {\n closePendingTab();\n setTarget(null);\n }}\n >\n close\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","import { defineFill } from '@agimon-ai/po-core/web';\n\nimport { McpSessionAuthSection } from './_components/McpSessionAuthSection';\nexport default defineFill({ component: McpSessionAuthSection });\n","import { defineSessionStore, type WebPluginRuntime } from '@agimon-ai/po-core/web';\n\nexport type { McpAppOpenResult } from '../../../../../../types/webMcp';\n\ninterface AppRuntimeBinding {\n runtime: WebPluginRuntime | null;\n}\n\nexport const mcpAppRuntime = defineSessionStore<AppRuntimeBinding>({ runtime: null });\n\n/** Session mount lifecycle owns the authenticated RPC capability and drops it on unload. */\nexport function startMcpAppRuntime(runtime: WebPluginRuntime): () => void {\n const mount = runtime.mount;\n if (mount?.scope !== 'session') throw new Error('MCP Apps require a session runtime mount');\n mcpAppRuntime.update(mount.sessionId, () => ({ runtime }));\n return () => {\n if (mcpAppRuntime.select(mcpAppRuntime.store.state, mount.sessionId).runtime === runtime) {\n mcpAppRuntime.drop(mount.sessionId);\n }\n };\n}\n","import { defineWebLifecycle } from '@agimon-ai/po-core/web';\n\nimport { startMcpAppRuntime } from '../tool/_lib/mcpAppRuntime';\n\nexport default defineWebLifecycle(startMcpAppRuntime);\n","import type { McpResultBlock } from '../../../../../../types/webMcp';\n\n/**\n * Pure view logic for MCP tool cards. MCP tools are registered under `<server>_<tool>`,\n * so the plugin recognises a call by the server names the session publishes.\n */\n\n/**\n * The footer status the session half publishes (src/constants/piMcp.ts\n * MCP_STATUS_KEY). Duplicated because the browser half may import only\n * src/types and src/constants; a test keeps the two literals equal.\n */\nexport const MCP_STATUS_KEY = 'doom-mcp';\nconst SERVER_SEPARATOR = ',';\nconst PI_NAME_SEPARATOR = '_';\nconst MAX_ARGUMENTS = 3;\n/** Text lines kept in the collapsed result, before the card is expanded. */\nconst COLLAPSED_RESULT_LINES = 12;\n\nexport interface McpToolIdentity {\n server: string;\n tool: string;\n}\n\n/** The server names the session reports, in the order it listed them. */\nexport function mcpServers(statuses: Readonly<Record<string, string>>): string[] {\n const raw = statuses[MCP_STATUS_KEY];\n if (raw === undefined) return [];\n return raw\n .split(SERVER_SEPARATOR)\n .map((name) => name.trim())\n .filter((name) => name.length > 0);\n}\n\n/**\n * Splits a Pi tool name into its MCP server and tool. The longest server\n * prefix wins so `github_enterprise_search` belongs to `github_enterprise`\n * when both it and `github` are configured.\n */\nexport function matchMcpTool(toolName: string, statuses: Readonly<Record<string, string>>): McpToolIdentity | null {\n let best: McpToolIdentity | null = null;\n for (const server of mcpServers(statuses)) {\n const prefix = `${server}${PI_NAME_SEPARATOR}`;\n if (!toolName.startsWith(prefix) || toolName.length === prefix.length) continue;\n if (best === null || server.length > best.server.length) {\n best = { server, tool: toolName.slice(prefix.length) };\n }\n }\n return best;\n}\n\n/** The identity the result details carry, which the tool wrote itself and is exact. */\nexport function mcpIdentityFromDetails(details: unknown): McpToolIdentity | null {\n if (typeof details !== 'object' || details === null) return null;\n const record = details as { server?: unknown; tool?: unknown };\n if (typeof record.server !== 'string' || typeof record.tool !== 'string') return null;\n return { server: record.server, tool: record.tool };\n}\n\nfunction argumentValue(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n if (value === null) return 'null';\n if (Array.isArray(value)) return `[${value.length}]`;\n return '{…}';\n}\n\n/** The first few arguments as `key=value`, with a count for the rest. */\nexport function mcpArgumentSummary(params: Record<string, unknown>): string {\n const entries = Object.entries(params);\n const shown = entries.slice(0, MAX_ARGUMENTS).map(([key, value]) => `${key}=${argumentValue(value)}`);\n if (entries.length > shown.length) shown.push(`+${entries.length - shown.length}`);\n return shown.join(' · ');\n}\n\nexport type McpStatusTone = 'running' | 'ok' | 'error' | 'hint';\n\nexport interface McpResultView {\n lines: string[];\n status: { glyph: string; tone: McpStatusTone; text: string } | null;\n}\n\n/** The result body as renderMcpResult lays it out: text lines, then one status line. */\nexport function mcpResultView(input: {\n output: string;\n expanded: boolean;\n isPartial: boolean;\n isError: boolean;\n}): McpResultView {\n const all = input.output.split('\\n');\n while (all.length > 0 && all.at(-1)?.trim() === '') all.pop();\n const lines = input.expanded ? all : all.slice(0, COLLAPSED_RESULT_LINES);\n\n if (input.isPartial) return { lines, status: { glyph: '◐', tone: 'running', text: 'running' } };\n if (input.isError) return { lines, status: { glyph: '✗', tone: 'error', text: 'failed' } };\n if (!input.expanded && all.length > lines.length) {\n return { lines, status: { glyph: '…', tone: 'hint', text: `${all.length - lines.length} more line(s)` } };\n }\n if (lines.length === 0) return { lines, status: { glyph: '✓', tone: 'ok', text: 'done' } };\n return { lines, status: null };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** One block of the result's details, kept only when its required fields are the strings the adapter wrote. */\nfunction mcpResultBlock(entry: unknown): McpResultBlock | null {\n if (!isRecord(entry)) return null;\n const text = (key: string): string | undefined => (typeof entry[key] === 'string' ? entry[key] : undefined);\n switch (entry.type) {\n case 'audio': {\n const data = text('data');\n const mimeType = text('mimeType');\n return data !== undefined && mimeType !== undefined ? { type: 'audio', data, mimeType } : null;\n }\n case 'resource_link': {\n const uri = text('uri');\n const name = text('name');\n if (uri === undefined || name === undefined) return null;\n const title = text('title');\n const description = text('description');\n const mimeType = text('mimeType');\n return {\n type: 'resource_link',\n uri,\n name,\n ...(title === undefined ? {} : { title }),\n ...(description === undefined ? {} : { description }),\n ...(mimeType === undefined ? {} : { mimeType }),\n };\n }\n case 'resource': {\n const uri = text('uri');\n if (uri === undefined) return null;\n const mimeType = text('mimeType');\n const content = text('text');\n const blob = text('blob');\n return {\n type: 'resource',\n uri,\n ...(mimeType === undefined ? {} : { mimeType }),\n ...(content === undefined ? {} : { text: content }),\n ...(blob === undefined ? {} : { blob }),\n };\n }\n case 'structured':\n return isRecord(entry.value) ? { type: 'structured', value: entry.value } : null;\n default:\n return null;\n }\n}\n\n/** The blocks beyond text the adapter attached to the result's details; malformed entries are dropped. */\nexport function mcpResultBlocks(details: unknown): McpResultBlock[] {\n if (!isRecord(details) || !Array.isArray(details.blocks)) return [];\n return details.blocks.flatMap((entry) => {\n const block = mcpResultBlock(entry);\n return block === null ? [] : [block];\n });\n}\n\nexport interface McpImageBlock {\n data: string;\n mimeType: string;\n}\n\n/** The image blocks of a result's content, which Pi carries beside the text. */\nexport function mcpImageBlocks(content: readonly unknown[]): McpImageBlock[] {\n return content.flatMap((block) => {\n if (!isRecord(block) || block.type !== 'image') return [];\n return typeof block.data === 'string' && typeof block.mimeType === 'string'\n ? [{ data: block.data, mimeType: block.mimeType }]\n : [];\n });\n}\n","const MAX_CSP_DOMAINS = 64;\nconst MAX_DOMAIN_LENGTH = 2048;\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/** Accept origins only, never CSP tokens, URL paths, credentials, or the host origin. */\nfunction origins(value: unknown, hostOrigin: string): string[] {\n if (value === undefined) return [];\n if (!Array.isArray(value) || value.length > MAX_CSP_DOMAINS) throw new Error('Invalid widget CSP domains');\n return value.map((domain: unknown) => {\n if (typeof domain !== 'string' || domain.length > MAX_DOMAIN_LENGTH) throw new Error('Invalid widget CSP domain');\n const parsed = new URL(domain);\n const wildcard = parsed.hostname.startsWith('*.');\n const host = new URL(hostOrigin);\n const includesHost =\n parsed.hostname === host.hostname || (wildcard && host.hostname.endsWith(parsed.hostname.slice(1)));\n if (\n !['https:', 'wss:'].includes(parsed.protocol) ||\n parsed.username ||\n parsed.password ||\n parsed.pathname !== '/' ||\n parsed.search ||\n parsed.hash ||\n includesHost ||\n parsed.hostname === 'localhost' ||\n /^(127\\.|0\\.|\\[?::1\\]?)/u.test(parsed.hostname) ||\n /[\\s;'\"<>]/u.test(domain)\n )\n throw new Error('Unsafe widget CSP domain');\n return parsed.origin;\n });\n}\n\nexport function mcpAppCsp(metadata: unknown, hostOrigin: string): string {\n const meta = record(metadata);\n const ui = record(meta?.ui);\n if (meta?.ui !== undefined && ui === undefined) throw new Error('Invalid widget UI metadata');\n // A present standard field always wins, including malformed values (fail closed).\n const standard = ui !== undefined && 'csp' in ui;\n const raw = standard ? ui.csp : meta?.['openai/widgetCSP'];\n const csp = raw === undefined ? {} : record(raw);\n if (csp === undefined) throw new Error('Invalid widget CSP');\n const resource = origins(csp[standard ? 'resourceDomains' : 'resource_domains'], hostOrigin).join(' ');\n const connect = origins(csp[standard ? 'connectDomains' : 'connect_domains'], hostOrigin).join(' ');\n // Nested frames, forms, base URLs, workers and navigation privileges are not admitted.\n return [\n \"default-src 'none'\",\n `script-src 'unsafe-inline' ${resource}`,\n `style-src 'unsafe-inline' ${resource}`,\n `img-src data: blob: ${resource}`,\n `font-src data: ${resource}`,\n `media-src blob: ${resource}`,\n `connect-src ${connect || \"'none'\"}`,\n \"frame-src 'none'\",\n \"child-src 'none'\",\n \"worker-src 'none'\",\n \"object-src 'none'\",\n \"base-uri 'none'\",\n \"form-action 'none'\",\n ].join('; ');\n}\n\nfunction escapeAttribute(value: string): string {\n return value.replaceAll('&', '&amp;').replaceAll('\"', '&quot;').replaceAll('<', '&lt;');\n}\n\ntype HostTheme = 'light' | 'dark';\n\n/** The theme a host message carries, from either bridge. Serialized into frames, so it stays self-contained. */\nexport function mcpAppHostTheme(data: unknown): HostTheme | undefined {\n const message = data as {\n channel?: unknown;\n globals?: { theme?: unknown } | null;\n jsonrpc?: unknown;\n method?: unknown;\n params?: { theme?: unknown } | null;\n } | null;\n const theme =\n message?.channel === 'po.openai'\n ? message.globals?.theme\n : message?.jsonrpc === '2.0' && message.method === 'ui/notifications/host-context-changed'\n ? message.params?.theme\n : undefined;\n return theme === 'light' || theme === 'dark' ? theme : undefined;\n}\n\n/**\n * Bundled trusted code, runs inside the App document. Waits for the App's own\n * <html> attributes, which the parser merges only where the root has none, so\n * an App-chosen class or data-theme wins until the host theme changes.\n */\nexport function widgetThemeBootstrap(hostTheme: (data: unknown) => HostTheme | undefined, initial: HostTheme): void {\n const root = document.documentElement;\n let theme = initial;\n let changed = false;\n const settle = (): void => {\n if (!root.classList.contains('light') && !root.classList.contains('dark')) root.classList.add(theme);\n if (root.getAttribute('data-theme') === null) root.setAttribute('data-theme', theme);\n };\n const follow = (): void => {\n root.classList.remove('light', 'dark');\n root.classList.add(theme);\n const current = root.getAttribute('data-theme');\n if (current === null || current === 'light' || current === 'dark') root.setAttribute('data-theme', theme);\n root.style.colorScheme = theme;\n };\n window.addEventListener('message', (event: MessageEvent<unknown>) => {\n const next = event.source === parent ? hostTheme(event.data) : undefined;\n if (next === undefined) return;\n theme = next;\n changed = true;\n if (document.readyState !== 'loading') follow();\n });\n if (document.readyState !== 'loading') settle();\n else\n document.addEventListener('readystatechange', () => {\n if (document.readyState === 'interactive') {\n if (changed) follow();\n else settle();\n }\n });\n}\n\n/** Bundled trusted code, runs in an opaque relay separate from the untrusted App. */\nfunction relayBootstrap(hostTheme: (data: unknown) => HostTheme | undefined): void {\n let configured = false;\n // The relay canvas must match the App's color scheme or the browser paints it opaque.\n const follow = (data: unknown): void => {\n const theme = hostTheme(data);\n if (theme !== undefined) document.documentElement.style.colorScheme = theme;\n };\n window.addEventListener('message', (event: MessageEvent<unknown>) => {\n if (event.source !== parent || configured || event.ports.length !== 1) return;\n const config = event.data as { html: string; policy: string; protocol: string };\n if (typeof config?.html !== 'string' || typeof config.policy !== 'string') return;\n configured = true;\n const port = event.ports[0]!;\n const inner = document.createElement('iframe');\n inner.title = 'MCP App content';\n inner.setAttribute('sandbox', 'allow-scripts');\n inner.setAttribute('csp', config.policy);\n inner.setAttribute(\n 'allow',\n \"camera 'none'; microphone 'none'; geolocation 'none'; clipboard-read 'none'; clipboard-write 'none'\",\n );\n inner.style.cssText = 'width:100%;height:100%;border:0;display:block';\n let loaded = false;\n let revoked = false;\n const revoke = (): void => {\n if (revoked) return;\n revoked = true;\n inner.remove();\n port.postMessage({ type: 'revoked' });\n port.close();\n };\n inner.addEventListener('load', () => {\n if (loaded) revoke();\n loaded = true;\n });\n let messageWindow = Date.now();\n let messageCount = 0;\n window.addEventListener('message', (childEvent: MessageEvent<unknown>) => {\n if (revoked || childEvent.source !== inner.contentWindow) return;\n try {\n const encoded = JSON.stringify(childEvent.data);\n if (encoded === undefined || new TextEncoder().encode(encoded).byteLength > 65536) return revoke();\n const now = Date.now();\n if (now - messageWindow >= 1000) {\n messageWindow = now;\n messageCount = 0;\n }\n if (++messageCount > 128) return revoke();\n } catch {\n return revoke();\n }\n // window.openai is in every App, so its channel reaches the host port whatever the protocol.\n const openai = (childEvent.data as { channel?: unknown } | null)?.channel === 'po.openai';\n if (config.protocol === 'mcp' && !openai) parent.postMessage(childEvent.data, '*');\n else port.postMessage({ type: 'legacy', data: childEvent.data });\n });\n // The parent alone owns the other end of this channel. No origin-based trust.\n port.onmessage = (hostEvent: MessageEvent<unknown>) => {\n if (revoked) return;\n follow(hostEvent.data);\n inner.contentWindow?.postMessage(hostEvent.data, '*');\n };\n window.addEventListener('message', (hostEvent: MessageEvent<unknown>) => {\n if (!revoked && hostEvent.source === parent && config.protocol === 'mcp') {\n const data = hostEvent.data as { jsonrpc?: string } | null;\n if (data?.jsonrpc !== '2.0') return;\n follow(data);\n inner.contentWindow?.postMessage(data, '*');\n }\n });\n port.start();\n inner.srcdoc = config.html;\n document.body.append(inner);\n port.postMessage({ type: 'ready' });\n });\n}\n\nexport function mcpAppRelayHtml(policy: string, theme: HostTheme = 'light'): string {\n // frame-src allows only srcdoc/about, not a host route or a remote sandbox URL.\n const relayPolicy = policy\n .replace(\"frame-src 'none'\", 'frame-src about:')\n .replace(\"child-src 'none'\", 'child-src about:');\n return `<!doctype html><html style=\"color-scheme:${theme}\"><meta http-equiv=\"Content-Security-Policy\" content=\"${escapeAttribute(relayPolicy)}\"><style>html,body{margin:0;height:100%;overflow:hidden}</style><script>(${relayBootstrap.toString()})(${mcpAppHostTheme.toString()})</script>`;\n}\n\n/** No host <html> is injected, so the App's own root attributes survive parsing. */\nexport function mcpAppDocument(html: string, policy: string, bootstrap = '', theme: HostTheme = 'light'): string {\n const themeScript = `<script>(${widgetThemeBootstrap.toString()})(${mcpAppHostTheme.toString()}, ${JSON.stringify(theme)})</script>`;\n return `<!doctype html><meta http-equiv=\"Content-Security-Policy\" content=\"${escapeAttribute(policy)}\"><meta name=\"color-scheme\" content=\"${theme}\">${themeScript}${bootstrap}${html}`;\n}\n\n/** Required CSP enforcement must survive self-navigation, not only initial srcdoc. */\nexport function supportsMcpAppSandbox(): boolean {\n return typeof HTMLIFrameElement !== 'undefined' && 'csp' in HTMLIFrameElement.prototype;\n}\n","interface LegacyGlobals {\n toolInput: Record<string, unknown>;\n toolOutput: unknown;\n toolResponseMetadata: Record<string, unknown>;\n widgetState: unknown;\n theme: 'light' | 'dark';\n locale: string;\n displayMode: 'inline';\n maxHeight: number;\n userAgent: { device: { type: 'desktop' | 'mobile' }; capabilities: { hover: boolean; touch: boolean } };\n safeArea: { insets: { top: number; right: number; bottom: number; left: number } };\n}\n\nfunction bootstrap(initial: LegacyGlobals): void {\n const channel = 'po.openai';\n const requestTimeout = 60_000;\n const pending = new Map<number, { resolve(value: unknown): void; reject(error: Error): void; timer: number }>();\n let sequence = 0;\n let globals = initial;\n const update = (patch: Partial<LegacyGlobals>): void => {\n globals = { ...globals, ...patch };\n window.dispatchEvent(new CustomEvent('openai:set_globals', { detail: { globals: patch } }));\n };\n const request = (method: string, input: unknown): Promise<unknown> => {\n if (pending.size >= 32) return Promise.reject(new Error('Too many pending widget requests'));\n const id = ++sequence;\n return new Promise((resolve, reject) => {\n const timer = window.setTimeout(() => {\n pending.delete(id);\n reject(new Error('Widget request timed out'));\n }, requestTimeout);\n pending.set(id, { resolve, reject, timer });\n parent.postMessage({ channel, id, method, input }, '*');\n });\n };\n const api = {\n get toolInput() {\n return globals.toolInput;\n },\n get toolOutput() {\n return globals.toolOutput;\n },\n get toolResponseMetadata() {\n return globals.toolResponseMetadata;\n },\n get widgetState() {\n return globals.widgetState;\n },\n get theme() {\n return globals.theme;\n },\n get locale() {\n return globals.locale;\n },\n get displayMode() {\n return globals.displayMode;\n },\n get maxHeight() {\n return globals.maxHeight;\n },\n get safeArea() {\n return globals.safeArea;\n },\n get userAgent() {\n return globals.userAgent;\n },\n callTool: (name: string, args: Record<string, unknown> = {}) => request('callTool', { name, arguments: args }),\n setWidgetState: (state: unknown) => {\n // Immediate local state, with await-compatible durable persistence.\n update({ widgetState: state });\n return request('setState', { state });\n },\n sendFollowUpMessage: (input: { prompt: string }) => request('followUp', input),\n requestDisplayMode: () => Promise.resolve({ mode: 'inline' }),\n openExternal: (input: { href: string }) => request('openLink', { url: input.href }),\n requestClose: () => request('close', {}),\n notifyIntrinsicHeight: (height: number) => request('height', { height }),\n };\n Object.defineProperty(window, 'openai', { value: Object.freeze(api), configurable: false, writable: false });\n window.addEventListener('message', (event: MessageEvent<unknown>) => {\n if (event.source !== parent) return;\n const message = event.data as {\n channel?: string;\n id?: number;\n error?: string;\n result?: unknown;\n globals?: Partial<LegacyGlobals>;\n };\n if (message?.channel !== channel) return;\n if (message.globals !== undefined) update(message.globals);\n if (message.id === undefined) return;\n const callback = pending.get(message.id);\n if (callback === undefined) return;\n pending.delete(message.id);\n clearTimeout(callback.timer);\n if (typeof message.error === 'string') callback.reject(new Error(message.error));\n else callback.resolve(message.result);\n });\n parent.postMessage({ channel, method: 'initialized', input: {} }, '*');\n document.addEventListener(\n 'DOMContentLoaded',\n () => {\n update(globals);\n const observer = new ResizeObserver(() => {\n const height = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);\n parent.postMessage({ channel, method: 'height', input: { height } }, '*');\n });\n observer.observe(document.body);\n window.addEventListener('pagehide', () => observer.disconnect(), { once: true });\n },\n { once: true },\n );\n}\n\nexport function mcpOpenAiScript(globals: LegacyGlobals): string {\n const encoded = JSON.stringify(globals)\n .replaceAll('<', '\\\\u003c')\n .replaceAll('\\u2028', '\\\\u2028')\n .replaceAll('\\u2029', '\\\\u2029');\n return `<script>(${bootstrap.toString()})(${encoded})</script>`;\n}\n","import type { WebPluginRuntime } from '@agimon-ai/po-core/web';\nimport { AppBridge, PostMessageTransport } from '@modelcontextprotocol/ext-apps/app-bridge';\nimport { useStore } from '@tanstack/react-store';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { type McpAppOpenResult, mcpAppRuntime } from '../_lib/mcpAppRuntime';\nimport { mcpAppCsp, mcpAppDocument, mcpAppRelayHtml, supportsMcpAppSandbox } from '../_lib/mcpAppSandbox';\nimport { mcpOpenAiScript } from '../_lib/mcpOpenAiBootstrap';\n\ntype CallToolResult = Awaited<ReturnType<NonNullable<AppBridge['oncalltool']>>>;\n\nconst DEFAULT_HEIGHT = 320;\nconst MAX_HEIGHT = 1200;\nconst MIN_HEIGHT = 80;\nconst OPEN_TIMEOUT = 15_000;\nconst LEGACY_CHANNEL = 'po.openai';\n\nfunction currentTheme(): 'light' | 'dark' {\n const scheme = document.documentElement.style.colorScheme;\n if (scheme === 'light' || scheme === 'dark') return scheme;\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : 'The MCP App could not complete this request';\n}\n\nfunction object(value: unknown): Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid App request');\n return value as Record<string, unknown>;\n}\n\nfunction invoke(runtime: WebPluginRuntime, sessionId: string, method: string, input: unknown): Promise<unknown> {\n return runtime.invokeServerMethod({ mount: { scope: 'session', sessionId }, service: 'mcp.apps', method, input });\n}\n\nasync function openLink(value: unknown): Promise<Record<string, never>> {\n if (typeof value !== 'string') throw new Error('Invalid external link');\n const url = new URL(value);\n if (url.protocol !== 'https:' || url.username || url.password)\n throw new Error('Only HTTPS external links are supported');\n if (!window.confirm(`Open this external link?\\n${url.href}`)) throw new Error('Opening the link was declined');\n const opened = window.open(url.href, '_blank', 'noopener,noreferrer');\n // noopener may deliberately return null, so it is not evidence of a blocked popup.\n if (opened !== null) opened.opener = null;\n return {};\n}\n\ninterface FrameProps {\n runtime: WebPluginRuntime;\n sessionId: string;\n toolCallId: string;\n data: McpAppOpenResult;\n savedState: unknown;\n saveState: (state: unknown) => void;\n onClose: () => void;\n}\n\nfunction AppFrame({ runtime, sessionId, toolCallId, data, savedState, saveState, onClose }: FrameProps) {\n const frameRef = useRef<HTMLIFrameElement>(null);\n const [height, setHeight] = useState(DEFAULT_HEIGHT);\n const [failure, setFailure] = useState<string | null>(null);\n const [ready, setReady] = useState(false);\n const [initialState] = useState(() => savedState);\n\n useEffect(() => {\n const frame = frameRef.current;\n if (frame === null || frame.contentWindow === null) return;\n let live = true;\n let bridge: AppBridge | undefined;\n const channels = new MessageChannel();\n const request = (method: string, input: Record<string, unknown>) => {\n if (!live) return Promise.reject(new Error('MCP App is closed'));\n return invoke(runtime, sessionId, method, { ...input, leaseId: data.leaseId });\n };\n const resize = (value: unknown): void => {\n if (typeof value === 'number' && Number.isFinite(value)) {\n setHeight(Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, Math.ceil(value))));\n }\n };\n const fail = (error: unknown): void => {\n if (!live) return;\n setFailure(errorText(error));\n live = false;\n frame.srcdoc = '';\n void requestCloseLease().catch((closeError: unknown) => {\n setFailure(`${errorText(error)}. Closing the App lease failed: ${errorText(closeError)}`);\n });\n };\n const requestCloseLease = (): Promise<unknown> => invoke(runtime, sessionId, 'close', { leaseId: data.leaseId });\n const timeout = window.setTimeout(() => fail(new Error('MCP App initialization timed out')), OPEN_TIMEOUT);\n const markReady = (): void => {\n if (!live) return;\n clearTimeout(timeout);\n setReady(true);\n };\n const callTool = async (name: unknown, args: unknown): Promise<CallToolResult> => {\n if (data.readOnly) throw new Error('Enable interactions in the conversation before calling tools');\n if (typeof name !== 'string') throw new Error('Invalid App tool name');\n const result = await request('callTool', { name, arguments: object(args ?? {}) });\n return result as CallToolResult;\n };\n const persist = async (state: unknown): Promise<Record<string, never>> => {\n await request('setState', { state });\n saveState(state);\n return {};\n };\n const followUp = async (prompt: unknown): Promise<Record<string, never>> => {\n if (data.readOnly) throw new Error('Enable interactions in the conversation before sending a follow-up');\n if (typeof prompt !== 'string') throw new Error('Invalid App follow-up');\n await request('followUp', { prompt });\n return {};\n };\n const close = async (): Promise<Record<string, never>> => {\n await request('close', {});\n onClose();\n return {};\n };\n const theme = currentTheme();\n const globals = {\n toolInput: data.args,\n toolOutput: data.result.structuredContent ?? null,\n toolResponseMetadata: data.result._meta ?? {},\n widgetState: initialState,\n theme,\n locale: navigator.language,\n displayMode: 'inline' as const,\n maxHeight: MAX_HEIGHT,\n safeArea: { insets: { top: 0, right: 0, bottom: 0, left: 0 } },\n userAgent: {\n device: { type: window.matchMedia('(pointer: coarse)').matches ? ('mobile' as const) : ('desktop' as const) },\n capabilities: { hover: window.matchMedia('(hover: hover)').matches, touch: navigator.maxTouchPoints > 0 },\n },\n };\n try {\n const policy = mcpAppCsp(data.resourceMeta, location.origin);\n if (data.protocol === 'mcp') {\n bridge = new AppBridge(\n null,\n { name: 'Po', version: '1' },\n {\n ...(data.readOnly ? {} : { serverTools: {}, message: { text: {} } }),\n openLinks: {},\n },\n {\n hostContext: {\n theme,\n locale: navigator.language,\n displayMode: 'inline',\n availableDisplayModes: ['inline'],\n toolInfo: { id: toolCallId, tool: data.tool },\n },\n },\n );\n bridge.oncalltool = ({ name, arguments: args }) => callTool(name, args);\n bridge.onmessage = async ({ content }) => {\n if (content.some((block) => block.type !== 'text')) throw new Error('Only text follow-ups are supported');\n return followUp(content.map((block) => (block.type === 'text' ? block.text : '')).join('\\n'));\n };\n bridge.onopenlink = ({ url }) => openLink(url);\n bridge.onsizechange = ({ height: next }) => resize(next);\n bridge.onrequestdisplaymode = async () => ({ mode: 'inline' });\n bridge.onrequestteardown = () => {\n void close().catch(fail);\n };\n bridge.oninitialized = () => {\n void (async () => {\n await bridge!.sendToolInput({ arguments: data.args });\n await bridge!.sendToolResult(data.result as CallToolResult);\n markReady();\n })().catch(fail);\n };\n void bridge.connect(new PostMessageTransport(frame.contentWindow, frame.contentWindow)).catch(fail);\n }\n channels.port1.onmessage = (event: MessageEvent<unknown>) => {\n if (!live) return;\n const message = event.data as { type?: string; data?: unknown };\n if (message?.type === 'revoked') {\n fail(new Error('MCP App navigation was blocked; reopen it to continue'));\n return;\n }\n if (message?.type !== 'legacy') return;\n const legacy = message.data as { channel?: string; id?: number; method?: string; input?: unknown } | null;\n if (legacy?.channel !== LEGACY_CHANNEL) return;\n void (async () => {\n const input = object(legacy.input ?? {});\n switch (legacy.method) {\n case 'initialized': {\n markReady();\n // A theme change while the App document loaded reached no listener; this one runs after it.\n const loadedTheme = currentTheme();\n if (loadedTheme !== theme)\n channels.port1.postMessage({ channel: LEGACY_CHANNEL, globals: { theme: loadedTheme } });\n return {};\n }\n case 'height':\n resize(input.height);\n return {};\n case 'callTool':\n return callTool(input.name, input.arguments);\n case 'setState':\n return persist(input.state);\n case 'followUp':\n return followUp(input.prompt);\n case 'openLink':\n return openLink(input.url);\n case 'close':\n return close();\n default:\n throw new Error('Unsupported ChatGPT widget method');\n }\n })().then(\n (result) => {\n if (!live || legacy.id === undefined) return;\n // A widget's own call returns its result; replacing the rendered tool's output corrupts widgets that persist it.\n const returned =\n legacy.method === 'callTool' && data.protocol === 'openai' ? (result as CallToolResult) : undefined;\n channels.port1.postMessage({\n channel: LEGACY_CHANNEL,\n id: legacy.id,\n result,\n ...(returned === undefined\n ? {}\n : {\n globals: {\n toolOutput: returned.structuredContent ?? null,\n toolResponseMetadata: returned._meta ?? {},\n },\n }),\n });\n },\n (error: unknown) => {\n if (!live || legacy.id === undefined) return;\n channels.port1.postMessage({ channel: LEGACY_CHANNEL, id: legacy.id, error: errorText(error) });\n },\n );\n };\n channels.port1.start();\n const load = (): void => {\n frame.contentWindow?.postMessage(\n {\n html: mcpAppDocument(data.html, policy, mcpOpenAiScript(globals), theme),\n policy,\n protocol: data.protocol,\n },\n '*',\n [channels.port2],\n );\n };\n frame.addEventListener('load', load, { once: true });\n frame.srcdoc = mcpAppRelayHtml(policy, theme);\n const observer = new MutationObserver(() => {\n const nextTheme = currentTheme();\n bridge?.setHostContext({ theme: nextTheme });\n channels.port1.postMessage({ channel: LEGACY_CHANNEL, globals: { theme: nextTheme } });\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'style'],\n });\n return () => {\n live = false;\n clearTimeout(timeout);\n observer.disconnect();\n frame.removeEventListener('load', load);\n channels.port1.close();\n channels.port2.close();\n if (bridge !== undefined) void bridge.close().catch((error: unknown) => setFailure(errorText(error)));\n frame.srcdoc = '';\n };\n } catch (error) {\n fail(error);\n return () => {\n clearTimeout(timeout);\n channels.port1.close();\n channels.port2.close();\n };\n }\n }, [runtime, sessionId, toolCallId, data, initialState, saveState, onClose]);\n\n return (\n <div className=\"overflow-hidden rounded border border-doom-border-soft\" data-testid=\"mcp-inline-app\">\n {failure !== null ? (\n <p role=\"alert\" className=\"p-3 text-doom-dim\">\n {failure}\n </p>\n ) : null}\n {!ready && failure === null ? <output className=\"p-3 text-doom-faint\">Loading MCP App…</output> : null}\n <iframe\n ref={frameRef}\n title={`${data.tool.name} MCP App`}\n sandbox=\"allow-scripts\"\n referrerPolicy=\"no-referrer\"\n allow=\"camera 'none'; microphone 'none'; geolocation 'none'; clipboard-read 'none'; clipboard-write 'none'\"\n className={failure !== null ? 'hidden' : 'block w-full border-0'}\n style={{ height }}\n />\n </div>\n );\n}\n\nexport function McpInlineApp({ sessionId, toolCallId }: { sessionId: string | null; toolCallId: string }) {\n const runtime = useStore(mcpAppRuntime.store, (state) => mcpAppRuntime.select(state, sessionId).runtime);\n const [data, setData] = useState<McpAppOpenResult | null>(null);\n const [failure, setFailure] = useState<string | null>(null);\n const [activating, setActivating] = useState(false);\n const [actionFailure, setActionFailure] = useState<string | null>(null);\n const [closed, setClosed] = useState(false);\n const [widgetState, setWidgetState] = useState<unknown>(null);\n const saveState = useCallback((value: unknown) => setWidgetState(value), []);\n const close = useCallback(() => setClosed(true), []);\n\n useEffect(() => {\n if (runtime === null || sessionId === null || !supportsMcpAppSandbox()) return;\n let mounted = true;\n let leaseId: string | undefined;\n void invoke(runtime, sessionId, 'open', { toolCallId })\n .then((response) => {\n const opened = response as McpAppOpenResult;\n leaseId = opened.leaseId;\n if (!mounted) return invoke(runtime, sessionId, 'close', { leaseId });\n setWidgetState(opened.state);\n setData(opened);\n return undefined;\n })\n .catch((error: unknown) => {\n if (mounted) setFailure(errorText(error));\n });\n return () => {\n mounted = false;\n if (leaseId !== undefined) {\n void invoke(runtime, sessionId, 'close', { leaseId }).catch((error: unknown) => setFailure(errorText(error)));\n }\n };\n }, [runtime, sessionId, toolCallId]);\n\n if (closed) return <p className=\"text-doom-faint\">MCP App closed. Expand the card to view the tool result.</p>;\n if (!supportsMcpAppSandbox())\n return (\n <p className=\"text-doom-faint\">\n This browser cannot securely display MCP Apps. Expand the card to view the tool result.\n </p>\n );\n if (failure !== null)\n return (\n <p role=\"alert\" className=\"text-doom-dim\">\n MCP App unavailable: {failure}\n </p>\n );\n if (runtime === null || sessionId === null)\n return (\n <p className=\"text-doom-faint\">\n The interactive MCP App is unavailable in this view. Expand the card to view the tool result.\n </p>\n );\n if (data === null) return <output className=\"text-doom-faint\">Loading MCP App…</output>;\n\n const activate = (): void => {\n setActivating(true);\n setActionFailure(null);\n void invoke(runtime, sessionId, 'activate', { leaseId: data.leaseId })\n .then(() => {\n setData({ ...data, readOnly: false });\n })\n .catch((error: unknown) => setActionFailure(errorText(error)))\n .finally(() => setActivating(false));\n };\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between gap-2 text-doom-faint\">\n <span>{data.readOnly ? 'Read-only MCP App' : 'MCP App interactions enabled'}</span>\n {data.readOnly ? (\n <button\n type=\"button\"\n disabled={activating}\n onClick={activate}\n className=\"rounded border border-doom-border-soft px-2 py-1 text-doom-blue disabled:opacity-50\"\n >\n {activating ? 'Enabling…' : 'Enable interactions'}\n </button>\n ) : null}\n </div>\n {actionFailure !== null ? (\n <p role=\"alert\" className=\"text-doom-dim\">\n {actionFailure}\n </p>\n ) : null}\n <AppFrame\n key={`${data.leaseId}-${String(data.readOnly)}`}\n runtime={runtime}\n sessionId={sessionId}\n toolCallId={toolCallId}\n data={data}\n savedState={widgetState}\n saveState={saveState}\n onClose={close}\n />\n </div>\n );\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport {\n MessageItem,\n MessageItemBody,\n MessageItemHeader,\n MessageItemStatus,\n type StatusTone,\n SyntaxText,\n toolTone,\n} from '@agimon-ai/po-web-components';\n\nimport type { McpResultBlock } from '../../../../../../types/webMcp';\nimport {\n type McpStatusTone,\n matchMcpTool,\n mcpArgumentSummary,\n mcpIdentityFromDetails,\n mcpImageBlocks,\n mcpResultBlocks,\n mcpResultView,\n} from '../_lib/mcpToolMatch';\nimport { McpInlineApp } from './McpInlineApp';\n\nconst STATUS_TONE: Record<McpStatusTone, StatusTone> = {\n running: 'running',\n ok: 'ok',\n error: 'error',\n hint: 'neutral',\n};\n\n/** The Pi name split on its first underscore, for a call whose server the session has not named. */\nfunction fallbackIdentity(toolName: string): { server: string; tool: string } {\n const separator = toolName.indexOf('_');\n if (separator <= 0) return { server: toolName, tool: '' };\n return { server: toolName.slice(0, separator), tool: toolName.slice(separator + 1) };\n}\n\n/** One block beyond text the result carried: a link, an embedded resource, structured content, or audio. */\nfunction McpBlock({ block }: { block: McpResultBlock }) {\n switch (block.type) {\n case 'resource_link':\n return (\n <a\n href={block.uri}\n target=\"_blank\"\n rel=\"noreferrer\"\n data-testid=\"tool-result-mcp-link\"\n className=\"truncate text-doom-blue hover:underline\"\n title={block.description ?? block.uri}\n >\n {block.title ?? block.name}\n </a>\n );\n case 'resource':\n return block.text !== undefined ? (\n // A resource arrives without a name, so its grammar is whatever the\n // text itself gives away; anything unrecognised stays plain.\n <SyntaxText data-testid=\"tool-result-mcp-resource\" className=\"text-doom-dim\" text={block.text} />\n ) : (\n <span data-testid=\"tool-result-mcp-resource\" className=\"truncate text-doom-dim\">\n binary {block.mimeType ?? 'resource'} · {block.uri}\n </span>\n );\n case 'structured':\n return (\n <SyntaxText\n data-testid=\"tool-result-mcp-structured\"\n className=\"text-doom-dim\"\n grammar=\"json\"\n text={JSON.stringify(block.value, null, 2)}\n />\n );\n case 'audio':\n return (\n <span data-testid=\"tool-result-mcp-audio\" className=\"text-doom-dim\">\n audio · {block.mimeType}\n </span>\n );\n }\n}\n\n/**\n * The MCP tool's timeline item, the web half of renderMcpCall and\n * renderMcpResult: `mcp | server / tool · k=v` in the header; the text lines,\n * collapsed to twelve, then the images Pi carries beside the text, the\n * blocks the adapter put in the details, and one status line in the body.\n * A call that rendered an MCP App keeps its result behind the toggle, unless it failed.\n */\nexport function McpToolMessage({\n sessionId,\n toolCallId,\n toolName,\n args,\n result,\n output,\n running,\n isError,\n statuses,\n}: ToolMessageRenderProps) {\n const identity =\n mcpIdentityFromDetails(result?.details) ?? matchMcpTool(toolName, statuses) ?? fallbackIdentity(toolName);\n const summary = mcpArgumentSummary(args);\n const collapsed = mcpResultView({ output, expanded: false, isPartial: running, isError });\n const images = mcpImageBlocks(result?.content ?? []);\n const blocks = mcpResultBlocks(result?.details);\n const details = result?.details;\n const app = !running && details !== null && typeof details === 'object' && 'app' in details ? details.app : undefined;\n const hasApp =\n app !== null &&\n typeof app === 'object' &&\n 'version' in app &&\n app.version === 1 &&\n 'resourceUri' in app &&\n typeof app.resourceUri === 'string';\n const resultFirst = !hasApp || isError;\n\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable={!resultFirst || collapsed.status?.tone === 'hint'}>\n {({ expanded }) => {\n const view = expanded ? mcpResultView({ output, expanded: true, isPartial: running, isError }) : collapsed;\n const hint = view.status?.tone === 'hint';\n const showResult = resultFirst || expanded;\n return (\n <>\n <MessageItemHeader title=\"mcp\">\n <span data-testid=\"tool-call-mcp\" className=\"flex min-w-0 flex-1 items-center gap-1.5\">\n <span className=\"shrink-0 text-doom-dim\">{identity.server}</span>\n <span className=\"shrink-0 text-doom-faint\">/</span>\n <span className=\"shrink-0 text-doom-blue\">{identity.tool}</span>\n {summary ? <span className=\"min-w-0 flex-1 truncate text-doom-dim\">· {summary}</span> : null}\n </span>\n </MessageItemHeader>\n {hasApp ? (\n <MessageItemBody>\n <McpInlineApp key={`${sessionId}:${toolCallId}`} sessionId={sessionId} toolCallId={toolCallId} />\n </MessageItemBody>\n ) : null}\n {showResult && (view.lines.length > 0 || view.status !== null || images.length > 0 || blocks.length > 0) ? (\n <MessageItemBody\n data-testid=\"tool-result-mcp\"\n data-mcp-server={identity.server}\n className=\"flex flex-col gap-1\"\n >\n {view.lines.length > 0 ? (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-doom-dim\">{view.lines.join('\\n')}</pre>\n ) : null}\n {images.map((image, index) => (\n <img\n key={`${String(index)}-${image.mimeType}`}\n data-testid=\"tool-result-mcp-image\"\n src={`data:${image.mimeType};base64,${image.data}`}\n alt={`${identity.tool} result ${String(index + 1)}`}\n className=\"max-h-60 max-w-full self-start rounded border border-doom-border-soft\"\n />\n ))}\n {blocks.map((block, index) => (\n <McpBlock key={`${String(index)}-${block.type}`} block={block} />\n ))}\n {view.status ? (\n <MessageItemStatus\n data-testid=\"tool-result-mcp-status\"\n tone={STATUS_TONE[view.status.tone]}\n glyph={view.status.glyph}\n expands={hint}\n >\n {view.status.text}\n </MessageItemStatus>\n ) : null}\n </MessageItemBody>\n ) : null}\n </>\n );\n }}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/po-core/web';\n\nimport { McpToolMessage } from './_components/McpToolMessage';\nimport { matchMcpTool, mcpIdentityFromDetails } from './_lib/mcpToolMatch';\nexport default defineToolRenderer({\n tools: [],\n matches: (toolName, statuses, details) =>\n mcpIdentityFromDetails(details) !== null || matchMcpTool(toolName, statuses) !== null,\n message: McpToolMessage,\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineWebPlugin, type WebPluginContributions } from '@agimon-ai/po-core/web';\n\nimport repositorySettingsPanelMcp from '../src/extensions/workspaces/(frontend)/repository-settings-panel/mcp.web';\nimport fillMcpAuth from '../src/extensions/workspaces/sessions/(frontend)/fill/McpAuth.context.web';\nimport lifecycleStart from '../src/extensions/workspaces/sessions/(frontend)/lifecycle/start.web';\nimport toolMcp from '../src/extensions/workspaces/sessions/(frontend)/tool/mcp.web';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const webPlugin = defineWebPlugin({\n id: 'mcp',\n workspace: {\n get repositorySettingsPanel(): WebPluginContributions['repositorySettingsPanel'] { return repositorySettingsPanelMcp; },\n },\n session: {\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'context', id: 'mcp-auth' }, fillMcpAuth)]; },\n get start(): WebPluginContributions['start'] { return lifecycleStart; },\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['mcp'] }, toolMcp)]; },\n },\n});\n"],"mappings":"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"}
package/dist/index.cjs ADDED
@@ -0,0 +1,18 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_mcpCatalog = require("./mcpCatalog-6Tpt6Gqn.cjs");
3
+ //#region src/schemas/sessionConfig.ts
4
+ /** @deprecated Use `DOOM_MCP_SESSION_ENV_VAR` from extension contracts. */
5
+ const SESSION_ENV_VAR = require("@agimon-ai/po-core/mcpSession").DOOM_MCP_SESSION_ENV_VAR;
6
+ //#endregion
7
+ exports.DIRECT_TOOLS_ENV = require_mcpCatalog.DIRECT_TOOLS_ENV;
8
+ exports.NO_DIRECT_TOOLS = require_mcpCatalog.NO_DIRECT_TOOLS;
9
+ exports.PROXY_SERVER_NAME = require_mcpCatalog.PROXY_SERVER_NAME;
10
+ exports.SESSION_ENV_VAR = SESSION_ENV_VAR;
11
+ exports.buildMcpConfigGroups = require_mcpCatalog.buildMcpConfigGroups;
12
+ exports.definitionsCachePath = require_mcpCatalog.definitionsCachePath;
13
+ exports.readCachedCatalog = require_mcpCatalog.readCachedCatalog;
14
+ exports.readSessionConfig = require_mcpCatalog.readSessionConfig;
15
+ exports.sessionConfigEnvironment = require_mcpCatalog.sessionConfigEnvironment;
16
+ exports.toPiToolName = require_mcpCatalog.toPiToolName;
17
+
18
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["DOOM_MCP_SESSION_ENV_VAR"],"sources":["../src/schemas/sessionConfig.ts"],"sourcesContent":["import { DOOM_MCP_SESSION_ENV_VAR } from '@agimon-ai/po-core/mcpSession';\n\n/** @deprecated Use `DOOM_MCP_SESSION_ENV_VAR` from extension contracts. */\nexport const SESSION_ENV_VAR = DOOM_MCP_SESSION_ENV_VAR;\n"],"mappings":";;;;AAGA,MAAa,yDAAkBA,CAAAA,CAAAA"}
@@ -0,0 +1,89 @@
1
+ import { a as McpSessionConfig, i as McpConfigSource, n as McpConfigGroups, r as McpConfigGroupsInput, t as McpAllowlist } from "./mcpConfig-BYESy-zP.mjs";
2
+ import "@agimon-ai/po-core/mcpStatus";
3
+ import "@agimon-ai/po-core/mcpToolResolver";
4
+ import { McpToolInfo } from "@agimon-ai/mcp-proxy";
5
+ import "@agimon-ai/po-core/packageApi";
6
+ import "@modelcontextprotocol/server";
7
+ //#region src/services/configSources/index.d.ts
8
+ /** Wrapper entry used by non-Doom clients to expose `mcp-config.yaml` as one MCP. */
9
+ export declare const PROXY_SERVER_NAME = "mcp-proxy";
10
+ /**
11
+ * Resolves every config layer for this session and applies its domain allowlist.
12
+ *
13
+ * All returned layers go into one embedded `@agimon-ai/mcp-proxy` client container.
14
+ * The package is used as a library only: its wrapper MCP never becomes a Doom MCP
15
+ * server, so status, enable/disable, resources, and OAuth stay attached to each
16
+ * actual downstream server.
17
+ */
18
+ export declare function buildMcpConfigGroups(input: McpConfigGroupsInput): McpConfigGroups;
19
+ //#endregion
20
+ //#region src/types/mcpRuntime.d.ts
21
+ interface CatalogServer {
22
+ name: string;
23
+ tools: McpToolInfo[];
24
+ }
25
+ /** Server definitions from the previous run, available before any socket opens. */
26
+ interface CachedCatalog {
27
+ servers: CatalogServer[];
28
+ }
29
+ //#endregion
30
+ //#region src/services/mcpRuntime/index.d.ts
31
+ /**
32
+ * Definitions cache path shared by Doom's synchronous warm reader and mcp-proxy.
33
+ *
34
+ * Generated staging paths are deliberately absent: projected source content must
35
+ * invalidate a reused path, while identical portable content must survive a new
36
+ * private staging directory. Stable source origins are carried inside each cache
37
+ * key; format and merge behavior remain part of the ordered identity.
38
+ */
39
+ export declare function definitionsCachePath(configSources: readonly McpConfigSource[]): string;
40
+ /**
41
+ * Reads the catalog the previous run left behind.
42
+ *
43
+ * Synchronous on purpose: Pi has to be able to register these tools during
44
+ * extension install, before it takes its first turn, and awaiting a file read
45
+ * would let that turn start with an empty tool set. A miss is normal on a first
46
+ * run and resolves to an empty catalog rather than an error.
47
+ *
48
+ * The file path is content-addressed from the current ordered layers, and its proxy
49
+ * version is checked before any schema is registered. Servers filtered out of the
50
+ * current configuration are also excluded later by `McpCatalog.seed`.
51
+ */
52
+ export declare function readCachedCatalog(configSources: readonly McpConfigSource[], cachePathFor?: (sources: readonly McpConfigSource[]) => string): CachedCatalog;
53
+ //#endregion
54
+ //#region src/services/sessionConfig/index.d.ts
55
+ /**
56
+ * Resolves what this session should connect to.
57
+ *
58
+ * Every field falls back to a working default so the extension is usable outside
59
+ * po: a bare Pi session in a repository still gets that repository's
60
+ * `.mcp.json` with no allowlist. A malformed value is treated as absent rather
61
+ * than fatal, because losing MCP is better than losing the session.
62
+ */
63
+ export declare function readSessionConfig(env?: Readonly<Record<string, string | undefined>>, defaultRepoRoot?: string): McpSessionConfig;
64
+ /** Serializes the configuration for the Pi child process po launches. */
65
+ export declare function sessionConfigEnvironment(config: McpSessionConfig): Record<string, string>;
66
+ //#endregion
67
+ //#region src/schemas/directTools.d.ts
68
+ /** Environment variable carrying a child agent's MCP tool selection. */
69
+ export declare const DIRECT_TOOLS_ENV = "MCP_DIRECT_TOOLS";
70
+ /** Explicit "no MCP tools", distinct from an unset variable meaning "no limit". */
71
+ export declare const NO_DIRECT_TOOLS = "__none__";
72
+ //#endregion
73
+ //#region src/schemas/sessionConfig.d.ts
74
+ /** @deprecated Use `DOOM_MCP_SESSION_ENV_VAR` from extension contracts. */
75
+ export declare const SESSION_ENV_VAR = "DOOM_MCP_SESSION";
76
+ //#endregion
77
+ //#region src/services/mcpCatalog/index.d.ts
78
+ /**
79
+ * Pi's tool name for a downstream tool.
80
+ *
81
+ * Always prefixed, matching what `pi-mcp-adapter` produced by default. Tool names
82
+ * are a contract with agent frontmatter selectors, transcripts, and user habit, so
83
+ * they stay stable across the swap rather than following mcp-proxy's internal
84
+ * scheme, which prefixes only on a clash.
85
+ */
86
+ export declare function toPiToolName(serverName: string, toolName: string): string;
87
+ //#endregion
88
+ export type { CachedCatalog, McpAllowlist, McpConfigGroups, McpConfigSource, McpSessionConfig };
89
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/services/configSources/index.ts","../src/types/mcpRuntime.ts","../src/services/mcpRuntime/index.ts","../src/services/sessionConfig/index.ts","../src/schemas/directTools.ts","../src/schemas/sessionConfig.ts","../src/services/mcpCatalog/index.ts"],"mappings":";;;;;;;;qBAWa;;;;;;;;;wBA2MG,qBAAqB,OAAO,uBAAuB;;;UCpNlD;EACf;EACA,OAAO;;;UAIQ;EACf,SAAS;;;;;;;;;;;;wBCsEK,qBAAqB,wBAAwB;;;;;;;;;;;;;wBAiC7C,kBACd,wBAAwB,mBACxB,gBAAe,kBAAkB,+BAChC;;;;;;;;;;;wBC/Ea,kBACd,MAAK,SAAS,qCACd,2BACC;;wBAkDa,yBAAyB,QAAQ,mBAAmB;;;;qBCxFvD;;qBAGA;;;;qBCDA;;;;;;;;;;;wBCqIG,aAAa,oBAAoB"}
package/dist/index.mjs ADDED
@@ -0,0 +1,9 @@
1
+ import { _ as buildMcpConfigGroups, c as NO_DIRECT_TOOLS, f as definitionsCachePath, g as PROXY_SERVER_NAME, h as readCachedCatalog, l as readSessionConfig, o as toPiToolName, s as DIRECT_TOOLS_ENV, u as sessionConfigEnvironment } from "./mcpCatalog-SlqWS-sb.mjs";
2
+ import { DOOM_MCP_SESSION_ENV_VAR } from "@agimon-ai/po-core/mcpSession";
3
+ //#region src/schemas/sessionConfig.ts
4
+ /** @deprecated Use `DOOM_MCP_SESSION_ENV_VAR` from extension contracts. */
5
+ const SESSION_ENV_VAR = DOOM_MCP_SESSION_ENV_VAR;
6
+ //#endregion
7
+ export { DIRECT_TOOLS_ENV, NO_DIRECT_TOOLS, PROXY_SERVER_NAME, SESSION_ENV_VAR, buildMcpConfigGroups, definitionsCachePath, readCachedCatalog, readSessionConfig, sessionConfigEnvironment, toPiToolName };
8
+
9
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/schemas/sessionConfig.ts"],"sourcesContent":["import { DOOM_MCP_SESSION_ENV_VAR } from '@agimon-ai/po-core/mcpSession';\n\n/** @deprecated Use `DOOM_MCP_SESSION_ENV_VAR` from extension contracts. */\nexport const SESSION_ENV_VAR = DOOM_MCP_SESSION_ENV_VAR;\n"],"mappings":";;;;AAGA,MAAa,kBAAkB"}