@agimon-ai/doompi-mcp 0.0.1-alpha.90 → 0.0.1-alpha.92

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.
@@ -48,13 +48,17 @@ function sessionConfiguration(execution, workspaceRoot) {
48
48
  }
49
49
  return require_mcpCatalog.readSessionConfig(execution.environment, execution.cwd);
50
50
  }
51
- function createMcpServerRuntime(environment = {}, workspaceRoot) {
51
+ function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver) {
52
52
  let active;
53
+ let currentSelection;
53
54
  let staleSelection = false;
55
+ let cleanup;
56
+ let transition = Promise.resolve();
54
57
  const authorizing = /* @__PURE__ */ new Map();
55
58
  const session = new require_mcpCommand.McpSession({
56
59
  environment: { ...environment },
57
60
  onAuthorizationUrl: async (url, serverName) => {
61
+ if (staleSelection || !session.getServers().some((server) => server.name === serverName)) return;
58
62
  await active?.client.notify({
59
63
  title: `Authorize MCP server ${serverName}`,
60
64
  body: url.toString(),
@@ -62,10 +66,63 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
62
66
  });
63
67
  }
64
68
  });
69
+ const refresh = (execution, selection) => {
70
+ staleSelection = true;
71
+ authorizing.clear();
72
+ transition = transition.catch(() => {}).then(async () => {
73
+ if (active !== execution) return;
74
+ const previousCleanup = cleanup;
75
+ cleanup = void 0;
76
+ try {
77
+ await session.dispose();
78
+ } finally {
79
+ session.install({
80
+ enabled: false,
81
+ repoRoot: execution.cwd,
82
+ stagingDirectory: execution.cwd
83
+ });
84
+ await previousCleanup?.();
85
+ }
86
+ if (active !== execution) return;
87
+ const resolver = getResolver?.();
88
+ const loaded = workspaceRoot ? (0, _agimon_ai_doompi_config_harnessStore.loadHarnessState)({ ...execution.environment }) : void 0;
89
+ const authorized = workspaceRoot && loaded?.filePath && loaded.state.root === workspaceRoot && execution.repoRoot === workspaceRoot && loaded.state.mcp && loaded.state.majorMode === selection.majorMode && JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) && JSON.stringify(loaded.state.layers) === JSON.stringify(selection.activeLayers) && (0, _agimon_ai_doompi_core_mcpProjection.isDoomMcpProjection)(loaded.state.mcpProjection) && loaded.state.mcpProjection.repoRoot === workspaceRoot && loaded.state.mcpProjection.enabled;
90
+ if (!resolver || !authorized) {
91
+ if (active === execution && selection === currentSelection) {
92
+ if (workspaceRoot === void 0 || JSON.stringify(execution.selection.domains) === JSON.stringify(selection.domains)) await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);
93
+ staleSelection = workspaceRoot !== void 0 && JSON.stringify(execution.selection.domains) !== JSON.stringify(selection.domains);
94
+ }
95
+ return;
96
+ }
97
+ const candidate = await resolver.resolve(selection.domains);
98
+ if (active !== execution || selection !== currentSelection) {
99
+ await candidate.cleanup();
100
+ return;
101
+ }
102
+ try {
103
+ if (!(0, _agimon_ai_doompi_core_mcpProjection.isDoomMcpProjection)(candidate.projection) || candidate.projection.repoRoot !== workspaceRoot || !candidate.projection.enabled) throw new Error("The selected domains returned an invalid MCP projection.");
104
+ await session.reconfigure(require_projection.mcpSessionConfigFromProjection(candidate.projection, execution.cwd), execution.cwd, execution.repoRoot);
105
+ cleanup = () => candidate.cleanup();
106
+ if (active === execution && selection === currentSelection) staleSelection = false;
107
+ } catch (error) {
108
+ await candidate.cleanup();
109
+ throw error;
110
+ }
111
+ }).catch(async (error) => {
112
+ if (active !== execution || selection !== currentSelection) return;
113
+ await execution.client.notify({
114
+ title: "DoomPi MCP unavailable",
115
+ body: error instanceof Error ? error.message : String(error),
116
+ level: "warning"
117
+ });
118
+ });
119
+ return transition;
120
+ };
65
121
  const activity = {
66
122
  name: "doompi-mcp-runtime",
67
123
  async start(execution) {
68
124
  active = execution;
125
+ currentSelection = execution.selection;
69
126
  staleSelection = false;
70
127
  const reported = /* @__PURE__ */ new Set();
71
128
  const publish = () => {
@@ -83,7 +140,7 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
83
140
  };
84
141
  const stopPublishing = session.onChange(publish);
85
142
  try {
86
- await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);
143
+ await refresh(execution, execution.selection);
87
144
  publish();
88
145
  } catch (error) {
89
146
  await execution.client.notify({
@@ -96,8 +153,12 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
96
153
  stopPublishing();
97
154
  if (active !== execution) return;
98
155
  active = void 0;
99
- staleSelection = false;
156
+ currentSelection = void 0;
157
+ staleSelection = true;
100
158
  authorizing.clear();
159
+ await transition;
160
+ const retiredCleanup = cleanup;
161
+ cleanup = void 0;
101
162
  try {
102
163
  await session.dispose();
103
164
  } finally {
@@ -106,6 +167,7 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
106
167
  repoRoot: execution.cwd,
107
168
  stagingDirectory: execution.cwd
108
169
  });
170
+ await retiredCleanup?.();
109
171
  execution.client.setStatus(require_mcpCommand.MCP_STATUS_KEY, void 0);
110
172
  execution.client.setStatus(require_mcpCommand.MCP_SESSION_AUTH_STATUS_KEY, void 0);
111
173
  }
@@ -171,18 +233,9 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
171
233
  return;
172
234
  }
173
235
  if (subcommand === "reload") {
174
- authorizing.clear();
175
- try {
176
- await session.dispose();
177
- } finally {
178
- session.install({
179
- enabled: false,
180
- repoRoot: execution.cwd,
181
- stagingDirectory: execution.cwd
182
- });
183
- }
184
- await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);
185
- await notify("Reconnecting MCP servers.");
236
+ if (!currentSelection) throw new Error("The MCP runtime has not started yet.");
237
+ await refresh(active, currentSelection);
238
+ if (!staleSelection) await notify("Reconnecting MCP servers.");
186
239
  return;
187
240
  }
188
241
  throw new Error(`Unknown /mcp subcommand "${subcommand}". Use status, auth, disconnect, reload.`);
@@ -214,26 +267,26 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
214
267
  childTool,
215
268
  async onSelectionChange(selection) {
216
269
  if (!active || workspaceRoot === void 0) return;
217
- const initial = active.selection;
218
- if (!initial || JSON.stringify(initial.domains) === JSON.stringify(selection.domains)) return;
219
- staleSelection = true;
220
- authorizing.clear();
221
- await session.reconfigure({
222
- enabled: false,
223
- repoRoot: active.cwd,
224
- stagingDirectory: node_path.default.join(active.cwd, ".doom", "mcp-disabled"),
225
- sources: []
226
- });
270
+ if (JSON.stringify(currentSelection) === JSON.stringify(selection)) return;
271
+ currentSelection = selection;
272
+ await refresh(active, selection);
227
273
  }
228
274
  };
229
275
  }
230
276
  //#endregion
231
277
  //#region src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts
232
278
  const createMcpServerRoot = (context) => {
233
- const runtime = createMcpServerRuntime(context?.agent?.context?.environment, context?.host.context.workspaceRoot);
279
+ let resolver;
280
+ const runtime = createMcpServerRuntime(context?.agent?.context?.environment, context?.host.context.workspaceRoot, () => resolver);
234
281
  const generation = `${context?.agent?.context?.sessionId ?? crypto.randomUUID()}:mcp-server`;
235
282
  const { session } = runtime;
236
283
  const mountSession = (cordis) => {
284
+ cordis.inject([_agimon_ai_doompi_core_mcpProjection.DOOM_MCP_PROJECTION_RESOLVER_SERVICE], (resolverContext) => {
285
+ resolver = resolverContext.get(_agimon_ai_doompi_core_mcpProjection.DOOM_MCP_PROJECTION_RESOLVER_SERVICE);
286
+ return () => {
287
+ resolver = void 0;
288
+ };
289
+ });
237
290
  cordis.inject([_agimon_ai_doompi_core_headless.DOOM_HEADLESS_HOST_SERVICE], (hostContext) => {
238
291
  return hostContext.get(_agimon_ai_doompi_core_headless.DOOM_HEADLESS_HOST_SERVICE).subscribeSelection((selection) => runtime.onSelectionChange(selection));
239
292
  });
@@ -1 +1 @@
1
- {"version":3,"file":"server.cjs","names":["loadHarnessState","isDoomMcpProjection","mcpSessionConfigFromProjection","path","readSessionConfig","McpSession","MCP_STATUS_KEY","MCP_SESSION_AUTH_STATUS_KEY","formatMcpSessionAuthStatus","createMcpChildTool","SERVER_COMMAND_DESCRIPTION","formatStatus","McpHeadlessToolParameters","DOOM_HEADLESS_HOST_SERVICE","DOOM_MCP_STATUS_SERVICE","DOOM_MCP_TOOL_RESOLVER_SERVICE","MCP_SESSION_TOOLS_SERVICE","createMcpSessionToolsService","DOOM_CHILD_SESSION_MCP_TOOL_SERVICE","defineRoot","toPiToolName","os","createTokenStore","fs","path","mcpSessionConfigFromProjection","buildMcpConfigGroups","readCachedCatalog","McpRuntimeOwner","randomUUID","hubCallbackSink","MCP_AUTHORIZATION_API_PATH","MCP_FLOW_ID_PARAM","defineApiRoutes","MCP_REPOSITORY_API_PATH","MCP_REPOSITORY_ID_QUERY","apiResponse","MCP_DISCOVERY_API_PATH","routes","MCP_FLOW_ID_PARAM","MCP_REPOSITORY_ID_QUERY","defineRoute","defineServerCommand","defineServerTool","defineServerPlugin","apiRoute","rootSession","composeRootHooks","commandMcp","toolMcpUse"],"sources":["../../src/services/mcpHeadlessTools/index.ts","../../src/services/serverRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/mcpSettingsManager/index.ts","../../src/types/apiRoutes.ts","../../src/services/mcpHubApi/index.ts","../../src/extensions/(backend)/api/mcp/route.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/mcp.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/mcp_use.server.ts","../../generated/server.ts"],"sourcesContent":["import type { DoomHeadlessTool } from '@agimon-ai/doompi-core/headless';\nimport type { DoomMcpPluginContext } from '@agimon-ai/doompi-core/mcpFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nexport const MCP_HEADLESS_TOOLS_SERVICE = 'doom/mcp-headless-tools';\n\nexport interface McpHeadlessToolCatalog {\n get(name: string): DoomHeadlessTool | undefined;\n}\n\nexport function mountMcpHeadlessTools(tools: readonly DoomHeadlessTool[]) {\n return (context: Context): void => {\n context.plugin((providerContext) => {\n providerContext.provide(MCP_HEADLESS_TOOLS_SERVICE, {\n get: (name) => tools.find((tool) => tool.name === name),\n } satisfies McpHeadlessToolCatalog);\n });\n };\n}\n\nexport function bindMcpHeadlessTool(context: DoomMcpPluginContext, name: string): DoomHeadlessTool {\n const tool = context.services.get<McpHeadlessToolCatalog>(MCP_HEADLESS_TOOLS_SERVICE)?.get(name);\n if (!tool) throw new Error(`MCP tool is unavailable: ${name}`);\n return {\n ...tool,\n execute(toolCallId, parameters, signal, onUpdate) {\n const executionSignal = AbortSignal.any([context.signal, signal ?? context.signal]);\n return tool.execute(toolCallId, parameters, executionSignal, onUpdate, context.execution);\n },\n };\n}\n","import path from 'node:path';\n\nimport { loadHarnessState } from '@agimon-ai/doompi-config/harnessStore';\nimport type {\n DoomHeadlessActivity,\n DoomHeadlessCommand,\n DoomHeadlessExecutionContext,\n DoomHeadlessSelection,\n DoomHeadlessTool,\n} from '@agimon-ai/doompi-core/headless';\nimport { isDoomMcpProjection } from '@agimon-ai/doompi-core/mcpProjection';\nimport type { DoomMcpSessionConfig } from '@agimon-ai/doompi-core/mcpSession';\n\nimport { COMMAND_NAME, SERVER_COMMAND_DESCRIPTION } from '../../constants/mcp';\nimport { MCP_STATUS_KEY } from '../../constants/piMcp';\nimport { McpHeadlessToolParameters } from '../../schemas/mcpHeadlessTool';\nimport { formatMcpSessionAuthStatus, MCP_SESSION_AUTH_STATUS_KEY } from '../../types/webMcp';\nimport { formatStatus } from '../mcpCommand';\nimport { McpSession } from '../mcpSession';\nimport { createMcpChildTool } from '../mcpSessionTools';\nimport { mcpSessionConfigFromProjection } from '../projection';\nimport { readSessionConfig } from '../sessionConfig';\n\nfunction sessionConfiguration(execution: DoomHeadlessExecutionContext, workspaceRoot?: string): DoomMcpSessionConfig {\n if (workspaceRoot !== undefined) {\n const loaded = loadHarnessState({ ...execution.environment });\n const projection = loaded.state.mcpProjection;\n if (\n loaded.filePath &&\n loaded.state.root === workspaceRoot &&\n execution.repoRoot === workspaceRoot &&\n loaded.state.mcp &&\n loaded.state.majorMode === execution.selection.majorMode &&\n JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) &&\n JSON.stringify(loaded.state.layers) === JSON.stringify(execution.selection.activeLayers) &&\n isDoomMcpProjection(projection) &&\n projection.repoRoot === workspaceRoot\n )\n return mcpSessionConfigFromProjection(projection, execution.cwd);\n return {\n enabled: false,\n repoRoot: execution.cwd,\n stagingDirectory: path.join(execution.cwd, '.doom', 'mcp-disabled'),\n sources: [],\n };\n }\n return readSessionConfig(execution.environment, execution.cwd);\n}\n\nexport function createMcpServerRuntime(\n environment: Readonly<Record<string, string | undefined>> = {},\n workspaceRoot?: string,\n) {\n let active: DoomHeadlessExecutionContext | undefined;\n let staleSelection = false;\n const authorizing = new Map<string, symbol>();\n const session = new McpSession({\n environment: { ...environment },\n onAuthorizationUrl: async (url, serverName) => {\n await active?.client.notify({\n title: `Authorize MCP server ${serverName}`,\n body: url.toString(),\n level: 'warning',\n });\n },\n });\n\n const activity: DoomHeadlessActivity = {\n name: 'doompi-mcp-runtime',\n async start(execution) {\n active = execution;\n staleSelection = false;\n const reported = new Set<string>();\n const publish = () => {\n execution.client.setStatus(\n MCP_STATUS_KEY,\n session\n .getServers()\n .map((server) => server.name)\n .join(','),\n );\n execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, formatMcpSessionAuthStatus(session.getServers()));\n for (const diagnostic of session.getDiagnostics()) {\n if (reported.has(diagnostic)) continue;\n reported.add(diagnostic);\n void execution.client.notify({ title: 'DoomPi MCP', body: diagnostic, level: 'warning' });\n }\n };\n const stopPublishing = session.onChange(publish);\n try {\n await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);\n publish();\n } catch (error) {\n await execution.client.notify({\n title: 'DoomPi MCP unavailable',\n body: error instanceof Error ? error.message : String(error),\n level: 'warning',\n });\n }\n return async () => {\n stopPublishing();\n if (active !== execution) return;\n active = undefined;\n staleSelection = false;\n authorizing.clear();\n try {\n await session.dispose();\n } finally {\n // Withdraw tools and UI state even when a connection fails to close.\n session.install({ enabled: false, repoRoot: execution.cwd, stagingDirectory: execution.cwd });\n execution.client.setStatus(MCP_STATUS_KEY, undefined);\n execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, undefined);\n }\n };\n },\n };\n\n const invoke: Parameters<typeof createMcpChildTool>[0] = async (parameters, signal) => {\n if (!active) throw new Error('The MCP runtime has not started yet.');\n if (staleSelection) throw new Error('The MCP projection is stale for the current selection.');\n const selected = session\n .activeToolDefinitions()\n .find((candidate) => candidate.serverName === parameters.server && candidate.toolName === parameters.tool);\n if (!selected)\n throw new Error(`MCP tool ${parameters.server}/${parameters.tool} is not available in this session.`);\n return session.invokeTool(selected.piName, parameters.arguments ?? {}, signal);\n };\n const childTool = createMcpChildTool(invoke);\n\n // web-plugin-tool-renderers: ignore mcp_use, headless-only generic MCP dispatch\n const tool: DoomHeadlessTool<typeof McpHeadlessToolParameters> = {\n name: 'mcp_use',\n label: 'MCP use',\n description: 'Call a tool exposed by a connected MCP server.',\n parameters: McpHeadlessToolParameters,\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n try {\n return await invoke(parameters, signal);\n } catch (error) {\n return {\n content: [{ type: 'text', text: error instanceof Error ? error.message : String(error) }],\n isError: true,\n };\n }\n },\n };\n\n const command: DoomHeadlessCommand = {\n name: COMMAND_NAME,\n description: SERVER_COMMAND_DESCRIPTION,\n async execute(args, execution) {\n const [subcommand = 'status', ...rest] = args.trim().split(/\\s+/u).filter(Boolean);\n const serverName = rest.join(' ');\n const notify = (body: string, level: 'info' | 'warning' = 'info') =>\n execution.client.notify({ title: 'DoomPi MCP', body, level });\n try {\n if (subcommand === 'status') {\n await notify(formatStatus(session));\n return;\n }\n if (!active) throw new Error('The MCP runtime has not started yet.');\n if (staleSelection) throw new Error('The MCP projection is stale for the current selection.');\n if (subcommand === 'auth' || subcommand === 'disconnect') {\n if (!serverName) throw new Error(`Name the server, for example /mcp ${subcommand} <server>.`);\n const server = session.getServers().find((candidate) => candidate.name === serverName);\n if (!server) throw new Error(`Unknown MCP server: ${serverName}`);\n if (subcommand === 'disconnect') {\n await session.disconnect(serverName);\n authorizing.delete(serverName);\n await notify(`${serverName} is disconnected from this session. Saved credentials were kept.`);\n return;\n }\n if (server.authorizationUrl) {\n await session.openAuthorizationPage(serverName);\n return;\n }\n if (authorizing.has(serverName)) return;\n const request = Symbol(serverName);\n authorizing.set(serverName, request);\n const owner = active;\n // OAuth waits for the browser. Do not hold the session command queue while it does.\n void session.reauthorize(serverName).then(\n async () => {\n if (active !== owner || authorizing.get(serverName) !== request) return;\n authorizing.delete(serverName);\n await notify(`${serverName} is authorized.`);\n },\n async (error: unknown) => {\n if (active !== owner || authorizing.get(serverName) !== request) return;\n authorizing.delete(serverName);\n await notify(\n `Could not authorize ${serverName}: ${error instanceof Error ? error.message : String(error)}`,\n 'warning',\n );\n },\n );\n return;\n }\n if (subcommand === 'reload') {\n authorizing.clear();\n try {\n await session.dispose();\n } finally {\n // Reset the catalog even when paths are unchanged or teardown fails.\n session.install({ enabled: false, repoRoot: execution.cwd, stagingDirectory: execution.cwd });\n }\n await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);\n await notify('Reconnecting MCP servers.');\n return;\n }\n throw new Error(`Unknown /${COMMAND_NAME} subcommand \"${subcommand}\". Use status, auth, disconnect, reload.`);\n } catch (error) {\n await notify(error instanceof Error ? error.message : String(error), 'warning');\n }\n },\n };\n return {\n session,\n activities: [activity],\n commands: [command],\n tools: [tool],\n childTool,\n async onSelectionChange(selection: DoomHeadlessSelection) {\n if (!active || workspaceRoot === undefined) return;\n const initial = active.selection;\n if (!initial || JSON.stringify(initial.domains) === JSON.stringify(selection.domains)) return;\n staleSelection = true;\n authorizing.clear();\n await session.reconfigure({\n enabled: false,\n repoRoot: active.cwd,\n stagingDirectory: path.join(active.cwd, '.doom', 'mcp-disabled'),\n sources: [],\n });\n },\n };\n}\n","import { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE } from '@agimon-ai/doompi-core/childSession';\nimport { DOOM_HEADLESS_HOST_SERVICE, type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { DOOM_MCP_STATUS_SERVICE, type DoomMcpStatusService } from '@agimon-ai/doompi-core/mcpStatus';\nimport {\n DOOM_MCP_TOOL_RESOLVER_SERVICE,\n type DoomMcpToolResolverService,\n} from '@agimon-ai/doompi-core/mcpToolResolver';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { mountMcpHeadlessTools } from '../../../../../services/mcpHeadlessTools';\nimport { createMcpSessionToolsService, MCP_SESSION_TOOLS_SERVICE } from '../../../../../services/mcpSessionTools';\nimport { createMcpServerRuntime } from '../../../../../services/serverRuntime';\n\nexport const createMcpServerRoot = (context?: DoomServerPluginContext) => {\n const runtime = createMcpServerRuntime(context?.agent?.context?.environment, context?.host.context.workspaceRoot);\n const generation = `${context?.agent?.context?.sessionId ?? crypto.randomUUID()}:mcp-server`;\n const { session } = runtime;\n const mountSession = (cordis: Context) => {\n cordis.inject([DOOM_HEADLESS_HOST_SERVICE], (hostContext) => {\n const host = hostContext.get(DOOM_HEADLESS_HOST_SERVICE) as DoomHeadlessHostService;\n return host.subscribeSelection((selection) => runtime.onSelectionChange(selection));\n });\n cordis.plugin((provider) => {\n provider.provide(DOOM_MCP_STATUS_SERVICE, {\n generation,\n getSnapshot: () => session.getSnapshot(),\n onChange: (listener) => session.onChange(listener),\n } satisfies DoomMcpStatusService);\n provider.provide(DOOM_MCP_TOOL_RESOLVER_SERVICE, {\n generation,\n resolve: (selectors) => session.resolveToolSelectors(selectors),\n } satisfies DoomMcpToolResolverService);\n provider.provide(MCP_SESSION_TOOLS_SERVICE, createMcpSessionToolsService(session, generation));\n provider.provide(DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, runtime.childTool);\n });\n };\n return {\n value: runtime,\n activities: runtime.activities,\n services: [mountMcpHeadlessTools(runtime.tools), mountSession],\n };\n};\nexport type McpServerScope = Awaited<ReturnType<typeof createMcpServerRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createMcpServerRoot } from './_lib/serverRoot';\n\nexport default defineRoot(createMcpServerRoot);\n","import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport type { DoomOAuthRedirect, DoomRepositorySyncView } from '@agimon-ai/doompi-core/packageApi';\nimport type { McpServerStateChange, McpToolInfo, TokenStore } from '@agimon-ai/mcp-proxy';\n\nimport type { McpConfigGroups, McpConfigSource, McpSessionConfig } from '../../types/mcpConfig';\nimport type {\n McpAuthorizationFlow,\n McpRepositoryCatalog,\n McpRepositoryServer,\n McpRepositoryServerState,\n McpRepositoryTool,\n} from '../../types/webMcp';\nimport { buildMcpConfigGroups } from '../configSources';\nimport { createTokenStore } from '../keyringTokenStore';\nimport { toPiToolName } from '../mcpCatalog';\nimport { hubCallbackSink, McpRuntimeOwner, readCachedCatalog } from '../mcpRuntime';\nimport { mcpSessionConfigFromProjection } from '../projection';\n\nconst DISCOVERY_TIMEOUT_MS = 30_000;\nconst AUTHORIZATION_TIMEOUT_MS = 5 * 60_000;\nconst TERMINAL_FLOW_RETENTION_MS = 5 * 60_000;\nconst EMPTY_SYNC = { fresh: false, reasons: ['never-synced'] } as const;\n\ninterface PreparedMcpRepository {\n catalog: McpRepositoryCatalog;\n configSources: McpConfigSource[];\n groups: McpConfigGroups;\n stagingDirectory?: string;\n}\n\ninterface InternalAuthorizationFlow extends McpAuthorizationFlow {\n owner?: McpRuntimeOwner;\n stagingDirectory?: string;\n timeout?: ReturnType<typeof setTimeout>;\n retainedUntil?: number;\n}\n\nexport interface McpSettingsManagerOptions {\n discoveryTimeoutMs?: number;\n authorizationTimeoutMs?: number;\n tokenStore?: TokenStore;\n}\n\nfunction configuredServerNames(groups: McpConfigGroups): string[] {\n return [...new Set([...groups.sessionLocal.serverNames, ...groups.shared.serverNames])].sort((left, right) =>\n left.localeCompare(right),\n );\n}\n\nfunction configSources(groups: McpConfigGroups): McpConfigSource[] {\n return [...groups.sessionLocal.configSources, ...groups.shared.configSources];\n}\n\nfunction toolView(serverName: string, tool: McpToolInfo): McpRepositoryTool {\n return {\n name: tool.name,\n piName: toPiToolName(serverName, tool.name),\n ...(tool.description ? { description: tool.description } : {}),\n };\n}\n\nfunction sanitizeDiagnostic(message: string, repositoryRoot: string, stagingDirectory: string | undefined): string {\n let safe = message;\n for (const value of [stagingDirectory, repositoryRoot, os.homedir()]) {\n if (value) safe = safe.split(value).join(value === os.homedir() ? '~' : '<repository>');\n }\n return safe.replace(/[A-Za-z]:\\\\[^\\s,;)'\"`]+/gu, '<path>').replace(/(^|\\s)\\/(?!\\/)[^\\s,;)'\"`]+/gu, '$1<path>');\n}\n\nfunction publicFlow(flow: InternalAuthorizationFlow): McpAuthorizationFlow {\n return {\n id: flow.id,\n repositoryId: flow.repositoryId,\n serverName: flow.serverName,\n status: flow.status,\n ...(flow.authorizationUrl ? { authorizationUrl: flow.authorizationUrl } : {}),\n ...(flow.error ? { error: flow.error } : {}),\n expiresAt: flow.expiresAt,\n };\n}\n\nfunction isTerminal(status: McpAuthorizationFlow['status']): boolean {\n return status === 'completed' || status === 'failed' || status === 'cancelled' || status === 'expired';\n}\n\nfunction safeAuthorizationUrl(url: URL): string | undefined {\n if ((url.protocol !== 'https:' && url.protocol !== 'http:') || url.toString().length > 4096) return undefined;\n return url.toString();\n}\n\nexport class McpSettingsManager {\n private readonly discoveryTimeoutMs: number;\n private readonly authorizationTimeoutMs: number;\n private readonly injectedTokenStore?: TokenStore;\n private readonly busyRepositories = new Set<string>();\n private readonly flows = new Map<string, InternalAuthorizationFlow>();\n\n constructor(options: McpSettingsManagerOptions = {}) {\n this.discoveryTimeoutMs = options.discoveryTimeoutMs ?? DISCOVERY_TIMEOUT_MS;\n this.authorizationTimeoutMs = options.authorizationTimeoutMs ?? AUTHORIZATION_TIMEOUT_MS;\n this.injectedTokenStore = options.tokenStore;\n }\n\n private async tokenStore(): Promise<TokenStore> {\n return this.injectedTokenStore ?? (await createTokenStore());\n }\n\n private async credentialPresence(serverNames: readonly string[]): Promise<Map<string, boolean>> {\n const presence = new Map<string, boolean>();\n try {\n const tokenStore = await this.tokenStore();\n await Promise.all(\n serverNames.map(async (serverName) => {\n try {\n presence.set(serverName, (await tokenStore.read(serverName)) !== undefined);\n } catch {\n presence.set(serverName, false);\n }\n }),\n );\n } catch {\n for (const serverName of serverNames) presence.set(serverName, false);\n }\n return presence;\n }\n\n private prepare(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n onlyServer?: string,\n ): PreparedMcpRepository {\n if (!sync?.mcpProjection) {\n const readiness = sync ?? EMPTY_SYNC;\n return {\n catalog: {\n repositoryId,\n sync: { fresh: readiness.fresh, reasons: [...readiness.reasons] },\n servers: [],\n droppedServers: [],\n diagnostics: [],\n },\n configSources: [],\n groups: {\n shared: { configSources: [], configPaths: [], serverNames: [] },\n sessionLocal: { configSources: [], configPaths: [], serverNames: [] },\n droppedServers: [],\n diagnostics: [],\n },\n };\n }\n\n const stagingDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'doompi-mcp-settings-'));\n fs.chmodSync(stagingDirectory, 0o700);\n try {\n const projected = mcpSessionConfigFromProjection(sync.mcpProjection);\n const configuration: McpSessionConfig = {\n ...projected,\n repoRoot: repositoryRoot,\n stagingDirectory,\n ...(onlyServer ? { allowlist: { servers: [onlyServer], proxy: [] } } : {}),\n };\n const groups = buildMcpConfigGroups(configuration);\n const sources = configSources(groups);\n const names = configuredServerNames(groups);\n const cachedByServer = new Map(readCachedCatalog(sources).servers.map((server) => [server.name, server.tools]));\n const servers: McpRepositoryServer[] = names.map((name) => {\n const tools = cachedByServer.get(name) ?? [];\n return {\n name,\n state: 'not-connected',\n source: tools.length === 0 ? 'configured' : 'cached',\n credentialPresent: false,\n tools: tools.map((tool) => toolView(name, tool)),\n };\n });\n return {\n catalog: {\n repositoryId,\n sync: { fresh: sync.fresh, reasons: [...sync.reasons] },\n servers,\n droppedServers: [...groups.droppedServers],\n diagnostics: groups.diagnostics.map((diagnostic) =>\n sanitizeDiagnostic(diagnostic, repositoryRoot, stagingDirectory),\n ),\n },\n configSources: sources,\n groups,\n stagingDirectory,\n };\n } catch (error) {\n fs.rmSync(stagingDirectory, { recursive: true, force: true });\n throw error;\n }\n }\n\n private cleanupPrepared(prepared: PreparedMcpRepository): void {\n if (prepared.stagingDirectory) fs.rmSync(prepared.stagingDirectory, { recursive: true, force: true });\n }\n\n async readCatalog(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n ): Promise<McpRepositoryCatalog> {\n const prepared = this.prepare(repositoryId, repositoryRoot, sync);\n try {\n const presence = await this.credentialPresence(prepared.catalog.servers.map((server) => server.name));\n return {\n ...prepared.catalog,\n servers: prepared.catalog.servers.map((server) => ({\n ...server,\n credentialPresent: presence.get(server.name) ?? false,\n })),\n };\n } finally {\n this.cleanupPrepared(prepared);\n }\n }\n\n async discover(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n ): Promise<McpRepositoryCatalog> {\n if (this.busyRepositories.has(repositoryId))\n throw new Error('MCP management is already active for this repository.');\n const prepared = this.prepare(repositoryId, repositoryRoot, sync);\n if (!prepared.catalog.sync.fresh) {\n this.cleanupPrepared(prepared);\n throw new Error('Sync this repository before discovering MCP capabilities.');\n }\n if (prepared.configSources.length === 0) {\n this.cleanupPrepared(prepared);\n return prepared.catalog;\n }\n\n this.busyRepositories.add(repositoryId);\n const owner = new McpRuntimeOwner();\n const liveStates = new Map<string, McpServerStateChange>();\n try {\n const handle = await owner.start({\n configSources: prepared.configSources,\n workspaceRoot: repositoryRoot,\n executionCwd: repositoryRoot,\n tokenStore: await this.tokenStore(),\n onAuthorizationUrl: (_url, serverName) => {\n liveStates.set(serverName, { serverName, state: 'needs-auth' });\n },\n onServerStateChange: (change) => liveStates.set(change.serverName, change),\n });\n if (handle) {\n await Promise.race([\n handle.connectionsSettled,\n new Promise<void>((resolve) => setTimeout(resolve, this.discoveryTimeoutMs)),\n ]);\n }\n const manager = handle?.services.clientManager;\n const cachedByServer = new Map(\n readCachedCatalog(prepared.configSources).servers.map((server) => [server.name, server.tools]),\n );\n const presence = await this.credentialPresence(prepared.catalog.servers.map((server) => server.name));\n const servers = await Promise.all(\n prepared.catalog.servers.map(async (server): Promise<McpRepositoryServer> => {\n const change = liveStates.get(server.name);\n const state = (change?.state ??\n manager?.getServerState(server.name) ??\n server.state) as McpRepositoryServerState;\n let tools = cachedByServer.get(server.name) ?? [];\n let source: McpRepositoryServer['source'] = tools.length === 0 ? 'configured' : 'cached';\n if (state === 'connected' && manager) {\n try {\n tools = await manager\n .ensureConnected(server.name)\n .then(async (connection) => await connection.listTools());\n source = 'live';\n } catch {\n // Preserve the cache when a server moved between state inspection and listing.\n }\n }\n return {\n name: server.name,\n state,\n source,\n credentialPresent: presence.get(server.name) ?? false,\n tools: tools.map((tool) => toolView(server.name, tool)),\n ...(change?.error ? { error: 'The server reported a connection error.' } : {}),\n };\n }),\n );\n return { ...prepared.catalog, servers };\n } finally {\n await owner.dispose();\n this.cleanupPrepared(prepared);\n this.busyRepositories.delete(repositoryId);\n }\n }\n\n async authorize(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n serverName: string,\n /**\n * The hub's redirect surface. Present, the authorization server sends the\n * browser back to the hub, which is reachable whether the operator is at\n * this machine or on a tunnel. Absent, the proxy keeps its loopback\n * listener and behaviour is unchanged.\n */\n redirect?: DoomOAuthRedirect,\n ): Promise<McpAuthorizationFlow> {\n this.sweepFlows();\n if (this.busyRepositories.has(repositoryId))\n throw new Error('MCP management is already active for this repository.');\n\n const full = this.prepare(repositoryId, repositoryRoot, sync);\n const configured = full.catalog.servers.some((server) => server.name === serverName);\n const fresh = full.catalog.sync.fresh;\n this.cleanupPrepared(full);\n if (!fresh) throw new Error('Sync this repository before authorizing an MCP server.');\n if (!configured) throw new Error('That MCP server is not enabled for this repository.');\n\n const prepared = this.prepare(repositoryId, repositoryRoot, sync, serverName);\n const flow: InternalAuthorizationFlow = {\n id: randomUUID(),\n repositoryId,\n serverName,\n status: 'starting',\n expiresAt: Date.now() + this.authorizationTimeoutMs,\n stagingDirectory: prepared.stagingDirectory,\n };\n this.flows.set(flow.id, flow);\n this.busyRepositories.add(repositoryId);\n void this.runAuthorization(flow, prepared.configSources, repositoryRoot, redirect);\n return publicFlow(flow);\n }\n\n getAuthorization(flowId: string, repositoryId: string): McpAuthorizationFlow | undefined {\n this.sweepFlows();\n const flow = this.flows.get(flowId);\n return flow?.repositoryId === repositoryId ? publicFlow(flow) : undefined;\n }\n\n async cancelAuthorization(flowId: string, repositoryId: string): Promise<McpAuthorizationFlow | undefined> {\n const flow = this.flows.get(flowId);\n if (!flow || flow.repositoryId !== repositoryId) return undefined;\n if (!isTerminal(flow.status)) {\n flow.status = 'cancelled';\n await this.finishFlow(flow);\n }\n return publicFlow(flow);\n }\n\n private async runAuthorization(\n flow: InternalAuthorizationFlow,\n sources: McpConfigSource[],\n repositoryRoot: string,\n redirect?: DoomOAuthRedirect,\n ): Promise<void> {\n const owner = new McpRuntimeOwner();\n flow.owner = owner;\n flow.timeout = setTimeout(() => {\n if (isTerminal(flow.status)) return;\n flow.status = 'expired';\n flow.error = 'Authorization timed out.';\n void this.finishFlow(flow);\n }, this.authorizationTimeoutMs);\n\n try {\n const handle = await owner.start({\n configSources: sources,\n workspaceRoot: repositoryRoot,\n executionCwd: repositoryRoot,\n tokenStore: await this.tokenStore(),\n ...(redirect ? { callbackServer: hubCallbackSink(redirect) } : {}),\n onAuthorizationUrl: (url, serverName) => {\n if (serverName !== flow.serverName || isTerminal(flow.status)) return;\n const safeUrl = safeAuthorizationUrl(url);\n if (!safeUrl) {\n flow.status = 'failed';\n flow.error = 'The server returned an invalid authorization URL.';\n void this.finishFlow(flow);\n return;\n }\n flow.authorizationUrl = safeUrl;\n flow.status = 'waiting';\n },\n onServerStateChange: (change) => this.applyAuthorizationState(flow, change),\n });\n if (!handle || isTerminal(flow.status)) return;\n const manager = handle.services.clientManager;\n await manager.disconnectServer(flow.serverName);\n await manager.ensureConnected(flow.serverName);\n if (!isTerminal(flow.status)) flow.status = 'completed';\n } catch {\n if (!isTerminal(flow.status)) {\n flow.status = 'failed';\n flow.error = 'The MCP server could not complete authorization.';\n }\n } finally {\n if (!isTerminal(flow.status)) flow.status = 'completed';\n await this.finishFlow(flow);\n }\n }\n\n private applyAuthorizationState(flow: InternalAuthorizationFlow, change: McpServerStateChange): void {\n if (change.serverName !== flow.serverName || isTerminal(flow.status)) return;\n if (change.state === 'connected') flow.status = 'completed';\n else if (change.state === 'needs-auth' && flow.status === 'starting') flow.status = 'waiting';\n else if (change.state === 'failed') {\n flow.status = 'failed';\n flow.error = 'The MCP server rejected the authorization attempt.';\n }\n }\n\n private async finishFlow(flow: InternalAuthorizationFlow): Promise<void> {\n if (flow.timeout) clearTimeout(flow.timeout);\n flow.timeout = undefined;\n const owner = flow.owner;\n flow.owner = undefined;\n await owner?.dispose();\n if (flow.stagingDirectory) fs.rmSync(flow.stagingDirectory, { recursive: true, force: true });\n flow.stagingDirectory = undefined;\n this.busyRepositories.delete(flow.repositoryId);\n flow.retainedUntil = Date.now() + TERMINAL_FLOW_RETENTION_MS;\n }\n\n private sweepFlows(): void {\n const now = Date.now();\n for (const [id, flow] of this.flows) {\n if (flow.retainedUntil !== undefined && flow.retainedUntil <= now) this.flows.delete(id);\n }\n }\n\n async dispose(): Promise<void> {\n await Promise.all(\n [...this.flows.values()].map(async (flow) => {\n if (!isTerminal(flow.status)) flow.status = 'cancelled';\n await this.finishFlow(flow);\n }),\n );\n this.flows.clear();\n this.busyRepositories.clear();\n }\n}\n","import { apiResponse, defineApiRoutes } from '@agimon-ai/doompi-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 type McpAuthorizationFlow,\n type McpRepositoryCatalog,\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});\n","import type { DoomApi, DoomApiContext } from '@agimon-ai/doompi-core/packageApi';\n\nimport { McpSettingsManager } from '../../services/mcpSettingsManager';\nimport routes from '../../types/apiRoutes';\nimport { MCP_FLOW_ID_PARAM, MCP_REPOSITORY_ID_QUERY } from '../../types/webMcp';\n\n/**\n * What sits above a flow id, read off the flow route itself.\n *\n * This handler matches paths by hand rather than through a router, so the one\n * route carrying a parameter is split here: everything before `:flowId` is the\n * prefix a request must start with, and what follows it is the id.\n */\nconst AUTHORIZATION_FLOW_PREFIX = routes.readAuthorization.path.replace(`:${MCP_FLOW_ID_PARAM}`, '');\n\nconst JSON_HEADERS = { 'content-type': 'application/json' };\nconst REPOSITORY_ID = /^(?:[a-f0-9]{32}|repo-[A-Za-z0-9_-]{24})$/u;\nconst FLOW_ID = /^[a-f0-9-]{36}$/u;\nconst MAX_BODY_BYTES = 8 * 1024;\nconst MAX_SERVER_NAME = 160;\nconst manager = new McpSettingsManager();\n\ntype JsonRecord = Record<string, unknown>;\n\nfunction json(body: unknown, status = 200): Response {\n return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS });\n}\n\nfunction isRecord(value: unknown): value is JsonRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nasync function bodyOf(request: Request): Promise<JsonRecord | undefined> {\n const text = await request.text();\n if (text.length > MAX_BODY_BYTES) return undefined;\n try {\n const parsed = JSON.parse(text) as unknown;\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction repositoryIdOf(value: unknown): string | undefined {\n return typeof value === 'string' && REPOSITORY_ID.test(value) ? value : undefined;\n}\n\nfunction serverNameOf(value: unknown): string | undefined {\n return typeof value === 'string' &&\n value.length > 0 &&\n value.length <= MAX_SERVER_NAME &&\n !Array.from(value).some((character) => character.charCodeAt(0) <= 0x1f)\n ? value\n : undefined;\n}\n\nfunction resolveRepository(context: DoomApiContext, repositoryId: string): string | undefined {\n return context.resolveRepository?.(repositoryId);\n}\n\nfunction errorStatus(error: unknown): { status: number; message: string } {\n const message = error instanceof Error ? error.message : '';\n if (message.includes('already active')) return { status: 409, message };\n if (message.startsWith('Sync this repository')) return { status: 409, message };\n if (message.includes('not enabled')) return { status: 404, message };\n return { status: 500, message: 'MCP management could not complete that request.' };\n}\n\nasync function handleCatalog(request: Request, context: DoomApiContext): Promise<Response> {\n const repositoryId = repositoryIdOf(new URL(request.url).searchParams.get(MCP_REPOSITORY_ID_QUERY));\n if (!repositoryId) return json({ error: 'A valid repositoryId is required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(await manager.readCatalog(repositoryId, repositoryRoot, context.readRepositorySync?.(repositoryId)));\n } catch {\n return json({ error: 'The synced MCP catalog could not be read.' }, 500);\n }\n}\n\nasync function handleDiscovery(request: Request, context: DoomApiContext): Promise<Response> {\n const body = await bodyOf(request);\n const repositoryId = repositoryIdOf(body?.repositoryId);\n if (!repositoryId) return json({ error: 'A valid repositoryId is required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(await manager.discover(repositoryId, repositoryRoot, context.readRepositorySync?.(repositoryId)));\n } catch (error) {\n const failure = errorStatus(error);\n return json({ error: failure.message }, failure.status);\n }\n}\n\nasync function handleAuthorize(request: Request, context: DoomApiContext): Promise<Response> {\n const body = await bodyOf(request);\n const repositoryId = repositoryIdOf(body?.repositoryId);\n const serverName = serverNameOf(body?.serverName);\n if (!repositoryId || !serverName) return json({ error: 'A valid repositoryId and serverName are required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(\n await manager.authorize(\n repositoryId,\n repositoryRoot,\n context.readRepositorySync?.(repositoryId),\n serverName,\n context.oauthRedirect?.(),\n ),\n 202,\n );\n } catch (error) {\n const failure = errorStatus(error);\n return json({ error: failure.message }, failure.status);\n }\n}\n\nasync function handleAuthorizationFlow(request: Request, context: DoomApiContext, path: string): Promise<Response> {\n const flowId = path.slice(AUTHORIZATION_FLOW_PREFIX.length);\n const repositoryId = repositoryIdOf(new URL(request.url).searchParams.get(MCP_REPOSITORY_ID_QUERY));\n if (!repositoryId || !FLOW_ID.test(flowId))\n return json({ error: 'A valid repositoryId and flow id are required.' }, 400);\n if (!resolveRepository(context, repositoryId)) {\n return json({ error: 'That repository is not available to this hub.' }, 404);\n }\n if (request.method === routes.cancelAuthorization.method) {\n const flow = await manager.cancelAuthorization(flowId, repositoryId);\n return flow ? json(flow) : json({ error: 'That authorization flow was not found.' }, 404);\n }\n const flow = manager.getAuthorization(flowId, repositoryId);\n return flow ? json(flow) : json({ error: 'That authorization flow was not found.' }, 404);\n}\n\nexport const mcpHubApi: DoomApi = {\n basePath: 'mcp',\n start(context) {\n return {\n async fetch(request) {\n const path = new URL(request.url).pathname;\n if (request.method === routes.catalog.method && path === routes.catalog.path) {\n return await handleCatalog(request, context);\n }\n if (request.method === routes.discover.method && path === routes.discover.path) {\n return await handleDiscovery(request, context);\n }\n if (request.method === routes.authorize.method && path === routes.authorize.path) {\n return await handleAuthorize(request, context);\n }\n if (\n (request.method === routes.readAuthorization.method ||\n request.method === routes.cancelAuthorization.method) &&\n path.startsWith(AUTHORIZATION_FLOW_PREFIX)\n ) {\n return await handleAuthorizationFlow(request, context, path);\n }\n return json({ error: 'Not found.' }, 404);\n },\n close() {\n void manager.dispose();\n },\n };\n },\n};\n","import { defineRoute } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { mcpHubApi } from '../../../../services/mcpHubApi';\n\n/**\n * Mounts this package's HTTP API at `mcp`, which the folder names.\n *\n * The folder is the declaration: the build reads the base path off it and hands\n * the browser a client bound to the same segment, so the settings panel can no\n * longer spell a workspace mount by hand.\n */\nexport default defineRoute(mcpHubApi);\n","import { defineServerCommand, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { McpServerScope } from '../_lib/serverRoot';\nexport default defineServerCommand(\n (context: WithRoot<DoomServerPluginContext, McpServerScope>) => context.root.commands[0]!,\n);\n","import { defineServerTool, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { McpServerScope } from '../_lib/serverRoot';\nexport default defineServerTool((context: WithRoot<DoomServerPluginContext, McpServerScope>) => context.root.tools[0]!);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport apiRoute from '../src/extensions/(backend)/api/mcp/route.server';\nimport commandMcp from '../src/extensions/workspaces/sessions/(backend)/command/mcp.server';\nimport toolMcpUse from '../src/extensions/workspaces/sessions/(backend)/tool/mcp_use.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-mcp',\n global: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n workspace: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n get commands(): DoomServerSessionPlugin['commands'] { return [via({ name: 'mcp' }, at(commandMcp, contextSession))]; },\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'mcp_use' }, at(toolMcpUse, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.cjs","names":["loadHarnessState","isDoomMcpProjection","mcpSessionConfigFromProjection","path","readSessionConfig","McpSession","MCP_STATUS_KEY","MCP_SESSION_AUTH_STATUS_KEY","formatMcpSessionAuthStatus","createMcpChildTool","SERVER_COMMAND_DESCRIPTION","formatStatus","McpHeadlessToolParameters","DOOM_MCP_PROJECTION_RESOLVER_SERVICE","DOOM_HEADLESS_HOST_SERVICE","DOOM_MCP_STATUS_SERVICE","DOOM_MCP_TOOL_RESOLVER_SERVICE","MCP_SESSION_TOOLS_SERVICE","createMcpSessionToolsService","DOOM_CHILD_SESSION_MCP_TOOL_SERVICE","defineRoot","toPiToolName","os","createTokenStore","fs","path","mcpSessionConfigFromProjection","buildMcpConfigGroups","readCachedCatalog","McpRuntimeOwner","randomUUID","hubCallbackSink","MCP_AUTHORIZATION_API_PATH","MCP_FLOW_ID_PARAM","defineApiRoutes","MCP_REPOSITORY_API_PATH","MCP_REPOSITORY_ID_QUERY","apiResponse","MCP_DISCOVERY_API_PATH","routes","MCP_FLOW_ID_PARAM","MCP_REPOSITORY_ID_QUERY","defineRoute","defineServerCommand","defineServerTool","defineServerPlugin","apiRoute","rootSession","composeRootHooks","commandMcp","toolMcpUse"],"sources":["../../src/services/mcpHeadlessTools/index.ts","../../src/services/serverRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/mcpSettingsManager/index.ts","../../src/types/apiRoutes.ts","../../src/services/mcpHubApi/index.ts","../../src/extensions/(backend)/api/mcp/route.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/mcp.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/mcp_use.server.ts","../../generated/server.ts"],"sourcesContent":["import type { DoomHeadlessTool } from '@agimon-ai/doompi-core/headless';\nimport type { DoomMcpPluginContext } from '@agimon-ai/doompi-core/mcpFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nexport const MCP_HEADLESS_TOOLS_SERVICE = 'doom/mcp-headless-tools';\n\nexport interface McpHeadlessToolCatalog {\n get(name: string): DoomHeadlessTool | undefined;\n}\n\nexport function mountMcpHeadlessTools(tools: readonly DoomHeadlessTool[]) {\n return (context: Context): void => {\n context.plugin((providerContext) => {\n providerContext.provide(MCP_HEADLESS_TOOLS_SERVICE, {\n get: (name) => tools.find((tool) => tool.name === name),\n } satisfies McpHeadlessToolCatalog);\n });\n };\n}\n\nexport function bindMcpHeadlessTool(context: DoomMcpPluginContext, name: string): DoomHeadlessTool {\n const tool = context.services.get<McpHeadlessToolCatalog>(MCP_HEADLESS_TOOLS_SERVICE)?.get(name);\n if (!tool) throw new Error(`MCP tool is unavailable: ${name}`);\n return {\n ...tool,\n execute(toolCallId, parameters, signal, onUpdate) {\n const executionSignal = AbortSignal.any([context.signal, signal ?? context.signal]);\n return tool.execute(toolCallId, parameters, executionSignal, onUpdate, context.execution);\n },\n };\n}\n","import path from 'node:path';\n\nimport { loadHarnessState } from '@agimon-ai/doompi-config/harnessStore';\nimport type {\n DoomHeadlessActivity,\n DoomHeadlessCommand,\n DoomHeadlessExecutionContext,\n DoomHeadlessSelection,\n DoomHeadlessTool,\n} from '@agimon-ai/doompi-core/headless';\nimport { isDoomMcpProjection, type DoomMcpProjectionResolverService } from '@agimon-ai/doompi-core/mcpProjection';\nimport type { DoomMcpSessionConfig } from '@agimon-ai/doompi-core/mcpSession';\n\nimport { COMMAND_NAME, SERVER_COMMAND_DESCRIPTION } from '../../constants/mcp';\nimport { MCP_STATUS_KEY } from '../../constants/piMcp';\nimport { McpHeadlessToolParameters } from '../../schemas/mcpHeadlessTool';\nimport { formatMcpSessionAuthStatus, MCP_SESSION_AUTH_STATUS_KEY } from '../../types/webMcp';\nimport { formatStatus } from '../mcpCommand';\nimport { McpSession } from '../mcpSession';\nimport { createMcpChildTool } from '../mcpSessionTools';\nimport { mcpSessionConfigFromProjection } from '../projection';\nimport { readSessionConfig } from '../sessionConfig';\n\nfunction sessionConfiguration(execution: DoomHeadlessExecutionContext, workspaceRoot?: string): DoomMcpSessionConfig {\n if (workspaceRoot !== undefined) {\n const loaded = loadHarnessState({ ...execution.environment });\n const projection = loaded.state.mcpProjection;\n if (\n loaded.filePath &&\n loaded.state.root === workspaceRoot &&\n execution.repoRoot === workspaceRoot &&\n loaded.state.mcp &&\n loaded.state.majorMode === execution.selection.majorMode &&\n JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) &&\n JSON.stringify(loaded.state.layers) === JSON.stringify(execution.selection.activeLayers) &&\n isDoomMcpProjection(projection) &&\n projection.repoRoot === workspaceRoot\n )\n return mcpSessionConfigFromProjection(projection, execution.cwd);\n return {\n enabled: false,\n repoRoot: execution.cwd,\n stagingDirectory: path.join(execution.cwd, '.doom', 'mcp-disabled'),\n sources: [],\n };\n }\n return readSessionConfig(execution.environment, execution.cwd);\n}\n\nexport function createMcpServerRuntime(\n environment: Readonly<Record<string, string | undefined>> = {},\n workspaceRoot?: string,\n getResolver?: () => DoomMcpProjectionResolverService | undefined,\n) {\n let active: DoomHeadlessExecutionContext | undefined;\n let currentSelection: DoomHeadlessSelection | undefined;\n let staleSelection = false;\n let cleanup: (() => Promise<void>) | undefined;\n let transition = Promise.resolve();\n const authorizing = new Map<string, symbol>();\n const session = new McpSession({\n environment: { ...environment },\n onAuthorizationUrl: async (url, serverName) => {\n if (staleSelection || !session.getServers().some((server) => server.name === serverName)) return;\n await active?.client.notify({\n title: `Authorize MCP server ${serverName}`,\n body: url.toString(),\n level: 'warning',\n });\n },\n });\n\n const refresh = (execution: DoomHeadlessExecutionContext, selection: DoomHeadlessSelection) => {\n staleSelection = true;\n authorizing.clear();\n transition = transition\n .catch(() => {})\n .then(async () => {\n if (active !== execution) return;\n const previousCleanup = cleanup;\n cleanup = undefined;\n try {\n await session.dispose();\n } finally {\n session.install({ enabled: false, repoRoot: execution.cwd, stagingDirectory: execution.cwd });\n await previousCleanup?.();\n }\n if (active !== execution) return;\n const resolver = getResolver?.();\n const loaded = workspaceRoot ? loadHarnessState({ ...execution.environment }) : undefined;\n const authorized =\n workspaceRoot &&\n loaded?.filePath &&\n loaded.state.root === workspaceRoot &&\n execution.repoRoot === workspaceRoot &&\n loaded.state.mcp &&\n loaded.state.majorMode === selection.majorMode &&\n JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) &&\n JSON.stringify(loaded.state.layers) === JSON.stringify(selection.activeLayers) &&\n isDoomMcpProjection(loaded.state.mcpProjection) &&\n loaded.state.mcpProjection.repoRoot === workspaceRoot &&\n loaded.state.mcpProjection.enabled;\n if (!resolver || !authorized) {\n // A missing or disabled saved projection never grants implicit repository access.\n if (active === execution && selection === currentSelection) {\n if (\n workspaceRoot === undefined ||\n JSON.stringify(execution.selection.domains) === JSON.stringify(selection.domains)\n ) {\n await session.reconfigure(\n sessionConfiguration(execution, workspaceRoot),\n execution.cwd,\n execution.repoRoot,\n );\n }\n staleSelection =\n workspaceRoot !== undefined &&\n JSON.stringify(execution.selection.domains) !== JSON.stringify(selection.domains);\n }\n return;\n }\n const candidate = await resolver.resolve(selection.domains);\n if (active !== execution || selection !== currentSelection) {\n await candidate.cleanup();\n return;\n }\n try {\n if (\n !isDoomMcpProjection(candidate.projection) ||\n candidate.projection.repoRoot !== workspaceRoot ||\n !candidate.projection.enabled\n ) {\n throw new Error('The selected domains returned an invalid MCP projection.');\n }\n await session.reconfigure(\n mcpSessionConfigFromProjection(candidate.projection, execution.cwd),\n execution.cwd,\n execution.repoRoot,\n );\n cleanup = () => candidate.cleanup();\n if (active === execution && selection === currentSelection) staleSelection = false;\n } catch (error) {\n await candidate.cleanup();\n throw error;\n }\n })\n .catch(async (error: unknown) => {\n if (active !== execution || selection !== currentSelection) return;\n await execution.client.notify({\n title: 'DoomPi MCP unavailable',\n body: error instanceof Error ? error.message : String(error),\n level: 'warning',\n });\n });\n return transition;\n };\n\n const activity: DoomHeadlessActivity = {\n name: 'doompi-mcp-runtime',\n async start(execution) {\n active = execution;\n currentSelection = execution.selection;\n staleSelection = false;\n const reported = new Set<string>();\n const publish = () => {\n execution.client.setStatus(\n MCP_STATUS_KEY,\n session\n .getServers()\n .map((server) => server.name)\n .join(','),\n );\n execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, formatMcpSessionAuthStatus(session.getServers()));\n for (const diagnostic of session.getDiagnostics()) {\n if (reported.has(diagnostic)) continue;\n reported.add(diagnostic);\n void execution.client.notify({ title: 'DoomPi MCP', body: diagnostic, level: 'warning' });\n }\n };\n const stopPublishing = session.onChange(publish);\n try {\n await refresh(execution, execution.selection);\n publish();\n } catch (error) {\n await execution.client.notify({\n title: 'DoomPi MCP unavailable',\n body: error instanceof Error ? error.message : String(error),\n level: 'warning',\n });\n }\n return async () => {\n stopPublishing();\n if (active !== execution) return;\n active = undefined;\n currentSelection = undefined;\n staleSelection = true;\n authorizing.clear();\n await transition;\n const retiredCleanup = cleanup;\n cleanup = undefined;\n try {\n await session.dispose();\n } finally {\n // Withdraw tools and UI state even when a connection fails to close.\n session.install({ enabled: false, repoRoot: execution.cwd, stagingDirectory: execution.cwd });\n await retiredCleanup?.();\n execution.client.setStatus(MCP_STATUS_KEY, undefined);\n execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, undefined);\n }\n };\n },\n };\n\n const invoke: Parameters<typeof createMcpChildTool>[0] = async (parameters, signal) => {\n if (!active) throw new Error('The MCP runtime has not started yet.');\n if (staleSelection) throw new Error('The MCP projection is stale for the current selection.');\n const selected = session\n .activeToolDefinitions()\n .find((candidate) => candidate.serverName === parameters.server && candidate.toolName === parameters.tool);\n if (!selected)\n throw new Error(`MCP tool ${parameters.server}/${parameters.tool} is not available in this session.`);\n return session.invokeTool(selected.piName, parameters.arguments ?? {}, signal);\n };\n const childTool = createMcpChildTool(invoke);\n\n // web-plugin-tool-renderers: ignore mcp_use, headless-only generic MCP dispatch\n const tool: DoomHeadlessTool<typeof McpHeadlessToolParameters> = {\n name: 'mcp_use',\n label: 'MCP use',\n description: 'Call a tool exposed by a connected MCP server.',\n parameters: McpHeadlessToolParameters,\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n try {\n return await invoke(parameters, signal);\n } catch (error) {\n return {\n content: [{ type: 'text', text: error instanceof Error ? error.message : String(error) }],\n isError: true,\n };\n }\n },\n };\n\n const command: DoomHeadlessCommand = {\n name: COMMAND_NAME,\n description: SERVER_COMMAND_DESCRIPTION,\n async execute(args, execution) {\n const [subcommand = 'status', ...rest] = args.trim().split(/\\s+/u).filter(Boolean);\n const serverName = rest.join(' ');\n const notify = (body: string, level: 'info' | 'warning' = 'info') =>\n execution.client.notify({ title: 'DoomPi MCP', body, level });\n try {\n if (subcommand === 'status') {\n await notify(formatStatus(session));\n return;\n }\n if (!active) throw new Error('The MCP runtime has not started yet.');\n if (staleSelection) throw new Error('The MCP projection is stale for the current selection.');\n if (subcommand === 'auth' || subcommand === 'disconnect') {\n if (!serverName) throw new Error(`Name the server, for example /mcp ${subcommand} <server>.`);\n const server = session.getServers().find((candidate) => candidate.name === serverName);\n if (!server) throw new Error(`Unknown MCP server: ${serverName}`);\n if (subcommand === 'disconnect') {\n await session.disconnect(serverName);\n authorizing.delete(serverName);\n await notify(`${serverName} is disconnected from this session. Saved credentials were kept.`);\n return;\n }\n if (server.authorizationUrl) {\n await session.openAuthorizationPage(serverName);\n return;\n }\n if (authorizing.has(serverName)) return;\n const request = Symbol(serverName);\n authorizing.set(serverName, request);\n const owner = active;\n // OAuth waits for the browser. Do not hold the session command queue while it does.\n void session.reauthorize(serverName).then(\n async () => {\n if (active !== owner || authorizing.get(serverName) !== request) return;\n authorizing.delete(serverName);\n await notify(`${serverName} is authorized.`);\n },\n async (error: unknown) => {\n if (active !== owner || authorizing.get(serverName) !== request) return;\n authorizing.delete(serverName);\n await notify(\n `Could not authorize ${serverName}: ${error instanceof Error ? error.message : String(error)}`,\n 'warning',\n );\n },\n );\n return;\n }\n if (subcommand === 'reload') {\n if (!currentSelection) throw new Error('The MCP runtime has not started yet.');\n await refresh(active, currentSelection);\n if (!staleSelection) await notify('Reconnecting MCP servers.');\n return;\n }\n throw new Error(`Unknown /${COMMAND_NAME} subcommand \"${subcommand}\". Use status, auth, disconnect, reload.`);\n } catch (error) {\n await notify(error instanceof Error ? error.message : String(error), 'warning');\n }\n },\n };\n return {\n session,\n activities: [activity],\n commands: [command],\n tools: [tool],\n childTool,\n async onSelectionChange(selection: DoomHeadlessSelection) {\n if (!active || workspaceRoot === undefined) return;\n if (JSON.stringify(currentSelection) === JSON.stringify(selection)) return;\n currentSelection = selection;\n await refresh(active, selection);\n },\n };\n}\n","import { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE } from '@agimon-ai/doompi-core/childSession';\nimport { DOOM_HEADLESS_HOST_SERVICE, type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport {\n DOOM_MCP_PROJECTION_RESOLVER_SERVICE,\n type DoomMcpProjectionResolverService,\n} from '@agimon-ai/doompi-core/mcpProjection';\nimport { DOOM_MCP_STATUS_SERVICE, type DoomMcpStatusService } from '@agimon-ai/doompi-core/mcpStatus';\nimport {\n DOOM_MCP_TOOL_RESOLVER_SERVICE,\n type DoomMcpToolResolverService,\n} from '@agimon-ai/doompi-core/mcpToolResolver';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { mountMcpHeadlessTools } from '../../../../../services/mcpHeadlessTools';\nimport { createMcpSessionToolsService, MCP_SESSION_TOOLS_SERVICE } from '../../../../../services/mcpSessionTools';\nimport { createMcpServerRuntime } from '../../../../../services/serverRuntime';\n\nexport const createMcpServerRoot = (context?: DoomServerPluginContext) => {\n let resolver: DoomMcpProjectionResolverService | undefined;\n const runtime = createMcpServerRuntime(\n context?.agent?.context?.environment,\n context?.host.context.workspaceRoot,\n () => resolver,\n );\n const generation = `${context?.agent?.context?.sessionId ?? crypto.randomUUID()}:mcp-server`;\n const { session } = runtime;\n const mountSession = (cordis: Context) => {\n cordis.inject([DOOM_MCP_PROJECTION_RESOLVER_SERVICE], (resolverContext) => {\n resolver = resolverContext.get(DOOM_MCP_PROJECTION_RESOLVER_SERVICE) as DoomMcpProjectionResolverService;\n return () => {\n resolver = undefined;\n };\n });\n cordis.inject([DOOM_HEADLESS_HOST_SERVICE], (hostContext) => {\n const host = hostContext.get(DOOM_HEADLESS_HOST_SERVICE) as DoomHeadlessHostService;\n return host.subscribeSelection((selection) => runtime.onSelectionChange(selection));\n });\n cordis.plugin((provider) => {\n provider.provide(DOOM_MCP_STATUS_SERVICE, {\n generation,\n getSnapshot: () => session.getSnapshot(),\n onChange: (listener) => session.onChange(listener),\n } satisfies DoomMcpStatusService);\n provider.provide(DOOM_MCP_TOOL_RESOLVER_SERVICE, {\n generation,\n resolve: (selectors) => session.resolveToolSelectors(selectors),\n } satisfies DoomMcpToolResolverService);\n provider.provide(MCP_SESSION_TOOLS_SERVICE, createMcpSessionToolsService(session, generation));\n provider.provide(DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, runtime.childTool);\n });\n };\n return {\n value: runtime,\n activities: runtime.activities,\n services: [mountMcpHeadlessTools(runtime.tools), mountSession],\n };\n};\nexport type McpServerScope = Awaited<ReturnType<typeof createMcpServerRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createMcpServerRoot } from './_lib/serverRoot';\n\nexport default defineRoot(createMcpServerRoot);\n","import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport type { DoomOAuthRedirect, DoomRepositorySyncView } from '@agimon-ai/doompi-core/packageApi';\nimport type { McpServerStateChange, McpToolInfo, TokenStore } from '@agimon-ai/mcp-proxy';\n\nimport type { McpConfigGroups, McpConfigSource, McpSessionConfig } from '../../types/mcpConfig';\nimport type {\n McpAuthorizationFlow,\n McpRepositoryCatalog,\n McpRepositoryServer,\n McpRepositoryServerState,\n McpRepositoryTool,\n} from '../../types/webMcp';\nimport { buildMcpConfigGroups } from '../configSources';\nimport { createTokenStore } from '../keyringTokenStore';\nimport { toPiToolName } from '../mcpCatalog';\nimport { hubCallbackSink, McpRuntimeOwner, readCachedCatalog } from '../mcpRuntime';\nimport { mcpSessionConfigFromProjection } from '../projection';\n\nconst DISCOVERY_TIMEOUT_MS = 30_000;\nconst AUTHORIZATION_TIMEOUT_MS = 5 * 60_000;\nconst TERMINAL_FLOW_RETENTION_MS = 5 * 60_000;\nconst EMPTY_SYNC = { fresh: false, reasons: ['never-synced'] } as const;\n\ninterface PreparedMcpRepository {\n catalog: McpRepositoryCatalog;\n configSources: McpConfigSource[];\n groups: McpConfigGroups;\n stagingDirectory?: string;\n}\n\ninterface InternalAuthorizationFlow extends McpAuthorizationFlow {\n owner?: McpRuntimeOwner;\n stagingDirectory?: string;\n timeout?: ReturnType<typeof setTimeout>;\n retainedUntil?: number;\n}\n\nexport interface McpSettingsManagerOptions {\n discoveryTimeoutMs?: number;\n authorizationTimeoutMs?: number;\n tokenStore?: TokenStore;\n}\n\nfunction configuredServerNames(groups: McpConfigGroups): string[] {\n return [...new Set([...groups.sessionLocal.serverNames, ...groups.shared.serverNames])].sort((left, right) =>\n left.localeCompare(right),\n );\n}\n\nfunction configSources(groups: McpConfigGroups): McpConfigSource[] {\n return [...groups.sessionLocal.configSources, ...groups.shared.configSources];\n}\n\nfunction toolView(serverName: string, tool: McpToolInfo): McpRepositoryTool {\n return {\n name: tool.name,\n piName: toPiToolName(serverName, tool.name),\n ...(tool.description ? { description: tool.description } : {}),\n };\n}\n\nfunction sanitizeDiagnostic(message: string, repositoryRoot: string, stagingDirectory: string | undefined): string {\n let safe = message;\n for (const value of [stagingDirectory, repositoryRoot, os.homedir()]) {\n if (value) safe = safe.split(value).join(value === os.homedir() ? '~' : '<repository>');\n }\n return safe.replace(/[A-Za-z]:\\\\[^\\s,;)'\"`]+/gu, '<path>').replace(/(^|\\s)\\/(?!\\/)[^\\s,;)'\"`]+/gu, '$1<path>');\n}\n\nfunction publicFlow(flow: InternalAuthorizationFlow): McpAuthorizationFlow {\n return {\n id: flow.id,\n repositoryId: flow.repositoryId,\n serverName: flow.serverName,\n status: flow.status,\n ...(flow.authorizationUrl ? { authorizationUrl: flow.authorizationUrl } : {}),\n ...(flow.error ? { error: flow.error } : {}),\n expiresAt: flow.expiresAt,\n };\n}\n\nfunction isTerminal(status: McpAuthorizationFlow['status']): boolean {\n return status === 'completed' || status === 'failed' || status === 'cancelled' || status === 'expired';\n}\n\nfunction safeAuthorizationUrl(url: URL): string | undefined {\n if ((url.protocol !== 'https:' && url.protocol !== 'http:') || url.toString().length > 4096) return undefined;\n return url.toString();\n}\n\nexport class McpSettingsManager {\n private readonly discoveryTimeoutMs: number;\n private readonly authorizationTimeoutMs: number;\n private readonly injectedTokenStore?: TokenStore;\n private readonly busyRepositories = new Set<string>();\n private readonly flows = new Map<string, InternalAuthorizationFlow>();\n\n constructor(options: McpSettingsManagerOptions = {}) {\n this.discoveryTimeoutMs = options.discoveryTimeoutMs ?? DISCOVERY_TIMEOUT_MS;\n this.authorizationTimeoutMs = options.authorizationTimeoutMs ?? AUTHORIZATION_TIMEOUT_MS;\n this.injectedTokenStore = options.tokenStore;\n }\n\n private async tokenStore(): Promise<TokenStore> {\n return this.injectedTokenStore ?? (await createTokenStore());\n }\n\n private async credentialPresence(serverNames: readonly string[]): Promise<Map<string, boolean>> {\n const presence = new Map<string, boolean>();\n try {\n const tokenStore = await this.tokenStore();\n await Promise.all(\n serverNames.map(async (serverName) => {\n try {\n presence.set(serverName, (await tokenStore.read(serverName)) !== undefined);\n } catch {\n presence.set(serverName, false);\n }\n }),\n );\n } catch {\n for (const serverName of serverNames) presence.set(serverName, false);\n }\n return presence;\n }\n\n private prepare(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n onlyServer?: string,\n ): PreparedMcpRepository {\n if (!sync?.mcpProjection) {\n const readiness = sync ?? EMPTY_SYNC;\n return {\n catalog: {\n repositoryId,\n sync: { fresh: readiness.fresh, reasons: [...readiness.reasons] },\n servers: [],\n droppedServers: [],\n diagnostics: [],\n },\n configSources: [],\n groups: {\n shared: { configSources: [], configPaths: [], serverNames: [] },\n sessionLocal: { configSources: [], configPaths: [], serverNames: [] },\n droppedServers: [],\n diagnostics: [],\n },\n };\n }\n\n const stagingDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'doompi-mcp-settings-'));\n fs.chmodSync(stagingDirectory, 0o700);\n try {\n const projected = mcpSessionConfigFromProjection(sync.mcpProjection);\n const configuration: McpSessionConfig = {\n ...projected,\n repoRoot: repositoryRoot,\n stagingDirectory,\n ...(onlyServer ? { allowlist: { servers: [onlyServer], proxy: [] } } : {}),\n };\n const groups = buildMcpConfigGroups(configuration);\n const sources = configSources(groups);\n const names = configuredServerNames(groups);\n const cachedByServer = new Map(readCachedCatalog(sources).servers.map((server) => [server.name, server.tools]));\n const servers: McpRepositoryServer[] = names.map((name) => {\n const tools = cachedByServer.get(name) ?? [];\n return {\n name,\n state: 'not-connected',\n source: tools.length === 0 ? 'configured' : 'cached',\n credentialPresent: false,\n tools: tools.map((tool) => toolView(name, tool)),\n };\n });\n return {\n catalog: {\n repositoryId,\n sync: { fresh: sync.fresh, reasons: [...sync.reasons] },\n servers,\n droppedServers: [...groups.droppedServers],\n diagnostics: groups.diagnostics.map((diagnostic) =>\n sanitizeDiagnostic(diagnostic, repositoryRoot, stagingDirectory),\n ),\n },\n configSources: sources,\n groups,\n stagingDirectory,\n };\n } catch (error) {\n fs.rmSync(stagingDirectory, { recursive: true, force: true });\n throw error;\n }\n }\n\n private cleanupPrepared(prepared: PreparedMcpRepository): void {\n if (prepared.stagingDirectory) fs.rmSync(prepared.stagingDirectory, { recursive: true, force: true });\n }\n\n async readCatalog(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n ): Promise<McpRepositoryCatalog> {\n const prepared = this.prepare(repositoryId, repositoryRoot, sync);\n try {\n const presence = await this.credentialPresence(prepared.catalog.servers.map((server) => server.name));\n return {\n ...prepared.catalog,\n servers: prepared.catalog.servers.map((server) => ({\n ...server,\n credentialPresent: presence.get(server.name) ?? false,\n })),\n };\n } finally {\n this.cleanupPrepared(prepared);\n }\n }\n\n async discover(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n ): Promise<McpRepositoryCatalog> {\n if (this.busyRepositories.has(repositoryId))\n throw new Error('MCP management is already active for this repository.');\n const prepared = this.prepare(repositoryId, repositoryRoot, sync);\n if (!prepared.catalog.sync.fresh) {\n this.cleanupPrepared(prepared);\n throw new Error('Sync this repository before discovering MCP capabilities.');\n }\n if (prepared.configSources.length === 0) {\n this.cleanupPrepared(prepared);\n return prepared.catalog;\n }\n\n this.busyRepositories.add(repositoryId);\n const owner = new McpRuntimeOwner();\n const liveStates = new Map<string, McpServerStateChange>();\n try {\n const handle = await owner.start({\n configSources: prepared.configSources,\n workspaceRoot: repositoryRoot,\n executionCwd: repositoryRoot,\n tokenStore: await this.tokenStore(),\n onAuthorizationUrl: (_url, serverName) => {\n liveStates.set(serverName, { serverName, state: 'needs-auth' });\n },\n onServerStateChange: (change) => liveStates.set(change.serverName, change),\n });\n if (handle) {\n await Promise.race([\n handle.connectionsSettled,\n new Promise<void>((resolve) => setTimeout(resolve, this.discoveryTimeoutMs)),\n ]);\n }\n const manager = handle?.services.clientManager;\n const cachedByServer = new Map(\n readCachedCatalog(prepared.configSources).servers.map((server) => [server.name, server.tools]),\n );\n const presence = await this.credentialPresence(prepared.catalog.servers.map((server) => server.name));\n const servers = await Promise.all(\n prepared.catalog.servers.map(async (server): Promise<McpRepositoryServer> => {\n const change = liveStates.get(server.name);\n const state = (change?.state ??\n manager?.getServerState(server.name) ??\n server.state) as McpRepositoryServerState;\n let tools = cachedByServer.get(server.name) ?? [];\n let source: McpRepositoryServer['source'] = tools.length === 0 ? 'configured' : 'cached';\n if (state === 'connected' && manager) {\n try {\n tools = await manager\n .ensureConnected(server.name)\n .then(async (connection) => await connection.listTools());\n source = 'live';\n } catch {\n // Preserve the cache when a server moved between state inspection and listing.\n }\n }\n return {\n name: server.name,\n state,\n source,\n credentialPresent: presence.get(server.name) ?? false,\n tools: tools.map((tool) => toolView(server.name, tool)),\n ...(change?.error ? { error: 'The server reported a connection error.' } : {}),\n };\n }),\n );\n return { ...prepared.catalog, servers };\n } finally {\n await owner.dispose();\n this.cleanupPrepared(prepared);\n this.busyRepositories.delete(repositoryId);\n }\n }\n\n async authorize(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n serverName: string,\n /**\n * The hub's redirect surface. Present, the authorization server sends the\n * browser back to the hub, which is reachable whether the operator is at\n * this machine or on a tunnel. Absent, the proxy keeps its loopback\n * listener and behaviour is unchanged.\n */\n redirect?: DoomOAuthRedirect,\n ): Promise<McpAuthorizationFlow> {\n this.sweepFlows();\n if (this.busyRepositories.has(repositoryId))\n throw new Error('MCP management is already active for this repository.');\n\n const full = this.prepare(repositoryId, repositoryRoot, sync);\n const configured = full.catalog.servers.some((server) => server.name === serverName);\n const fresh = full.catalog.sync.fresh;\n this.cleanupPrepared(full);\n if (!fresh) throw new Error('Sync this repository before authorizing an MCP server.');\n if (!configured) throw new Error('That MCP server is not enabled for this repository.');\n\n const prepared = this.prepare(repositoryId, repositoryRoot, sync, serverName);\n const flow: InternalAuthorizationFlow = {\n id: randomUUID(),\n repositoryId,\n serverName,\n status: 'starting',\n expiresAt: Date.now() + this.authorizationTimeoutMs,\n stagingDirectory: prepared.stagingDirectory,\n };\n this.flows.set(flow.id, flow);\n this.busyRepositories.add(repositoryId);\n void this.runAuthorization(flow, prepared.configSources, repositoryRoot, redirect);\n return publicFlow(flow);\n }\n\n getAuthorization(flowId: string, repositoryId: string): McpAuthorizationFlow | undefined {\n this.sweepFlows();\n const flow = this.flows.get(flowId);\n return flow?.repositoryId === repositoryId ? publicFlow(flow) : undefined;\n }\n\n async cancelAuthorization(flowId: string, repositoryId: string): Promise<McpAuthorizationFlow | undefined> {\n const flow = this.flows.get(flowId);\n if (!flow || flow.repositoryId !== repositoryId) return undefined;\n if (!isTerminal(flow.status)) {\n flow.status = 'cancelled';\n await this.finishFlow(flow);\n }\n return publicFlow(flow);\n }\n\n private async runAuthorization(\n flow: InternalAuthorizationFlow,\n sources: McpConfigSource[],\n repositoryRoot: string,\n redirect?: DoomOAuthRedirect,\n ): Promise<void> {\n const owner = new McpRuntimeOwner();\n flow.owner = owner;\n flow.timeout = setTimeout(() => {\n if (isTerminal(flow.status)) return;\n flow.status = 'expired';\n flow.error = 'Authorization timed out.';\n void this.finishFlow(flow);\n }, this.authorizationTimeoutMs);\n\n try {\n const handle = await owner.start({\n configSources: sources,\n workspaceRoot: repositoryRoot,\n executionCwd: repositoryRoot,\n tokenStore: await this.tokenStore(),\n ...(redirect ? { callbackServer: hubCallbackSink(redirect) } : {}),\n onAuthorizationUrl: (url, serverName) => {\n if (serverName !== flow.serverName || isTerminal(flow.status)) return;\n const safeUrl = safeAuthorizationUrl(url);\n if (!safeUrl) {\n flow.status = 'failed';\n flow.error = 'The server returned an invalid authorization URL.';\n void this.finishFlow(flow);\n return;\n }\n flow.authorizationUrl = safeUrl;\n flow.status = 'waiting';\n },\n onServerStateChange: (change) => this.applyAuthorizationState(flow, change),\n });\n if (!handle || isTerminal(flow.status)) return;\n const manager = handle.services.clientManager;\n await manager.disconnectServer(flow.serverName);\n await manager.ensureConnected(flow.serverName);\n if (!isTerminal(flow.status)) flow.status = 'completed';\n } catch {\n if (!isTerminal(flow.status)) {\n flow.status = 'failed';\n flow.error = 'The MCP server could not complete authorization.';\n }\n } finally {\n if (!isTerminal(flow.status)) flow.status = 'completed';\n await this.finishFlow(flow);\n }\n }\n\n private applyAuthorizationState(flow: InternalAuthorizationFlow, change: McpServerStateChange): void {\n if (change.serverName !== flow.serverName || isTerminal(flow.status)) return;\n if (change.state === 'connected') flow.status = 'completed';\n else if (change.state === 'needs-auth' && flow.status === 'starting') flow.status = 'waiting';\n else if (change.state === 'failed') {\n flow.status = 'failed';\n flow.error = 'The MCP server rejected the authorization attempt.';\n }\n }\n\n private async finishFlow(flow: InternalAuthorizationFlow): Promise<void> {\n if (flow.timeout) clearTimeout(flow.timeout);\n flow.timeout = undefined;\n const owner = flow.owner;\n flow.owner = undefined;\n await owner?.dispose();\n if (flow.stagingDirectory) fs.rmSync(flow.stagingDirectory, { recursive: true, force: true });\n flow.stagingDirectory = undefined;\n this.busyRepositories.delete(flow.repositoryId);\n flow.retainedUntil = Date.now() + TERMINAL_FLOW_RETENTION_MS;\n }\n\n private sweepFlows(): void {\n const now = Date.now();\n for (const [id, flow] of this.flows) {\n if (flow.retainedUntil !== undefined && flow.retainedUntil <= now) this.flows.delete(id);\n }\n }\n\n async dispose(): Promise<void> {\n await Promise.all(\n [...this.flows.values()].map(async (flow) => {\n if (!isTerminal(flow.status)) flow.status = 'cancelled';\n await this.finishFlow(flow);\n }),\n );\n this.flows.clear();\n this.busyRepositories.clear();\n }\n}\n","import { apiResponse, defineApiRoutes } from '@agimon-ai/doompi-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 type McpAuthorizationFlow,\n type McpRepositoryCatalog,\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});\n","import type { DoomApi, DoomApiContext } from '@agimon-ai/doompi-core/packageApi';\n\nimport { McpSettingsManager } from '../../services/mcpSettingsManager';\nimport routes from '../../types/apiRoutes';\nimport { MCP_FLOW_ID_PARAM, MCP_REPOSITORY_ID_QUERY } from '../../types/webMcp';\n\n/**\n * What sits above a flow id, read off the flow route itself.\n *\n * This handler matches paths by hand rather than through a router, so the one\n * route carrying a parameter is split here: everything before `:flowId` is the\n * prefix a request must start with, and what follows it is the id.\n */\nconst AUTHORIZATION_FLOW_PREFIX = routes.readAuthorization.path.replace(`:${MCP_FLOW_ID_PARAM}`, '');\n\nconst JSON_HEADERS = { 'content-type': 'application/json' };\nconst REPOSITORY_ID = /^(?:[a-f0-9]{32}|repo-[A-Za-z0-9_-]{24})$/u;\nconst FLOW_ID = /^[a-f0-9-]{36}$/u;\nconst MAX_BODY_BYTES = 8 * 1024;\nconst MAX_SERVER_NAME = 160;\nconst manager = new McpSettingsManager();\n\ntype JsonRecord = Record<string, unknown>;\n\nfunction json(body: unknown, status = 200): Response {\n return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS });\n}\n\nfunction isRecord(value: unknown): value is JsonRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nasync function bodyOf(request: Request): Promise<JsonRecord | undefined> {\n const text = await request.text();\n if (text.length > MAX_BODY_BYTES) return undefined;\n try {\n const parsed = JSON.parse(text) as unknown;\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction repositoryIdOf(value: unknown): string | undefined {\n return typeof value === 'string' && REPOSITORY_ID.test(value) ? value : undefined;\n}\n\nfunction serverNameOf(value: unknown): string | undefined {\n return typeof value === 'string' &&\n value.length > 0 &&\n value.length <= MAX_SERVER_NAME &&\n !Array.from(value).some((character) => character.charCodeAt(0) <= 0x1f)\n ? value\n : undefined;\n}\n\nfunction resolveRepository(context: DoomApiContext, repositoryId: string): string | undefined {\n return context.resolveRepository?.(repositoryId);\n}\n\nfunction errorStatus(error: unknown): { status: number; message: string } {\n const message = error instanceof Error ? error.message : '';\n if (message.includes('already active')) return { status: 409, message };\n if (message.startsWith('Sync this repository')) return { status: 409, message };\n if (message.includes('not enabled')) return { status: 404, message };\n return { status: 500, message: 'MCP management could not complete that request.' };\n}\n\nasync function handleCatalog(request: Request, context: DoomApiContext): Promise<Response> {\n const repositoryId = repositoryIdOf(new URL(request.url).searchParams.get(MCP_REPOSITORY_ID_QUERY));\n if (!repositoryId) return json({ error: 'A valid repositoryId is required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(await manager.readCatalog(repositoryId, repositoryRoot, context.readRepositorySync?.(repositoryId)));\n } catch {\n return json({ error: 'The synced MCP catalog could not be read.' }, 500);\n }\n}\n\nasync function handleDiscovery(request: Request, context: DoomApiContext): Promise<Response> {\n const body = await bodyOf(request);\n const repositoryId = repositoryIdOf(body?.repositoryId);\n if (!repositoryId) return json({ error: 'A valid repositoryId is required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(await manager.discover(repositoryId, repositoryRoot, context.readRepositorySync?.(repositoryId)));\n } catch (error) {\n const failure = errorStatus(error);\n return json({ error: failure.message }, failure.status);\n }\n}\n\nasync function handleAuthorize(request: Request, context: DoomApiContext): Promise<Response> {\n const body = await bodyOf(request);\n const repositoryId = repositoryIdOf(body?.repositoryId);\n const serverName = serverNameOf(body?.serverName);\n if (!repositoryId || !serverName) return json({ error: 'A valid repositoryId and serverName are required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(\n await manager.authorize(\n repositoryId,\n repositoryRoot,\n context.readRepositorySync?.(repositoryId),\n serverName,\n context.oauthRedirect?.(),\n ),\n 202,\n );\n } catch (error) {\n const failure = errorStatus(error);\n return json({ error: failure.message }, failure.status);\n }\n}\n\nasync function handleAuthorizationFlow(request: Request, context: DoomApiContext, path: string): Promise<Response> {\n const flowId = path.slice(AUTHORIZATION_FLOW_PREFIX.length);\n const repositoryId = repositoryIdOf(new URL(request.url).searchParams.get(MCP_REPOSITORY_ID_QUERY));\n if (!repositoryId || !FLOW_ID.test(flowId))\n return json({ error: 'A valid repositoryId and flow id are required.' }, 400);\n if (!resolveRepository(context, repositoryId)) {\n return json({ error: 'That repository is not available to this hub.' }, 404);\n }\n if (request.method === routes.cancelAuthorization.method) {\n const flow = await manager.cancelAuthorization(flowId, repositoryId);\n return flow ? json(flow) : json({ error: 'That authorization flow was not found.' }, 404);\n }\n const flow = manager.getAuthorization(flowId, repositoryId);\n return flow ? json(flow) : json({ error: 'That authorization flow was not found.' }, 404);\n}\n\nexport const mcpHubApi: DoomApi = {\n basePath: 'mcp',\n start(context) {\n return {\n async fetch(request) {\n const path = new URL(request.url).pathname;\n if (request.method === routes.catalog.method && path === routes.catalog.path) {\n return await handleCatalog(request, context);\n }\n if (request.method === routes.discover.method && path === routes.discover.path) {\n return await handleDiscovery(request, context);\n }\n if (request.method === routes.authorize.method && path === routes.authorize.path) {\n return await handleAuthorize(request, context);\n }\n if (\n (request.method === routes.readAuthorization.method ||\n request.method === routes.cancelAuthorization.method) &&\n path.startsWith(AUTHORIZATION_FLOW_PREFIX)\n ) {\n return await handleAuthorizationFlow(request, context, path);\n }\n return json({ error: 'Not found.' }, 404);\n },\n close() {\n void manager.dispose();\n },\n };\n },\n};\n","import { defineRoute } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { mcpHubApi } from '../../../../services/mcpHubApi';\n\n/**\n * Mounts this package's HTTP API at `mcp`, which the folder names.\n *\n * The folder is the declaration: the build reads the base path off it and hands\n * the browser a client bound to the same segment, so the settings panel can no\n * longer spell a workspace mount by hand.\n */\nexport default defineRoute(mcpHubApi);\n","import { defineServerCommand, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { McpServerScope } from '../_lib/serverRoot';\nexport default defineServerCommand(\n (context: WithRoot<DoomServerPluginContext, McpServerScope>) => context.root.commands[0]!,\n);\n","import { defineServerTool, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { McpServerScope } from '../_lib/serverRoot';\nexport default defineServerTool((context: WithRoot<DoomServerPluginContext, McpServerScope>) => context.root.tools[0]!);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport apiRoute from '../src/extensions/(backend)/api/mcp/route.server';\nimport commandMcp from '../src/extensions/workspaces/sessions/(backend)/command/mcp.server';\nimport toolMcpUse from '../src/extensions/workspaces/sessions/(backend)/tool/mcp_use.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-mcp',\n global: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n workspace: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n get commands(): DoomServerSessionPlugin['commands'] { return [via({ name: 'mcp' }, at(commandMcp, contextSession))]; },\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'mcp_use' }, at(toolMcpUse, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
@@ -6,7 +6,7 @@ import { randomUUID } from "node:crypto";
6
6
  import fs from "node:fs";
7
7
  import path from "node:path";
8
8
  import os from "node:os";
9
- import { isDoomMcpProjection } from "@agimon-ai/doompi-core/mcpProjection";
9
+ import { DOOM_MCP_PROJECTION_RESOLVER_SERVICE, isDoomMcpProjection } from "@agimon-ai/doompi-core/mcpProjection";
10
10
  import { composeRootHooks, defineRoot, defineRoute, defineServerCommand, defineServerTool } from "@agimon-ai/doompi-core/extensionFile";
11
11
  import { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE } from "@agimon-ai/doompi-core/childSession";
12
12
  import { DOOM_MCP_STATUS_SERVICE } from "@agimon-ai/doompi-core/mcpStatus";
@@ -40,13 +40,17 @@ function sessionConfiguration(execution, workspaceRoot) {
40
40
  }
41
41
  return readSessionConfig(execution.environment, execution.cwd);
42
42
  }
43
- function createMcpServerRuntime(environment = {}, workspaceRoot) {
43
+ function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver) {
44
44
  let active;
45
+ let currentSelection;
45
46
  let staleSelection = false;
47
+ let cleanup;
48
+ let transition = Promise.resolve();
46
49
  const authorizing = /* @__PURE__ */ new Map();
47
50
  const session = new McpSession({
48
51
  environment: { ...environment },
49
52
  onAuthorizationUrl: async (url, serverName) => {
53
+ if (staleSelection || !session.getServers().some((server) => server.name === serverName)) return;
50
54
  await active?.client.notify({
51
55
  title: `Authorize MCP server ${serverName}`,
52
56
  body: url.toString(),
@@ -54,10 +58,63 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
54
58
  });
55
59
  }
56
60
  });
61
+ const refresh = (execution, selection) => {
62
+ staleSelection = true;
63
+ authorizing.clear();
64
+ transition = transition.catch(() => {}).then(async () => {
65
+ if (active !== execution) return;
66
+ const previousCleanup = cleanup;
67
+ cleanup = void 0;
68
+ try {
69
+ await session.dispose();
70
+ } finally {
71
+ session.install({
72
+ enabled: false,
73
+ repoRoot: execution.cwd,
74
+ stagingDirectory: execution.cwd
75
+ });
76
+ await previousCleanup?.();
77
+ }
78
+ if (active !== execution) return;
79
+ const resolver = getResolver?.();
80
+ const loaded = workspaceRoot ? loadHarnessState({ ...execution.environment }) : void 0;
81
+ const authorized = workspaceRoot && loaded?.filePath && loaded.state.root === workspaceRoot && execution.repoRoot === workspaceRoot && loaded.state.mcp && loaded.state.majorMode === selection.majorMode && JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) && JSON.stringify(loaded.state.layers) === JSON.stringify(selection.activeLayers) && isDoomMcpProjection(loaded.state.mcpProjection) && loaded.state.mcpProjection.repoRoot === workspaceRoot && loaded.state.mcpProjection.enabled;
82
+ if (!resolver || !authorized) {
83
+ if (active === execution && selection === currentSelection) {
84
+ if (workspaceRoot === void 0 || JSON.stringify(execution.selection.domains) === JSON.stringify(selection.domains)) await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);
85
+ staleSelection = workspaceRoot !== void 0 && JSON.stringify(execution.selection.domains) !== JSON.stringify(selection.domains);
86
+ }
87
+ return;
88
+ }
89
+ const candidate = await resolver.resolve(selection.domains);
90
+ if (active !== execution || selection !== currentSelection) {
91
+ await candidate.cleanup();
92
+ return;
93
+ }
94
+ try {
95
+ if (!isDoomMcpProjection(candidate.projection) || candidate.projection.repoRoot !== workspaceRoot || !candidate.projection.enabled) throw new Error("The selected domains returned an invalid MCP projection.");
96
+ await session.reconfigure(mcpSessionConfigFromProjection(candidate.projection, execution.cwd), execution.cwd, execution.repoRoot);
97
+ cleanup = () => candidate.cleanup();
98
+ if (active === execution && selection === currentSelection) staleSelection = false;
99
+ } catch (error) {
100
+ await candidate.cleanup();
101
+ throw error;
102
+ }
103
+ }).catch(async (error) => {
104
+ if (active !== execution || selection !== currentSelection) return;
105
+ await execution.client.notify({
106
+ title: "DoomPi MCP unavailable",
107
+ body: error instanceof Error ? error.message : String(error),
108
+ level: "warning"
109
+ });
110
+ });
111
+ return transition;
112
+ };
57
113
  const activity = {
58
114
  name: "doompi-mcp-runtime",
59
115
  async start(execution) {
60
116
  active = execution;
117
+ currentSelection = execution.selection;
61
118
  staleSelection = false;
62
119
  const reported = /* @__PURE__ */ new Set();
63
120
  const publish = () => {
@@ -75,7 +132,7 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
75
132
  };
76
133
  const stopPublishing = session.onChange(publish);
77
134
  try {
78
- await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);
135
+ await refresh(execution, execution.selection);
79
136
  publish();
80
137
  } catch (error) {
81
138
  await execution.client.notify({
@@ -88,8 +145,12 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
88
145
  stopPublishing();
89
146
  if (active !== execution) return;
90
147
  active = void 0;
91
- staleSelection = false;
148
+ currentSelection = void 0;
149
+ staleSelection = true;
92
150
  authorizing.clear();
151
+ await transition;
152
+ const retiredCleanup = cleanup;
153
+ cleanup = void 0;
93
154
  try {
94
155
  await session.dispose();
95
156
  } finally {
@@ -98,6 +159,7 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
98
159
  repoRoot: execution.cwd,
99
160
  stagingDirectory: execution.cwd
100
161
  });
162
+ await retiredCleanup?.();
101
163
  execution.client.setStatus(MCP_STATUS_KEY, void 0);
102
164
  execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, void 0);
103
165
  }
@@ -163,18 +225,9 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
163
225
  return;
164
226
  }
165
227
  if (subcommand === "reload") {
166
- authorizing.clear();
167
- try {
168
- await session.dispose();
169
- } finally {
170
- session.install({
171
- enabled: false,
172
- repoRoot: execution.cwd,
173
- stagingDirectory: execution.cwd
174
- });
175
- }
176
- await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);
177
- await notify("Reconnecting MCP servers.");
228
+ if (!currentSelection) throw new Error("The MCP runtime has not started yet.");
229
+ await refresh(active, currentSelection);
230
+ if (!staleSelection) await notify("Reconnecting MCP servers.");
178
231
  return;
179
232
  }
180
233
  throw new Error(`Unknown /mcp subcommand "${subcommand}". Use status, auth, disconnect, reload.`);
@@ -206,26 +259,26 @@ function createMcpServerRuntime(environment = {}, workspaceRoot) {
206
259
  childTool,
207
260
  async onSelectionChange(selection) {
208
261
  if (!active || workspaceRoot === void 0) return;
209
- const initial = active.selection;
210
- if (!initial || JSON.stringify(initial.domains) === JSON.stringify(selection.domains)) return;
211
- staleSelection = true;
212
- authorizing.clear();
213
- await session.reconfigure({
214
- enabled: false,
215
- repoRoot: active.cwd,
216
- stagingDirectory: path.join(active.cwd, ".doom", "mcp-disabled"),
217
- sources: []
218
- });
262
+ if (JSON.stringify(currentSelection) === JSON.stringify(selection)) return;
263
+ currentSelection = selection;
264
+ await refresh(active, selection);
219
265
  }
220
266
  };
221
267
  }
222
268
  //#endregion
223
269
  //#region src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts
224
270
  const createMcpServerRoot = (context) => {
225
- const runtime = createMcpServerRuntime(context?.agent?.context?.environment, context?.host.context.workspaceRoot);
271
+ let resolver;
272
+ const runtime = createMcpServerRuntime(context?.agent?.context?.environment, context?.host.context.workspaceRoot, () => resolver);
226
273
  const generation = `${context?.agent?.context?.sessionId ?? crypto.randomUUID()}:mcp-server`;
227
274
  const { session } = runtime;
228
275
  const mountSession = (cordis) => {
276
+ cordis.inject([DOOM_MCP_PROJECTION_RESOLVER_SERVICE], (resolverContext) => {
277
+ resolver = resolverContext.get(DOOM_MCP_PROJECTION_RESOLVER_SERVICE);
278
+ return () => {
279
+ resolver = void 0;
280
+ };
281
+ });
229
282
  cordis.inject([DOOM_HEADLESS_HOST_SERVICE], (hostContext) => {
230
283
  return hostContext.get(DOOM_HEADLESS_HOST_SERVICE).subscribeSelection((selection) => runtime.onSelectionChange(selection));
231
284
  });
@@ -1 +1 @@
1
- {"version":3,"file":"server.mjs","names":["routes","apiRoute","rootSession","commandMcp","toolMcpUse"],"sources":["../../src/services/mcpHeadlessTools/index.ts","../../src/services/serverRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/mcpSettingsManager/index.ts","../../src/types/apiRoutes.ts","../../src/services/mcpHubApi/index.ts","../../src/extensions/(backend)/api/mcp/route.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/mcp.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/mcp_use.server.ts","../../generated/server.ts"],"sourcesContent":["import type { DoomHeadlessTool } from '@agimon-ai/doompi-core/headless';\nimport type { DoomMcpPluginContext } from '@agimon-ai/doompi-core/mcpFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nexport const MCP_HEADLESS_TOOLS_SERVICE = 'doom/mcp-headless-tools';\n\nexport interface McpHeadlessToolCatalog {\n get(name: string): DoomHeadlessTool | undefined;\n}\n\nexport function mountMcpHeadlessTools(tools: readonly DoomHeadlessTool[]) {\n return (context: Context): void => {\n context.plugin((providerContext) => {\n providerContext.provide(MCP_HEADLESS_TOOLS_SERVICE, {\n get: (name) => tools.find((tool) => tool.name === name),\n } satisfies McpHeadlessToolCatalog);\n });\n };\n}\n\nexport function bindMcpHeadlessTool(context: DoomMcpPluginContext, name: string): DoomHeadlessTool {\n const tool = context.services.get<McpHeadlessToolCatalog>(MCP_HEADLESS_TOOLS_SERVICE)?.get(name);\n if (!tool) throw new Error(`MCP tool is unavailable: ${name}`);\n return {\n ...tool,\n execute(toolCallId, parameters, signal, onUpdate) {\n const executionSignal = AbortSignal.any([context.signal, signal ?? context.signal]);\n return tool.execute(toolCallId, parameters, executionSignal, onUpdate, context.execution);\n },\n };\n}\n","import path from 'node:path';\n\nimport { loadHarnessState } from '@agimon-ai/doompi-config/harnessStore';\nimport type {\n DoomHeadlessActivity,\n DoomHeadlessCommand,\n DoomHeadlessExecutionContext,\n DoomHeadlessSelection,\n DoomHeadlessTool,\n} from '@agimon-ai/doompi-core/headless';\nimport { isDoomMcpProjection } from '@agimon-ai/doompi-core/mcpProjection';\nimport type { DoomMcpSessionConfig } from '@agimon-ai/doompi-core/mcpSession';\n\nimport { COMMAND_NAME, SERVER_COMMAND_DESCRIPTION } from '../../constants/mcp';\nimport { MCP_STATUS_KEY } from '../../constants/piMcp';\nimport { McpHeadlessToolParameters } from '../../schemas/mcpHeadlessTool';\nimport { formatMcpSessionAuthStatus, MCP_SESSION_AUTH_STATUS_KEY } from '../../types/webMcp';\nimport { formatStatus } from '../mcpCommand';\nimport { McpSession } from '../mcpSession';\nimport { createMcpChildTool } from '../mcpSessionTools';\nimport { mcpSessionConfigFromProjection } from '../projection';\nimport { readSessionConfig } from '../sessionConfig';\n\nfunction sessionConfiguration(execution: DoomHeadlessExecutionContext, workspaceRoot?: string): DoomMcpSessionConfig {\n if (workspaceRoot !== undefined) {\n const loaded = loadHarnessState({ ...execution.environment });\n const projection = loaded.state.mcpProjection;\n if (\n loaded.filePath &&\n loaded.state.root === workspaceRoot &&\n execution.repoRoot === workspaceRoot &&\n loaded.state.mcp &&\n loaded.state.majorMode === execution.selection.majorMode &&\n JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) &&\n JSON.stringify(loaded.state.layers) === JSON.stringify(execution.selection.activeLayers) &&\n isDoomMcpProjection(projection) &&\n projection.repoRoot === workspaceRoot\n )\n return mcpSessionConfigFromProjection(projection, execution.cwd);\n return {\n enabled: false,\n repoRoot: execution.cwd,\n stagingDirectory: path.join(execution.cwd, '.doom', 'mcp-disabled'),\n sources: [],\n };\n }\n return readSessionConfig(execution.environment, execution.cwd);\n}\n\nexport function createMcpServerRuntime(\n environment: Readonly<Record<string, string | undefined>> = {},\n workspaceRoot?: string,\n) {\n let active: DoomHeadlessExecutionContext | undefined;\n let staleSelection = false;\n const authorizing = new Map<string, symbol>();\n const session = new McpSession({\n environment: { ...environment },\n onAuthorizationUrl: async (url, serverName) => {\n await active?.client.notify({\n title: `Authorize MCP server ${serverName}`,\n body: url.toString(),\n level: 'warning',\n });\n },\n });\n\n const activity: DoomHeadlessActivity = {\n name: 'doompi-mcp-runtime',\n async start(execution) {\n active = execution;\n staleSelection = false;\n const reported = new Set<string>();\n const publish = () => {\n execution.client.setStatus(\n MCP_STATUS_KEY,\n session\n .getServers()\n .map((server) => server.name)\n .join(','),\n );\n execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, formatMcpSessionAuthStatus(session.getServers()));\n for (const diagnostic of session.getDiagnostics()) {\n if (reported.has(diagnostic)) continue;\n reported.add(diagnostic);\n void execution.client.notify({ title: 'DoomPi MCP', body: diagnostic, level: 'warning' });\n }\n };\n const stopPublishing = session.onChange(publish);\n try {\n await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);\n publish();\n } catch (error) {\n await execution.client.notify({\n title: 'DoomPi MCP unavailable',\n body: error instanceof Error ? error.message : String(error),\n level: 'warning',\n });\n }\n return async () => {\n stopPublishing();\n if (active !== execution) return;\n active = undefined;\n staleSelection = false;\n authorizing.clear();\n try {\n await session.dispose();\n } finally {\n // Withdraw tools and UI state even when a connection fails to close.\n session.install({ enabled: false, repoRoot: execution.cwd, stagingDirectory: execution.cwd });\n execution.client.setStatus(MCP_STATUS_KEY, undefined);\n execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, undefined);\n }\n };\n },\n };\n\n const invoke: Parameters<typeof createMcpChildTool>[0] = async (parameters, signal) => {\n if (!active) throw new Error('The MCP runtime has not started yet.');\n if (staleSelection) throw new Error('The MCP projection is stale for the current selection.');\n const selected = session\n .activeToolDefinitions()\n .find((candidate) => candidate.serverName === parameters.server && candidate.toolName === parameters.tool);\n if (!selected)\n throw new Error(`MCP tool ${parameters.server}/${parameters.tool} is not available in this session.`);\n return session.invokeTool(selected.piName, parameters.arguments ?? {}, signal);\n };\n const childTool = createMcpChildTool(invoke);\n\n // web-plugin-tool-renderers: ignore mcp_use, headless-only generic MCP dispatch\n const tool: DoomHeadlessTool<typeof McpHeadlessToolParameters> = {\n name: 'mcp_use',\n label: 'MCP use',\n description: 'Call a tool exposed by a connected MCP server.',\n parameters: McpHeadlessToolParameters,\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n try {\n return await invoke(parameters, signal);\n } catch (error) {\n return {\n content: [{ type: 'text', text: error instanceof Error ? error.message : String(error) }],\n isError: true,\n };\n }\n },\n };\n\n const command: DoomHeadlessCommand = {\n name: COMMAND_NAME,\n description: SERVER_COMMAND_DESCRIPTION,\n async execute(args, execution) {\n const [subcommand = 'status', ...rest] = args.trim().split(/\\s+/u).filter(Boolean);\n const serverName = rest.join(' ');\n const notify = (body: string, level: 'info' | 'warning' = 'info') =>\n execution.client.notify({ title: 'DoomPi MCP', body, level });\n try {\n if (subcommand === 'status') {\n await notify(formatStatus(session));\n return;\n }\n if (!active) throw new Error('The MCP runtime has not started yet.');\n if (staleSelection) throw new Error('The MCP projection is stale for the current selection.');\n if (subcommand === 'auth' || subcommand === 'disconnect') {\n if (!serverName) throw new Error(`Name the server, for example /mcp ${subcommand} <server>.`);\n const server = session.getServers().find((candidate) => candidate.name === serverName);\n if (!server) throw new Error(`Unknown MCP server: ${serverName}`);\n if (subcommand === 'disconnect') {\n await session.disconnect(serverName);\n authorizing.delete(serverName);\n await notify(`${serverName} is disconnected from this session. Saved credentials were kept.`);\n return;\n }\n if (server.authorizationUrl) {\n await session.openAuthorizationPage(serverName);\n return;\n }\n if (authorizing.has(serverName)) return;\n const request = Symbol(serverName);\n authorizing.set(serverName, request);\n const owner = active;\n // OAuth waits for the browser. Do not hold the session command queue while it does.\n void session.reauthorize(serverName).then(\n async () => {\n if (active !== owner || authorizing.get(serverName) !== request) return;\n authorizing.delete(serverName);\n await notify(`${serverName} is authorized.`);\n },\n async (error: unknown) => {\n if (active !== owner || authorizing.get(serverName) !== request) return;\n authorizing.delete(serverName);\n await notify(\n `Could not authorize ${serverName}: ${error instanceof Error ? error.message : String(error)}`,\n 'warning',\n );\n },\n );\n return;\n }\n if (subcommand === 'reload') {\n authorizing.clear();\n try {\n await session.dispose();\n } finally {\n // Reset the catalog even when paths are unchanged or teardown fails.\n session.install({ enabled: false, repoRoot: execution.cwd, stagingDirectory: execution.cwd });\n }\n await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);\n await notify('Reconnecting MCP servers.');\n return;\n }\n throw new Error(`Unknown /${COMMAND_NAME} subcommand \"${subcommand}\". Use status, auth, disconnect, reload.`);\n } catch (error) {\n await notify(error instanceof Error ? error.message : String(error), 'warning');\n }\n },\n };\n return {\n session,\n activities: [activity],\n commands: [command],\n tools: [tool],\n childTool,\n async onSelectionChange(selection: DoomHeadlessSelection) {\n if (!active || workspaceRoot === undefined) return;\n const initial = active.selection;\n if (!initial || JSON.stringify(initial.domains) === JSON.stringify(selection.domains)) return;\n staleSelection = true;\n authorizing.clear();\n await session.reconfigure({\n enabled: false,\n repoRoot: active.cwd,\n stagingDirectory: path.join(active.cwd, '.doom', 'mcp-disabled'),\n sources: [],\n });\n },\n };\n}\n","import { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE } from '@agimon-ai/doompi-core/childSession';\nimport { DOOM_HEADLESS_HOST_SERVICE, type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { DOOM_MCP_STATUS_SERVICE, type DoomMcpStatusService } from '@agimon-ai/doompi-core/mcpStatus';\nimport {\n DOOM_MCP_TOOL_RESOLVER_SERVICE,\n type DoomMcpToolResolverService,\n} from '@agimon-ai/doompi-core/mcpToolResolver';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { mountMcpHeadlessTools } from '../../../../../services/mcpHeadlessTools';\nimport { createMcpSessionToolsService, MCP_SESSION_TOOLS_SERVICE } from '../../../../../services/mcpSessionTools';\nimport { createMcpServerRuntime } from '../../../../../services/serverRuntime';\n\nexport const createMcpServerRoot = (context?: DoomServerPluginContext) => {\n const runtime = createMcpServerRuntime(context?.agent?.context?.environment, context?.host.context.workspaceRoot);\n const generation = `${context?.agent?.context?.sessionId ?? crypto.randomUUID()}:mcp-server`;\n const { session } = runtime;\n const mountSession = (cordis: Context) => {\n cordis.inject([DOOM_HEADLESS_HOST_SERVICE], (hostContext) => {\n const host = hostContext.get(DOOM_HEADLESS_HOST_SERVICE) as DoomHeadlessHostService;\n return host.subscribeSelection((selection) => runtime.onSelectionChange(selection));\n });\n cordis.plugin((provider) => {\n provider.provide(DOOM_MCP_STATUS_SERVICE, {\n generation,\n getSnapshot: () => session.getSnapshot(),\n onChange: (listener) => session.onChange(listener),\n } satisfies DoomMcpStatusService);\n provider.provide(DOOM_MCP_TOOL_RESOLVER_SERVICE, {\n generation,\n resolve: (selectors) => session.resolveToolSelectors(selectors),\n } satisfies DoomMcpToolResolverService);\n provider.provide(MCP_SESSION_TOOLS_SERVICE, createMcpSessionToolsService(session, generation));\n provider.provide(DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, runtime.childTool);\n });\n };\n return {\n value: runtime,\n activities: runtime.activities,\n services: [mountMcpHeadlessTools(runtime.tools), mountSession],\n };\n};\nexport type McpServerScope = Awaited<ReturnType<typeof createMcpServerRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createMcpServerRoot } from './_lib/serverRoot';\n\nexport default defineRoot(createMcpServerRoot);\n","import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport type { DoomOAuthRedirect, DoomRepositorySyncView } from '@agimon-ai/doompi-core/packageApi';\nimport type { McpServerStateChange, McpToolInfo, TokenStore } from '@agimon-ai/mcp-proxy';\n\nimport type { McpConfigGroups, McpConfigSource, McpSessionConfig } from '../../types/mcpConfig';\nimport type {\n McpAuthorizationFlow,\n McpRepositoryCatalog,\n McpRepositoryServer,\n McpRepositoryServerState,\n McpRepositoryTool,\n} from '../../types/webMcp';\nimport { buildMcpConfigGroups } from '../configSources';\nimport { createTokenStore } from '../keyringTokenStore';\nimport { toPiToolName } from '../mcpCatalog';\nimport { hubCallbackSink, McpRuntimeOwner, readCachedCatalog } from '../mcpRuntime';\nimport { mcpSessionConfigFromProjection } from '../projection';\n\nconst DISCOVERY_TIMEOUT_MS = 30_000;\nconst AUTHORIZATION_TIMEOUT_MS = 5 * 60_000;\nconst TERMINAL_FLOW_RETENTION_MS = 5 * 60_000;\nconst EMPTY_SYNC = { fresh: false, reasons: ['never-synced'] } as const;\n\ninterface PreparedMcpRepository {\n catalog: McpRepositoryCatalog;\n configSources: McpConfigSource[];\n groups: McpConfigGroups;\n stagingDirectory?: string;\n}\n\ninterface InternalAuthorizationFlow extends McpAuthorizationFlow {\n owner?: McpRuntimeOwner;\n stagingDirectory?: string;\n timeout?: ReturnType<typeof setTimeout>;\n retainedUntil?: number;\n}\n\nexport interface McpSettingsManagerOptions {\n discoveryTimeoutMs?: number;\n authorizationTimeoutMs?: number;\n tokenStore?: TokenStore;\n}\n\nfunction configuredServerNames(groups: McpConfigGroups): string[] {\n return [...new Set([...groups.sessionLocal.serverNames, ...groups.shared.serverNames])].sort((left, right) =>\n left.localeCompare(right),\n );\n}\n\nfunction configSources(groups: McpConfigGroups): McpConfigSource[] {\n return [...groups.sessionLocal.configSources, ...groups.shared.configSources];\n}\n\nfunction toolView(serverName: string, tool: McpToolInfo): McpRepositoryTool {\n return {\n name: tool.name,\n piName: toPiToolName(serverName, tool.name),\n ...(tool.description ? { description: tool.description } : {}),\n };\n}\n\nfunction sanitizeDiagnostic(message: string, repositoryRoot: string, stagingDirectory: string | undefined): string {\n let safe = message;\n for (const value of [stagingDirectory, repositoryRoot, os.homedir()]) {\n if (value) safe = safe.split(value).join(value === os.homedir() ? '~' : '<repository>');\n }\n return safe.replace(/[A-Za-z]:\\\\[^\\s,;)'\"`]+/gu, '<path>').replace(/(^|\\s)\\/(?!\\/)[^\\s,;)'\"`]+/gu, '$1<path>');\n}\n\nfunction publicFlow(flow: InternalAuthorizationFlow): McpAuthorizationFlow {\n return {\n id: flow.id,\n repositoryId: flow.repositoryId,\n serverName: flow.serverName,\n status: flow.status,\n ...(flow.authorizationUrl ? { authorizationUrl: flow.authorizationUrl } : {}),\n ...(flow.error ? { error: flow.error } : {}),\n expiresAt: flow.expiresAt,\n };\n}\n\nfunction isTerminal(status: McpAuthorizationFlow['status']): boolean {\n return status === 'completed' || status === 'failed' || status === 'cancelled' || status === 'expired';\n}\n\nfunction safeAuthorizationUrl(url: URL): string | undefined {\n if ((url.protocol !== 'https:' && url.protocol !== 'http:') || url.toString().length > 4096) return undefined;\n return url.toString();\n}\n\nexport class McpSettingsManager {\n private readonly discoveryTimeoutMs: number;\n private readonly authorizationTimeoutMs: number;\n private readonly injectedTokenStore?: TokenStore;\n private readonly busyRepositories = new Set<string>();\n private readonly flows = new Map<string, InternalAuthorizationFlow>();\n\n constructor(options: McpSettingsManagerOptions = {}) {\n this.discoveryTimeoutMs = options.discoveryTimeoutMs ?? DISCOVERY_TIMEOUT_MS;\n this.authorizationTimeoutMs = options.authorizationTimeoutMs ?? AUTHORIZATION_TIMEOUT_MS;\n this.injectedTokenStore = options.tokenStore;\n }\n\n private async tokenStore(): Promise<TokenStore> {\n return this.injectedTokenStore ?? (await createTokenStore());\n }\n\n private async credentialPresence(serverNames: readonly string[]): Promise<Map<string, boolean>> {\n const presence = new Map<string, boolean>();\n try {\n const tokenStore = await this.tokenStore();\n await Promise.all(\n serverNames.map(async (serverName) => {\n try {\n presence.set(serverName, (await tokenStore.read(serverName)) !== undefined);\n } catch {\n presence.set(serverName, false);\n }\n }),\n );\n } catch {\n for (const serverName of serverNames) presence.set(serverName, false);\n }\n return presence;\n }\n\n private prepare(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n onlyServer?: string,\n ): PreparedMcpRepository {\n if (!sync?.mcpProjection) {\n const readiness = sync ?? EMPTY_SYNC;\n return {\n catalog: {\n repositoryId,\n sync: { fresh: readiness.fresh, reasons: [...readiness.reasons] },\n servers: [],\n droppedServers: [],\n diagnostics: [],\n },\n configSources: [],\n groups: {\n shared: { configSources: [], configPaths: [], serverNames: [] },\n sessionLocal: { configSources: [], configPaths: [], serverNames: [] },\n droppedServers: [],\n diagnostics: [],\n },\n };\n }\n\n const stagingDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'doompi-mcp-settings-'));\n fs.chmodSync(stagingDirectory, 0o700);\n try {\n const projected = mcpSessionConfigFromProjection(sync.mcpProjection);\n const configuration: McpSessionConfig = {\n ...projected,\n repoRoot: repositoryRoot,\n stagingDirectory,\n ...(onlyServer ? { allowlist: { servers: [onlyServer], proxy: [] } } : {}),\n };\n const groups = buildMcpConfigGroups(configuration);\n const sources = configSources(groups);\n const names = configuredServerNames(groups);\n const cachedByServer = new Map(readCachedCatalog(sources).servers.map((server) => [server.name, server.tools]));\n const servers: McpRepositoryServer[] = names.map((name) => {\n const tools = cachedByServer.get(name) ?? [];\n return {\n name,\n state: 'not-connected',\n source: tools.length === 0 ? 'configured' : 'cached',\n credentialPresent: false,\n tools: tools.map((tool) => toolView(name, tool)),\n };\n });\n return {\n catalog: {\n repositoryId,\n sync: { fresh: sync.fresh, reasons: [...sync.reasons] },\n servers,\n droppedServers: [...groups.droppedServers],\n diagnostics: groups.diagnostics.map((diagnostic) =>\n sanitizeDiagnostic(diagnostic, repositoryRoot, stagingDirectory),\n ),\n },\n configSources: sources,\n groups,\n stagingDirectory,\n };\n } catch (error) {\n fs.rmSync(stagingDirectory, { recursive: true, force: true });\n throw error;\n }\n }\n\n private cleanupPrepared(prepared: PreparedMcpRepository): void {\n if (prepared.stagingDirectory) fs.rmSync(prepared.stagingDirectory, { recursive: true, force: true });\n }\n\n async readCatalog(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n ): Promise<McpRepositoryCatalog> {\n const prepared = this.prepare(repositoryId, repositoryRoot, sync);\n try {\n const presence = await this.credentialPresence(prepared.catalog.servers.map((server) => server.name));\n return {\n ...prepared.catalog,\n servers: prepared.catalog.servers.map((server) => ({\n ...server,\n credentialPresent: presence.get(server.name) ?? false,\n })),\n };\n } finally {\n this.cleanupPrepared(prepared);\n }\n }\n\n async discover(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n ): Promise<McpRepositoryCatalog> {\n if (this.busyRepositories.has(repositoryId))\n throw new Error('MCP management is already active for this repository.');\n const prepared = this.prepare(repositoryId, repositoryRoot, sync);\n if (!prepared.catalog.sync.fresh) {\n this.cleanupPrepared(prepared);\n throw new Error('Sync this repository before discovering MCP capabilities.');\n }\n if (prepared.configSources.length === 0) {\n this.cleanupPrepared(prepared);\n return prepared.catalog;\n }\n\n this.busyRepositories.add(repositoryId);\n const owner = new McpRuntimeOwner();\n const liveStates = new Map<string, McpServerStateChange>();\n try {\n const handle = await owner.start({\n configSources: prepared.configSources,\n workspaceRoot: repositoryRoot,\n executionCwd: repositoryRoot,\n tokenStore: await this.tokenStore(),\n onAuthorizationUrl: (_url, serverName) => {\n liveStates.set(serverName, { serverName, state: 'needs-auth' });\n },\n onServerStateChange: (change) => liveStates.set(change.serverName, change),\n });\n if (handle) {\n await Promise.race([\n handle.connectionsSettled,\n new Promise<void>((resolve) => setTimeout(resolve, this.discoveryTimeoutMs)),\n ]);\n }\n const manager = handle?.services.clientManager;\n const cachedByServer = new Map(\n readCachedCatalog(prepared.configSources).servers.map((server) => [server.name, server.tools]),\n );\n const presence = await this.credentialPresence(prepared.catalog.servers.map((server) => server.name));\n const servers = await Promise.all(\n prepared.catalog.servers.map(async (server): Promise<McpRepositoryServer> => {\n const change = liveStates.get(server.name);\n const state = (change?.state ??\n manager?.getServerState(server.name) ??\n server.state) as McpRepositoryServerState;\n let tools = cachedByServer.get(server.name) ?? [];\n let source: McpRepositoryServer['source'] = tools.length === 0 ? 'configured' : 'cached';\n if (state === 'connected' && manager) {\n try {\n tools = await manager\n .ensureConnected(server.name)\n .then(async (connection) => await connection.listTools());\n source = 'live';\n } catch {\n // Preserve the cache when a server moved between state inspection and listing.\n }\n }\n return {\n name: server.name,\n state,\n source,\n credentialPresent: presence.get(server.name) ?? false,\n tools: tools.map((tool) => toolView(server.name, tool)),\n ...(change?.error ? { error: 'The server reported a connection error.' } : {}),\n };\n }),\n );\n return { ...prepared.catalog, servers };\n } finally {\n await owner.dispose();\n this.cleanupPrepared(prepared);\n this.busyRepositories.delete(repositoryId);\n }\n }\n\n async authorize(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n serverName: string,\n /**\n * The hub's redirect surface. Present, the authorization server sends the\n * browser back to the hub, which is reachable whether the operator is at\n * this machine or on a tunnel. Absent, the proxy keeps its loopback\n * listener and behaviour is unchanged.\n */\n redirect?: DoomOAuthRedirect,\n ): Promise<McpAuthorizationFlow> {\n this.sweepFlows();\n if (this.busyRepositories.has(repositoryId))\n throw new Error('MCP management is already active for this repository.');\n\n const full = this.prepare(repositoryId, repositoryRoot, sync);\n const configured = full.catalog.servers.some((server) => server.name === serverName);\n const fresh = full.catalog.sync.fresh;\n this.cleanupPrepared(full);\n if (!fresh) throw new Error('Sync this repository before authorizing an MCP server.');\n if (!configured) throw new Error('That MCP server is not enabled for this repository.');\n\n const prepared = this.prepare(repositoryId, repositoryRoot, sync, serverName);\n const flow: InternalAuthorizationFlow = {\n id: randomUUID(),\n repositoryId,\n serverName,\n status: 'starting',\n expiresAt: Date.now() + this.authorizationTimeoutMs,\n stagingDirectory: prepared.stagingDirectory,\n };\n this.flows.set(flow.id, flow);\n this.busyRepositories.add(repositoryId);\n void this.runAuthorization(flow, prepared.configSources, repositoryRoot, redirect);\n return publicFlow(flow);\n }\n\n getAuthorization(flowId: string, repositoryId: string): McpAuthorizationFlow | undefined {\n this.sweepFlows();\n const flow = this.flows.get(flowId);\n return flow?.repositoryId === repositoryId ? publicFlow(flow) : undefined;\n }\n\n async cancelAuthorization(flowId: string, repositoryId: string): Promise<McpAuthorizationFlow | undefined> {\n const flow = this.flows.get(flowId);\n if (!flow || flow.repositoryId !== repositoryId) return undefined;\n if (!isTerminal(flow.status)) {\n flow.status = 'cancelled';\n await this.finishFlow(flow);\n }\n return publicFlow(flow);\n }\n\n private async runAuthorization(\n flow: InternalAuthorizationFlow,\n sources: McpConfigSource[],\n repositoryRoot: string,\n redirect?: DoomOAuthRedirect,\n ): Promise<void> {\n const owner = new McpRuntimeOwner();\n flow.owner = owner;\n flow.timeout = setTimeout(() => {\n if (isTerminal(flow.status)) return;\n flow.status = 'expired';\n flow.error = 'Authorization timed out.';\n void this.finishFlow(flow);\n }, this.authorizationTimeoutMs);\n\n try {\n const handle = await owner.start({\n configSources: sources,\n workspaceRoot: repositoryRoot,\n executionCwd: repositoryRoot,\n tokenStore: await this.tokenStore(),\n ...(redirect ? { callbackServer: hubCallbackSink(redirect) } : {}),\n onAuthorizationUrl: (url, serverName) => {\n if (serverName !== flow.serverName || isTerminal(flow.status)) return;\n const safeUrl = safeAuthorizationUrl(url);\n if (!safeUrl) {\n flow.status = 'failed';\n flow.error = 'The server returned an invalid authorization URL.';\n void this.finishFlow(flow);\n return;\n }\n flow.authorizationUrl = safeUrl;\n flow.status = 'waiting';\n },\n onServerStateChange: (change) => this.applyAuthorizationState(flow, change),\n });\n if (!handle || isTerminal(flow.status)) return;\n const manager = handle.services.clientManager;\n await manager.disconnectServer(flow.serverName);\n await manager.ensureConnected(flow.serverName);\n if (!isTerminal(flow.status)) flow.status = 'completed';\n } catch {\n if (!isTerminal(flow.status)) {\n flow.status = 'failed';\n flow.error = 'The MCP server could not complete authorization.';\n }\n } finally {\n if (!isTerminal(flow.status)) flow.status = 'completed';\n await this.finishFlow(flow);\n }\n }\n\n private applyAuthorizationState(flow: InternalAuthorizationFlow, change: McpServerStateChange): void {\n if (change.serverName !== flow.serverName || isTerminal(flow.status)) return;\n if (change.state === 'connected') flow.status = 'completed';\n else if (change.state === 'needs-auth' && flow.status === 'starting') flow.status = 'waiting';\n else if (change.state === 'failed') {\n flow.status = 'failed';\n flow.error = 'The MCP server rejected the authorization attempt.';\n }\n }\n\n private async finishFlow(flow: InternalAuthorizationFlow): Promise<void> {\n if (flow.timeout) clearTimeout(flow.timeout);\n flow.timeout = undefined;\n const owner = flow.owner;\n flow.owner = undefined;\n await owner?.dispose();\n if (flow.stagingDirectory) fs.rmSync(flow.stagingDirectory, { recursive: true, force: true });\n flow.stagingDirectory = undefined;\n this.busyRepositories.delete(flow.repositoryId);\n flow.retainedUntil = Date.now() + TERMINAL_FLOW_RETENTION_MS;\n }\n\n private sweepFlows(): void {\n const now = Date.now();\n for (const [id, flow] of this.flows) {\n if (flow.retainedUntil !== undefined && flow.retainedUntil <= now) this.flows.delete(id);\n }\n }\n\n async dispose(): Promise<void> {\n await Promise.all(\n [...this.flows.values()].map(async (flow) => {\n if (!isTerminal(flow.status)) flow.status = 'cancelled';\n await this.finishFlow(flow);\n }),\n );\n this.flows.clear();\n this.busyRepositories.clear();\n }\n}\n","import { apiResponse, defineApiRoutes } from '@agimon-ai/doompi-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 type McpAuthorizationFlow,\n type McpRepositoryCatalog,\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});\n","import type { DoomApi, DoomApiContext } from '@agimon-ai/doompi-core/packageApi';\n\nimport { McpSettingsManager } from '../../services/mcpSettingsManager';\nimport routes from '../../types/apiRoutes';\nimport { MCP_FLOW_ID_PARAM, MCP_REPOSITORY_ID_QUERY } from '../../types/webMcp';\n\n/**\n * What sits above a flow id, read off the flow route itself.\n *\n * This handler matches paths by hand rather than through a router, so the one\n * route carrying a parameter is split here: everything before `:flowId` is the\n * prefix a request must start with, and what follows it is the id.\n */\nconst AUTHORIZATION_FLOW_PREFIX = routes.readAuthorization.path.replace(`:${MCP_FLOW_ID_PARAM}`, '');\n\nconst JSON_HEADERS = { 'content-type': 'application/json' };\nconst REPOSITORY_ID = /^(?:[a-f0-9]{32}|repo-[A-Za-z0-9_-]{24})$/u;\nconst FLOW_ID = /^[a-f0-9-]{36}$/u;\nconst MAX_BODY_BYTES = 8 * 1024;\nconst MAX_SERVER_NAME = 160;\nconst manager = new McpSettingsManager();\n\ntype JsonRecord = Record<string, unknown>;\n\nfunction json(body: unknown, status = 200): Response {\n return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS });\n}\n\nfunction isRecord(value: unknown): value is JsonRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nasync function bodyOf(request: Request): Promise<JsonRecord | undefined> {\n const text = await request.text();\n if (text.length > MAX_BODY_BYTES) return undefined;\n try {\n const parsed = JSON.parse(text) as unknown;\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction repositoryIdOf(value: unknown): string | undefined {\n return typeof value === 'string' && REPOSITORY_ID.test(value) ? value : undefined;\n}\n\nfunction serverNameOf(value: unknown): string | undefined {\n return typeof value === 'string' &&\n value.length > 0 &&\n value.length <= MAX_SERVER_NAME &&\n !Array.from(value).some((character) => character.charCodeAt(0) <= 0x1f)\n ? value\n : undefined;\n}\n\nfunction resolveRepository(context: DoomApiContext, repositoryId: string): string | undefined {\n return context.resolveRepository?.(repositoryId);\n}\n\nfunction errorStatus(error: unknown): { status: number; message: string } {\n const message = error instanceof Error ? error.message : '';\n if (message.includes('already active')) return { status: 409, message };\n if (message.startsWith('Sync this repository')) return { status: 409, message };\n if (message.includes('not enabled')) return { status: 404, message };\n return { status: 500, message: 'MCP management could not complete that request.' };\n}\n\nasync function handleCatalog(request: Request, context: DoomApiContext): Promise<Response> {\n const repositoryId = repositoryIdOf(new URL(request.url).searchParams.get(MCP_REPOSITORY_ID_QUERY));\n if (!repositoryId) return json({ error: 'A valid repositoryId is required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(await manager.readCatalog(repositoryId, repositoryRoot, context.readRepositorySync?.(repositoryId)));\n } catch {\n return json({ error: 'The synced MCP catalog could not be read.' }, 500);\n }\n}\n\nasync function handleDiscovery(request: Request, context: DoomApiContext): Promise<Response> {\n const body = await bodyOf(request);\n const repositoryId = repositoryIdOf(body?.repositoryId);\n if (!repositoryId) return json({ error: 'A valid repositoryId is required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(await manager.discover(repositoryId, repositoryRoot, context.readRepositorySync?.(repositoryId)));\n } catch (error) {\n const failure = errorStatus(error);\n return json({ error: failure.message }, failure.status);\n }\n}\n\nasync function handleAuthorize(request: Request, context: DoomApiContext): Promise<Response> {\n const body = await bodyOf(request);\n const repositoryId = repositoryIdOf(body?.repositoryId);\n const serverName = serverNameOf(body?.serverName);\n if (!repositoryId || !serverName) return json({ error: 'A valid repositoryId and serverName are required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(\n await manager.authorize(\n repositoryId,\n repositoryRoot,\n context.readRepositorySync?.(repositoryId),\n serverName,\n context.oauthRedirect?.(),\n ),\n 202,\n );\n } catch (error) {\n const failure = errorStatus(error);\n return json({ error: failure.message }, failure.status);\n }\n}\n\nasync function handleAuthorizationFlow(request: Request, context: DoomApiContext, path: string): Promise<Response> {\n const flowId = path.slice(AUTHORIZATION_FLOW_PREFIX.length);\n const repositoryId = repositoryIdOf(new URL(request.url).searchParams.get(MCP_REPOSITORY_ID_QUERY));\n if (!repositoryId || !FLOW_ID.test(flowId))\n return json({ error: 'A valid repositoryId and flow id are required.' }, 400);\n if (!resolveRepository(context, repositoryId)) {\n return json({ error: 'That repository is not available to this hub.' }, 404);\n }\n if (request.method === routes.cancelAuthorization.method) {\n const flow = await manager.cancelAuthorization(flowId, repositoryId);\n return flow ? json(flow) : json({ error: 'That authorization flow was not found.' }, 404);\n }\n const flow = manager.getAuthorization(flowId, repositoryId);\n return flow ? json(flow) : json({ error: 'That authorization flow was not found.' }, 404);\n}\n\nexport const mcpHubApi: DoomApi = {\n basePath: 'mcp',\n start(context) {\n return {\n async fetch(request) {\n const path = new URL(request.url).pathname;\n if (request.method === routes.catalog.method && path === routes.catalog.path) {\n return await handleCatalog(request, context);\n }\n if (request.method === routes.discover.method && path === routes.discover.path) {\n return await handleDiscovery(request, context);\n }\n if (request.method === routes.authorize.method && path === routes.authorize.path) {\n return await handleAuthorize(request, context);\n }\n if (\n (request.method === routes.readAuthorization.method ||\n request.method === routes.cancelAuthorization.method) &&\n path.startsWith(AUTHORIZATION_FLOW_PREFIX)\n ) {\n return await handleAuthorizationFlow(request, context, path);\n }\n return json({ error: 'Not found.' }, 404);\n },\n close() {\n void manager.dispose();\n },\n };\n },\n};\n","import { defineRoute } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { mcpHubApi } from '../../../../services/mcpHubApi';\n\n/**\n * Mounts this package's HTTP API at `mcp`, which the folder names.\n *\n * The folder is the declaration: the build reads the base path off it and hands\n * the browser a client bound to the same segment, so the settings panel can no\n * longer spell a workspace mount by hand.\n */\nexport default defineRoute(mcpHubApi);\n","import { defineServerCommand, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { McpServerScope } from '../_lib/serverRoot';\nexport default defineServerCommand(\n (context: WithRoot<DoomServerPluginContext, McpServerScope>) => context.root.commands[0]!,\n);\n","import { defineServerTool, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { McpServerScope } from '../_lib/serverRoot';\nexport default defineServerTool((context: WithRoot<DoomServerPluginContext, McpServerScope>) => context.root.tools[0]!);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport apiRoute from '../src/extensions/(backend)/api/mcp/route.server';\nimport commandMcp from '../src/extensions/workspaces/sessions/(backend)/command/mcp.server';\nimport toolMcpUse from '../src/extensions/workspaces/sessions/(backend)/tool/mcp_use.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-mcp',\n global: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n workspace: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n get commands(): DoomServerSessionPlugin['commands'] { return [via({ name: 'mcp' }, at(commandMcp, contextSession))]; },\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'mcp_use' }, at(toolMcpUse, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.mjs","names":["routes","apiRoute","rootSession","commandMcp","toolMcpUse"],"sources":["../../src/services/mcpHeadlessTools/index.ts","../../src/services/serverRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/mcpSettingsManager/index.ts","../../src/types/apiRoutes.ts","../../src/services/mcpHubApi/index.ts","../../src/extensions/(backend)/api/mcp/route.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/mcp.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/mcp_use.server.ts","../../generated/server.ts"],"sourcesContent":["import type { DoomHeadlessTool } from '@agimon-ai/doompi-core/headless';\nimport type { DoomMcpPluginContext } from '@agimon-ai/doompi-core/mcpFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nexport const MCP_HEADLESS_TOOLS_SERVICE = 'doom/mcp-headless-tools';\n\nexport interface McpHeadlessToolCatalog {\n get(name: string): DoomHeadlessTool | undefined;\n}\n\nexport function mountMcpHeadlessTools(tools: readonly DoomHeadlessTool[]) {\n return (context: Context): void => {\n context.plugin((providerContext) => {\n providerContext.provide(MCP_HEADLESS_TOOLS_SERVICE, {\n get: (name) => tools.find((tool) => tool.name === name),\n } satisfies McpHeadlessToolCatalog);\n });\n };\n}\n\nexport function bindMcpHeadlessTool(context: DoomMcpPluginContext, name: string): DoomHeadlessTool {\n const tool = context.services.get<McpHeadlessToolCatalog>(MCP_HEADLESS_TOOLS_SERVICE)?.get(name);\n if (!tool) throw new Error(`MCP tool is unavailable: ${name}`);\n return {\n ...tool,\n execute(toolCallId, parameters, signal, onUpdate) {\n const executionSignal = AbortSignal.any([context.signal, signal ?? context.signal]);\n return tool.execute(toolCallId, parameters, executionSignal, onUpdate, context.execution);\n },\n };\n}\n","import path from 'node:path';\n\nimport { loadHarnessState } from '@agimon-ai/doompi-config/harnessStore';\nimport type {\n DoomHeadlessActivity,\n DoomHeadlessCommand,\n DoomHeadlessExecutionContext,\n DoomHeadlessSelection,\n DoomHeadlessTool,\n} from '@agimon-ai/doompi-core/headless';\nimport { isDoomMcpProjection, type DoomMcpProjectionResolverService } from '@agimon-ai/doompi-core/mcpProjection';\nimport type { DoomMcpSessionConfig } from '@agimon-ai/doompi-core/mcpSession';\n\nimport { COMMAND_NAME, SERVER_COMMAND_DESCRIPTION } from '../../constants/mcp';\nimport { MCP_STATUS_KEY } from '../../constants/piMcp';\nimport { McpHeadlessToolParameters } from '../../schemas/mcpHeadlessTool';\nimport { formatMcpSessionAuthStatus, MCP_SESSION_AUTH_STATUS_KEY } from '../../types/webMcp';\nimport { formatStatus } from '../mcpCommand';\nimport { McpSession } from '../mcpSession';\nimport { createMcpChildTool } from '../mcpSessionTools';\nimport { mcpSessionConfigFromProjection } from '../projection';\nimport { readSessionConfig } from '../sessionConfig';\n\nfunction sessionConfiguration(execution: DoomHeadlessExecutionContext, workspaceRoot?: string): DoomMcpSessionConfig {\n if (workspaceRoot !== undefined) {\n const loaded = loadHarnessState({ ...execution.environment });\n const projection = loaded.state.mcpProjection;\n if (\n loaded.filePath &&\n loaded.state.root === workspaceRoot &&\n execution.repoRoot === workspaceRoot &&\n loaded.state.mcp &&\n loaded.state.majorMode === execution.selection.majorMode &&\n JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) &&\n JSON.stringify(loaded.state.layers) === JSON.stringify(execution.selection.activeLayers) &&\n isDoomMcpProjection(projection) &&\n projection.repoRoot === workspaceRoot\n )\n return mcpSessionConfigFromProjection(projection, execution.cwd);\n return {\n enabled: false,\n repoRoot: execution.cwd,\n stagingDirectory: path.join(execution.cwd, '.doom', 'mcp-disabled'),\n sources: [],\n };\n }\n return readSessionConfig(execution.environment, execution.cwd);\n}\n\nexport function createMcpServerRuntime(\n environment: Readonly<Record<string, string | undefined>> = {},\n workspaceRoot?: string,\n getResolver?: () => DoomMcpProjectionResolverService | undefined,\n) {\n let active: DoomHeadlessExecutionContext | undefined;\n let currentSelection: DoomHeadlessSelection | undefined;\n let staleSelection = false;\n let cleanup: (() => Promise<void>) | undefined;\n let transition = Promise.resolve();\n const authorizing = new Map<string, symbol>();\n const session = new McpSession({\n environment: { ...environment },\n onAuthorizationUrl: async (url, serverName) => {\n if (staleSelection || !session.getServers().some((server) => server.name === serverName)) return;\n await active?.client.notify({\n title: `Authorize MCP server ${serverName}`,\n body: url.toString(),\n level: 'warning',\n });\n },\n });\n\n const refresh = (execution: DoomHeadlessExecutionContext, selection: DoomHeadlessSelection) => {\n staleSelection = true;\n authorizing.clear();\n transition = transition\n .catch(() => {})\n .then(async () => {\n if (active !== execution) return;\n const previousCleanup = cleanup;\n cleanup = undefined;\n try {\n await session.dispose();\n } finally {\n session.install({ enabled: false, repoRoot: execution.cwd, stagingDirectory: execution.cwd });\n await previousCleanup?.();\n }\n if (active !== execution) return;\n const resolver = getResolver?.();\n const loaded = workspaceRoot ? loadHarnessState({ ...execution.environment }) : undefined;\n const authorized =\n workspaceRoot &&\n loaded?.filePath &&\n loaded.state.root === workspaceRoot &&\n execution.repoRoot === workspaceRoot &&\n loaded.state.mcp &&\n loaded.state.majorMode === selection.majorMode &&\n JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) &&\n JSON.stringify(loaded.state.layers) === JSON.stringify(selection.activeLayers) &&\n isDoomMcpProjection(loaded.state.mcpProjection) &&\n loaded.state.mcpProjection.repoRoot === workspaceRoot &&\n loaded.state.mcpProjection.enabled;\n if (!resolver || !authorized) {\n // A missing or disabled saved projection never grants implicit repository access.\n if (active === execution && selection === currentSelection) {\n if (\n workspaceRoot === undefined ||\n JSON.stringify(execution.selection.domains) === JSON.stringify(selection.domains)\n ) {\n await session.reconfigure(\n sessionConfiguration(execution, workspaceRoot),\n execution.cwd,\n execution.repoRoot,\n );\n }\n staleSelection =\n workspaceRoot !== undefined &&\n JSON.stringify(execution.selection.domains) !== JSON.stringify(selection.domains);\n }\n return;\n }\n const candidate = await resolver.resolve(selection.domains);\n if (active !== execution || selection !== currentSelection) {\n await candidate.cleanup();\n return;\n }\n try {\n if (\n !isDoomMcpProjection(candidate.projection) ||\n candidate.projection.repoRoot !== workspaceRoot ||\n !candidate.projection.enabled\n ) {\n throw new Error('The selected domains returned an invalid MCP projection.');\n }\n await session.reconfigure(\n mcpSessionConfigFromProjection(candidate.projection, execution.cwd),\n execution.cwd,\n execution.repoRoot,\n );\n cleanup = () => candidate.cleanup();\n if (active === execution && selection === currentSelection) staleSelection = false;\n } catch (error) {\n await candidate.cleanup();\n throw error;\n }\n })\n .catch(async (error: unknown) => {\n if (active !== execution || selection !== currentSelection) return;\n await execution.client.notify({\n title: 'DoomPi MCP unavailable',\n body: error instanceof Error ? error.message : String(error),\n level: 'warning',\n });\n });\n return transition;\n };\n\n const activity: DoomHeadlessActivity = {\n name: 'doompi-mcp-runtime',\n async start(execution) {\n active = execution;\n currentSelection = execution.selection;\n staleSelection = false;\n const reported = new Set<string>();\n const publish = () => {\n execution.client.setStatus(\n MCP_STATUS_KEY,\n session\n .getServers()\n .map((server) => server.name)\n .join(','),\n );\n execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, formatMcpSessionAuthStatus(session.getServers()));\n for (const diagnostic of session.getDiagnostics()) {\n if (reported.has(diagnostic)) continue;\n reported.add(diagnostic);\n void execution.client.notify({ title: 'DoomPi MCP', body: diagnostic, level: 'warning' });\n }\n };\n const stopPublishing = session.onChange(publish);\n try {\n await refresh(execution, execution.selection);\n publish();\n } catch (error) {\n await execution.client.notify({\n title: 'DoomPi MCP unavailable',\n body: error instanceof Error ? error.message : String(error),\n level: 'warning',\n });\n }\n return async () => {\n stopPublishing();\n if (active !== execution) return;\n active = undefined;\n currentSelection = undefined;\n staleSelection = true;\n authorizing.clear();\n await transition;\n const retiredCleanup = cleanup;\n cleanup = undefined;\n try {\n await session.dispose();\n } finally {\n // Withdraw tools and UI state even when a connection fails to close.\n session.install({ enabled: false, repoRoot: execution.cwd, stagingDirectory: execution.cwd });\n await retiredCleanup?.();\n execution.client.setStatus(MCP_STATUS_KEY, undefined);\n execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, undefined);\n }\n };\n },\n };\n\n const invoke: Parameters<typeof createMcpChildTool>[0] = async (parameters, signal) => {\n if (!active) throw new Error('The MCP runtime has not started yet.');\n if (staleSelection) throw new Error('The MCP projection is stale for the current selection.');\n const selected = session\n .activeToolDefinitions()\n .find((candidate) => candidate.serverName === parameters.server && candidate.toolName === parameters.tool);\n if (!selected)\n throw new Error(`MCP tool ${parameters.server}/${parameters.tool} is not available in this session.`);\n return session.invokeTool(selected.piName, parameters.arguments ?? {}, signal);\n };\n const childTool = createMcpChildTool(invoke);\n\n // web-plugin-tool-renderers: ignore mcp_use, headless-only generic MCP dispatch\n const tool: DoomHeadlessTool<typeof McpHeadlessToolParameters> = {\n name: 'mcp_use',\n label: 'MCP use',\n description: 'Call a tool exposed by a connected MCP server.',\n parameters: McpHeadlessToolParameters,\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n try {\n return await invoke(parameters, signal);\n } catch (error) {\n return {\n content: [{ type: 'text', text: error instanceof Error ? error.message : String(error) }],\n isError: true,\n };\n }\n },\n };\n\n const command: DoomHeadlessCommand = {\n name: COMMAND_NAME,\n description: SERVER_COMMAND_DESCRIPTION,\n async execute(args, execution) {\n const [subcommand = 'status', ...rest] = args.trim().split(/\\s+/u).filter(Boolean);\n const serverName = rest.join(' ');\n const notify = (body: string, level: 'info' | 'warning' = 'info') =>\n execution.client.notify({ title: 'DoomPi MCP', body, level });\n try {\n if (subcommand === 'status') {\n await notify(formatStatus(session));\n return;\n }\n if (!active) throw new Error('The MCP runtime has not started yet.');\n if (staleSelection) throw new Error('The MCP projection is stale for the current selection.');\n if (subcommand === 'auth' || subcommand === 'disconnect') {\n if (!serverName) throw new Error(`Name the server, for example /mcp ${subcommand} <server>.`);\n const server = session.getServers().find((candidate) => candidate.name === serverName);\n if (!server) throw new Error(`Unknown MCP server: ${serverName}`);\n if (subcommand === 'disconnect') {\n await session.disconnect(serverName);\n authorizing.delete(serverName);\n await notify(`${serverName} is disconnected from this session. Saved credentials were kept.`);\n return;\n }\n if (server.authorizationUrl) {\n await session.openAuthorizationPage(serverName);\n return;\n }\n if (authorizing.has(serverName)) return;\n const request = Symbol(serverName);\n authorizing.set(serverName, request);\n const owner = active;\n // OAuth waits for the browser. Do not hold the session command queue while it does.\n void session.reauthorize(serverName).then(\n async () => {\n if (active !== owner || authorizing.get(serverName) !== request) return;\n authorizing.delete(serverName);\n await notify(`${serverName} is authorized.`);\n },\n async (error: unknown) => {\n if (active !== owner || authorizing.get(serverName) !== request) return;\n authorizing.delete(serverName);\n await notify(\n `Could not authorize ${serverName}: ${error instanceof Error ? error.message : String(error)}`,\n 'warning',\n );\n },\n );\n return;\n }\n if (subcommand === 'reload') {\n if (!currentSelection) throw new Error('The MCP runtime has not started yet.');\n await refresh(active, currentSelection);\n if (!staleSelection) await notify('Reconnecting MCP servers.');\n return;\n }\n throw new Error(`Unknown /${COMMAND_NAME} subcommand \"${subcommand}\". Use status, auth, disconnect, reload.`);\n } catch (error) {\n await notify(error instanceof Error ? error.message : String(error), 'warning');\n }\n },\n };\n return {\n session,\n activities: [activity],\n commands: [command],\n tools: [tool],\n childTool,\n async onSelectionChange(selection: DoomHeadlessSelection) {\n if (!active || workspaceRoot === undefined) return;\n if (JSON.stringify(currentSelection) === JSON.stringify(selection)) return;\n currentSelection = selection;\n await refresh(active, selection);\n },\n };\n}\n","import { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE } from '@agimon-ai/doompi-core/childSession';\nimport { DOOM_HEADLESS_HOST_SERVICE, type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport {\n DOOM_MCP_PROJECTION_RESOLVER_SERVICE,\n type DoomMcpProjectionResolverService,\n} from '@agimon-ai/doompi-core/mcpProjection';\nimport { DOOM_MCP_STATUS_SERVICE, type DoomMcpStatusService } from '@agimon-ai/doompi-core/mcpStatus';\nimport {\n DOOM_MCP_TOOL_RESOLVER_SERVICE,\n type DoomMcpToolResolverService,\n} from '@agimon-ai/doompi-core/mcpToolResolver';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { mountMcpHeadlessTools } from '../../../../../services/mcpHeadlessTools';\nimport { createMcpSessionToolsService, MCP_SESSION_TOOLS_SERVICE } from '../../../../../services/mcpSessionTools';\nimport { createMcpServerRuntime } from '../../../../../services/serverRuntime';\n\nexport const createMcpServerRoot = (context?: DoomServerPluginContext) => {\n let resolver: DoomMcpProjectionResolverService | undefined;\n const runtime = createMcpServerRuntime(\n context?.agent?.context?.environment,\n context?.host.context.workspaceRoot,\n () => resolver,\n );\n const generation = `${context?.agent?.context?.sessionId ?? crypto.randomUUID()}:mcp-server`;\n const { session } = runtime;\n const mountSession = (cordis: Context) => {\n cordis.inject([DOOM_MCP_PROJECTION_RESOLVER_SERVICE], (resolverContext) => {\n resolver = resolverContext.get(DOOM_MCP_PROJECTION_RESOLVER_SERVICE) as DoomMcpProjectionResolverService;\n return () => {\n resolver = undefined;\n };\n });\n cordis.inject([DOOM_HEADLESS_HOST_SERVICE], (hostContext) => {\n const host = hostContext.get(DOOM_HEADLESS_HOST_SERVICE) as DoomHeadlessHostService;\n return host.subscribeSelection((selection) => runtime.onSelectionChange(selection));\n });\n cordis.plugin((provider) => {\n provider.provide(DOOM_MCP_STATUS_SERVICE, {\n generation,\n getSnapshot: () => session.getSnapshot(),\n onChange: (listener) => session.onChange(listener),\n } satisfies DoomMcpStatusService);\n provider.provide(DOOM_MCP_TOOL_RESOLVER_SERVICE, {\n generation,\n resolve: (selectors) => session.resolveToolSelectors(selectors),\n } satisfies DoomMcpToolResolverService);\n provider.provide(MCP_SESSION_TOOLS_SERVICE, createMcpSessionToolsService(session, generation));\n provider.provide(DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, runtime.childTool);\n });\n };\n return {\n value: runtime,\n activities: runtime.activities,\n services: [mountMcpHeadlessTools(runtime.tools), mountSession],\n };\n};\nexport type McpServerScope = Awaited<ReturnType<typeof createMcpServerRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createMcpServerRoot } from './_lib/serverRoot';\n\nexport default defineRoot(createMcpServerRoot);\n","import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport type { DoomOAuthRedirect, DoomRepositorySyncView } from '@agimon-ai/doompi-core/packageApi';\nimport type { McpServerStateChange, McpToolInfo, TokenStore } from '@agimon-ai/mcp-proxy';\n\nimport type { McpConfigGroups, McpConfigSource, McpSessionConfig } from '../../types/mcpConfig';\nimport type {\n McpAuthorizationFlow,\n McpRepositoryCatalog,\n McpRepositoryServer,\n McpRepositoryServerState,\n McpRepositoryTool,\n} from '../../types/webMcp';\nimport { buildMcpConfigGroups } from '../configSources';\nimport { createTokenStore } from '../keyringTokenStore';\nimport { toPiToolName } from '../mcpCatalog';\nimport { hubCallbackSink, McpRuntimeOwner, readCachedCatalog } from '../mcpRuntime';\nimport { mcpSessionConfigFromProjection } from '../projection';\n\nconst DISCOVERY_TIMEOUT_MS = 30_000;\nconst AUTHORIZATION_TIMEOUT_MS = 5 * 60_000;\nconst TERMINAL_FLOW_RETENTION_MS = 5 * 60_000;\nconst EMPTY_SYNC = { fresh: false, reasons: ['never-synced'] } as const;\n\ninterface PreparedMcpRepository {\n catalog: McpRepositoryCatalog;\n configSources: McpConfigSource[];\n groups: McpConfigGroups;\n stagingDirectory?: string;\n}\n\ninterface InternalAuthorizationFlow extends McpAuthorizationFlow {\n owner?: McpRuntimeOwner;\n stagingDirectory?: string;\n timeout?: ReturnType<typeof setTimeout>;\n retainedUntil?: number;\n}\n\nexport interface McpSettingsManagerOptions {\n discoveryTimeoutMs?: number;\n authorizationTimeoutMs?: number;\n tokenStore?: TokenStore;\n}\n\nfunction configuredServerNames(groups: McpConfigGroups): string[] {\n return [...new Set([...groups.sessionLocal.serverNames, ...groups.shared.serverNames])].sort((left, right) =>\n left.localeCompare(right),\n );\n}\n\nfunction configSources(groups: McpConfigGroups): McpConfigSource[] {\n return [...groups.sessionLocal.configSources, ...groups.shared.configSources];\n}\n\nfunction toolView(serverName: string, tool: McpToolInfo): McpRepositoryTool {\n return {\n name: tool.name,\n piName: toPiToolName(serverName, tool.name),\n ...(tool.description ? { description: tool.description } : {}),\n };\n}\n\nfunction sanitizeDiagnostic(message: string, repositoryRoot: string, stagingDirectory: string | undefined): string {\n let safe = message;\n for (const value of [stagingDirectory, repositoryRoot, os.homedir()]) {\n if (value) safe = safe.split(value).join(value === os.homedir() ? '~' : '<repository>');\n }\n return safe.replace(/[A-Za-z]:\\\\[^\\s,;)'\"`]+/gu, '<path>').replace(/(^|\\s)\\/(?!\\/)[^\\s,;)'\"`]+/gu, '$1<path>');\n}\n\nfunction publicFlow(flow: InternalAuthorizationFlow): McpAuthorizationFlow {\n return {\n id: flow.id,\n repositoryId: flow.repositoryId,\n serverName: flow.serverName,\n status: flow.status,\n ...(flow.authorizationUrl ? { authorizationUrl: flow.authorizationUrl } : {}),\n ...(flow.error ? { error: flow.error } : {}),\n expiresAt: flow.expiresAt,\n };\n}\n\nfunction isTerminal(status: McpAuthorizationFlow['status']): boolean {\n return status === 'completed' || status === 'failed' || status === 'cancelled' || status === 'expired';\n}\n\nfunction safeAuthorizationUrl(url: URL): string | undefined {\n if ((url.protocol !== 'https:' && url.protocol !== 'http:') || url.toString().length > 4096) return undefined;\n return url.toString();\n}\n\nexport class McpSettingsManager {\n private readonly discoveryTimeoutMs: number;\n private readonly authorizationTimeoutMs: number;\n private readonly injectedTokenStore?: TokenStore;\n private readonly busyRepositories = new Set<string>();\n private readonly flows = new Map<string, InternalAuthorizationFlow>();\n\n constructor(options: McpSettingsManagerOptions = {}) {\n this.discoveryTimeoutMs = options.discoveryTimeoutMs ?? DISCOVERY_TIMEOUT_MS;\n this.authorizationTimeoutMs = options.authorizationTimeoutMs ?? AUTHORIZATION_TIMEOUT_MS;\n this.injectedTokenStore = options.tokenStore;\n }\n\n private async tokenStore(): Promise<TokenStore> {\n return this.injectedTokenStore ?? (await createTokenStore());\n }\n\n private async credentialPresence(serverNames: readonly string[]): Promise<Map<string, boolean>> {\n const presence = new Map<string, boolean>();\n try {\n const tokenStore = await this.tokenStore();\n await Promise.all(\n serverNames.map(async (serverName) => {\n try {\n presence.set(serverName, (await tokenStore.read(serverName)) !== undefined);\n } catch {\n presence.set(serverName, false);\n }\n }),\n );\n } catch {\n for (const serverName of serverNames) presence.set(serverName, false);\n }\n return presence;\n }\n\n private prepare(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n onlyServer?: string,\n ): PreparedMcpRepository {\n if (!sync?.mcpProjection) {\n const readiness = sync ?? EMPTY_SYNC;\n return {\n catalog: {\n repositoryId,\n sync: { fresh: readiness.fresh, reasons: [...readiness.reasons] },\n servers: [],\n droppedServers: [],\n diagnostics: [],\n },\n configSources: [],\n groups: {\n shared: { configSources: [], configPaths: [], serverNames: [] },\n sessionLocal: { configSources: [], configPaths: [], serverNames: [] },\n droppedServers: [],\n diagnostics: [],\n },\n };\n }\n\n const stagingDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'doompi-mcp-settings-'));\n fs.chmodSync(stagingDirectory, 0o700);\n try {\n const projected = mcpSessionConfigFromProjection(sync.mcpProjection);\n const configuration: McpSessionConfig = {\n ...projected,\n repoRoot: repositoryRoot,\n stagingDirectory,\n ...(onlyServer ? { allowlist: { servers: [onlyServer], proxy: [] } } : {}),\n };\n const groups = buildMcpConfigGroups(configuration);\n const sources = configSources(groups);\n const names = configuredServerNames(groups);\n const cachedByServer = new Map(readCachedCatalog(sources).servers.map((server) => [server.name, server.tools]));\n const servers: McpRepositoryServer[] = names.map((name) => {\n const tools = cachedByServer.get(name) ?? [];\n return {\n name,\n state: 'not-connected',\n source: tools.length === 0 ? 'configured' : 'cached',\n credentialPresent: false,\n tools: tools.map((tool) => toolView(name, tool)),\n };\n });\n return {\n catalog: {\n repositoryId,\n sync: { fresh: sync.fresh, reasons: [...sync.reasons] },\n servers,\n droppedServers: [...groups.droppedServers],\n diagnostics: groups.diagnostics.map((diagnostic) =>\n sanitizeDiagnostic(diagnostic, repositoryRoot, stagingDirectory),\n ),\n },\n configSources: sources,\n groups,\n stagingDirectory,\n };\n } catch (error) {\n fs.rmSync(stagingDirectory, { recursive: true, force: true });\n throw error;\n }\n }\n\n private cleanupPrepared(prepared: PreparedMcpRepository): void {\n if (prepared.stagingDirectory) fs.rmSync(prepared.stagingDirectory, { recursive: true, force: true });\n }\n\n async readCatalog(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n ): Promise<McpRepositoryCatalog> {\n const prepared = this.prepare(repositoryId, repositoryRoot, sync);\n try {\n const presence = await this.credentialPresence(prepared.catalog.servers.map((server) => server.name));\n return {\n ...prepared.catalog,\n servers: prepared.catalog.servers.map((server) => ({\n ...server,\n credentialPresent: presence.get(server.name) ?? false,\n })),\n };\n } finally {\n this.cleanupPrepared(prepared);\n }\n }\n\n async discover(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n ): Promise<McpRepositoryCatalog> {\n if (this.busyRepositories.has(repositoryId))\n throw new Error('MCP management is already active for this repository.');\n const prepared = this.prepare(repositoryId, repositoryRoot, sync);\n if (!prepared.catalog.sync.fresh) {\n this.cleanupPrepared(prepared);\n throw new Error('Sync this repository before discovering MCP capabilities.');\n }\n if (prepared.configSources.length === 0) {\n this.cleanupPrepared(prepared);\n return prepared.catalog;\n }\n\n this.busyRepositories.add(repositoryId);\n const owner = new McpRuntimeOwner();\n const liveStates = new Map<string, McpServerStateChange>();\n try {\n const handle = await owner.start({\n configSources: prepared.configSources,\n workspaceRoot: repositoryRoot,\n executionCwd: repositoryRoot,\n tokenStore: await this.tokenStore(),\n onAuthorizationUrl: (_url, serverName) => {\n liveStates.set(serverName, { serverName, state: 'needs-auth' });\n },\n onServerStateChange: (change) => liveStates.set(change.serverName, change),\n });\n if (handle) {\n await Promise.race([\n handle.connectionsSettled,\n new Promise<void>((resolve) => setTimeout(resolve, this.discoveryTimeoutMs)),\n ]);\n }\n const manager = handle?.services.clientManager;\n const cachedByServer = new Map(\n readCachedCatalog(prepared.configSources).servers.map((server) => [server.name, server.tools]),\n );\n const presence = await this.credentialPresence(prepared.catalog.servers.map((server) => server.name));\n const servers = await Promise.all(\n prepared.catalog.servers.map(async (server): Promise<McpRepositoryServer> => {\n const change = liveStates.get(server.name);\n const state = (change?.state ??\n manager?.getServerState(server.name) ??\n server.state) as McpRepositoryServerState;\n let tools = cachedByServer.get(server.name) ?? [];\n let source: McpRepositoryServer['source'] = tools.length === 0 ? 'configured' : 'cached';\n if (state === 'connected' && manager) {\n try {\n tools = await manager\n .ensureConnected(server.name)\n .then(async (connection) => await connection.listTools());\n source = 'live';\n } catch {\n // Preserve the cache when a server moved between state inspection and listing.\n }\n }\n return {\n name: server.name,\n state,\n source,\n credentialPresent: presence.get(server.name) ?? false,\n tools: tools.map((tool) => toolView(server.name, tool)),\n ...(change?.error ? { error: 'The server reported a connection error.' } : {}),\n };\n }),\n );\n return { ...prepared.catalog, servers };\n } finally {\n await owner.dispose();\n this.cleanupPrepared(prepared);\n this.busyRepositories.delete(repositoryId);\n }\n }\n\n async authorize(\n repositoryId: string,\n repositoryRoot: string,\n sync: DoomRepositorySyncView | undefined,\n serverName: string,\n /**\n * The hub's redirect surface. Present, the authorization server sends the\n * browser back to the hub, which is reachable whether the operator is at\n * this machine or on a tunnel. Absent, the proxy keeps its loopback\n * listener and behaviour is unchanged.\n */\n redirect?: DoomOAuthRedirect,\n ): Promise<McpAuthorizationFlow> {\n this.sweepFlows();\n if (this.busyRepositories.has(repositoryId))\n throw new Error('MCP management is already active for this repository.');\n\n const full = this.prepare(repositoryId, repositoryRoot, sync);\n const configured = full.catalog.servers.some((server) => server.name === serverName);\n const fresh = full.catalog.sync.fresh;\n this.cleanupPrepared(full);\n if (!fresh) throw new Error('Sync this repository before authorizing an MCP server.');\n if (!configured) throw new Error('That MCP server is not enabled for this repository.');\n\n const prepared = this.prepare(repositoryId, repositoryRoot, sync, serverName);\n const flow: InternalAuthorizationFlow = {\n id: randomUUID(),\n repositoryId,\n serverName,\n status: 'starting',\n expiresAt: Date.now() + this.authorizationTimeoutMs,\n stagingDirectory: prepared.stagingDirectory,\n };\n this.flows.set(flow.id, flow);\n this.busyRepositories.add(repositoryId);\n void this.runAuthorization(flow, prepared.configSources, repositoryRoot, redirect);\n return publicFlow(flow);\n }\n\n getAuthorization(flowId: string, repositoryId: string): McpAuthorizationFlow | undefined {\n this.sweepFlows();\n const flow = this.flows.get(flowId);\n return flow?.repositoryId === repositoryId ? publicFlow(flow) : undefined;\n }\n\n async cancelAuthorization(flowId: string, repositoryId: string): Promise<McpAuthorizationFlow | undefined> {\n const flow = this.flows.get(flowId);\n if (!flow || flow.repositoryId !== repositoryId) return undefined;\n if (!isTerminal(flow.status)) {\n flow.status = 'cancelled';\n await this.finishFlow(flow);\n }\n return publicFlow(flow);\n }\n\n private async runAuthorization(\n flow: InternalAuthorizationFlow,\n sources: McpConfigSource[],\n repositoryRoot: string,\n redirect?: DoomOAuthRedirect,\n ): Promise<void> {\n const owner = new McpRuntimeOwner();\n flow.owner = owner;\n flow.timeout = setTimeout(() => {\n if (isTerminal(flow.status)) return;\n flow.status = 'expired';\n flow.error = 'Authorization timed out.';\n void this.finishFlow(flow);\n }, this.authorizationTimeoutMs);\n\n try {\n const handle = await owner.start({\n configSources: sources,\n workspaceRoot: repositoryRoot,\n executionCwd: repositoryRoot,\n tokenStore: await this.tokenStore(),\n ...(redirect ? { callbackServer: hubCallbackSink(redirect) } : {}),\n onAuthorizationUrl: (url, serverName) => {\n if (serverName !== flow.serverName || isTerminal(flow.status)) return;\n const safeUrl = safeAuthorizationUrl(url);\n if (!safeUrl) {\n flow.status = 'failed';\n flow.error = 'The server returned an invalid authorization URL.';\n void this.finishFlow(flow);\n return;\n }\n flow.authorizationUrl = safeUrl;\n flow.status = 'waiting';\n },\n onServerStateChange: (change) => this.applyAuthorizationState(flow, change),\n });\n if (!handle || isTerminal(flow.status)) return;\n const manager = handle.services.clientManager;\n await manager.disconnectServer(flow.serverName);\n await manager.ensureConnected(flow.serverName);\n if (!isTerminal(flow.status)) flow.status = 'completed';\n } catch {\n if (!isTerminal(flow.status)) {\n flow.status = 'failed';\n flow.error = 'The MCP server could not complete authorization.';\n }\n } finally {\n if (!isTerminal(flow.status)) flow.status = 'completed';\n await this.finishFlow(flow);\n }\n }\n\n private applyAuthorizationState(flow: InternalAuthorizationFlow, change: McpServerStateChange): void {\n if (change.serverName !== flow.serverName || isTerminal(flow.status)) return;\n if (change.state === 'connected') flow.status = 'completed';\n else if (change.state === 'needs-auth' && flow.status === 'starting') flow.status = 'waiting';\n else if (change.state === 'failed') {\n flow.status = 'failed';\n flow.error = 'The MCP server rejected the authorization attempt.';\n }\n }\n\n private async finishFlow(flow: InternalAuthorizationFlow): Promise<void> {\n if (flow.timeout) clearTimeout(flow.timeout);\n flow.timeout = undefined;\n const owner = flow.owner;\n flow.owner = undefined;\n await owner?.dispose();\n if (flow.stagingDirectory) fs.rmSync(flow.stagingDirectory, { recursive: true, force: true });\n flow.stagingDirectory = undefined;\n this.busyRepositories.delete(flow.repositoryId);\n flow.retainedUntil = Date.now() + TERMINAL_FLOW_RETENTION_MS;\n }\n\n private sweepFlows(): void {\n const now = Date.now();\n for (const [id, flow] of this.flows) {\n if (flow.retainedUntil !== undefined && flow.retainedUntil <= now) this.flows.delete(id);\n }\n }\n\n async dispose(): Promise<void> {\n await Promise.all(\n [...this.flows.values()].map(async (flow) => {\n if (!isTerminal(flow.status)) flow.status = 'cancelled';\n await this.finishFlow(flow);\n }),\n );\n this.flows.clear();\n this.busyRepositories.clear();\n }\n}\n","import { apiResponse, defineApiRoutes } from '@agimon-ai/doompi-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 type McpAuthorizationFlow,\n type McpRepositoryCatalog,\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});\n","import type { DoomApi, DoomApiContext } from '@agimon-ai/doompi-core/packageApi';\n\nimport { McpSettingsManager } from '../../services/mcpSettingsManager';\nimport routes from '../../types/apiRoutes';\nimport { MCP_FLOW_ID_PARAM, MCP_REPOSITORY_ID_QUERY } from '../../types/webMcp';\n\n/**\n * What sits above a flow id, read off the flow route itself.\n *\n * This handler matches paths by hand rather than through a router, so the one\n * route carrying a parameter is split here: everything before `:flowId` is the\n * prefix a request must start with, and what follows it is the id.\n */\nconst AUTHORIZATION_FLOW_PREFIX = routes.readAuthorization.path.replace(`:${MCP_FLOW_ID_PARAM}`, '');\n\nconst JSON_HEADERS = { 'content-type': 'application/json' };\nconst REPOSITORY_ID = /^(?:[a-f0-9]{32}|repo-[A-Za-z0-9_-]{24})$/u;\nconst FLOW_ID = /^[a-f0-9-]{36}$/u;\nconst MAX_BODY_BYTES = 8 * 1024;\nconst MAX_SERVER_NAME = 160;\nconst manager = new McpSettingsManager();\n\ntype JsonRecord = Record<string, unknown>;\n\nfunction json(body: unknown, status = 200): Response {\n return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS });\n}\n\nfunction isRecord(value: unknown): value is JsonRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nasync function bodyOf(request: Request): Promise<JsonRecord | undefined> {\n const text = await request.text();\n if (text.length > MAX_BODY_BYTES) return undefined;\n try {\n const parsed = JSON.parse(text) as unknown;\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction repositoryIdOf(value: unknown): string | undefined {\n return typeof value === 'string' && REPOSITORY_ID.test(value) ? value : undefined;\n}\n\nfunction serverNameOf(value: unknown): string | undefined {\n return typeof value === 'string' &&\n value.length > 0 &&\n value.length <= MAX_SERVER_NAME &&\n !Array.from(value).some((character) => character.charCodeAt(0) <= 0x1f)\n ? value\n : undefined;\n}\n\nfunction resolveRepository(context: DoomApiContext, repositoryId: string): string | undefined {\n return context.resolveRepository?.(repositoryId);\n}\n\nfunction errorStatus(error: unknown): { status: number; message: string } {\n const message = error instanceof Error ? error.message : '';\n if (message.includes('already active')) return { status: 409, message };\n if (message.startsWith('Sync this repository')) return { status: 409, message };\n if (message.includes('not enabled')) return { status: 404, message };\n return { status: 500, message: 'MCP management could not complete that request.' };\n}\n\nasync function handleCatalog(request: Request, context: DoomApiContext): Promise<Response> {\n const repositoryId = repositoryIdOf(new URL(request.url).searchParams.get(MCP_REPOSITORY_ID_QUERY));\n if (!repositoryId) return json({ error: 'A valid repositoryId is required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(await manager.readCatalog(repositoryId, repositoryRoot, context.readRepositorySync?.(repositoryId)));\n } catch {\n return json({ error: 'The synced MCP catalog could not be read.' }, 500);\n }\n}\n\nasync function handleDiscovery(request: Request, context: DoomApiContext): Promise<Response> {\n const body = await bodyOf(request);\n const repositoryId = repositoryIdOf(body?.repositoryId);\n if (!repositoryId) return json({ error: 'A valid repositoryId is required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(await manager.discover(repositoryId, repositoryRoot, context.readRepositorySync?.(repositoryId)));\n } catch (error) {\n const failure = errorStatus(error);\n return json({ error: failure.message }, failure.status);\n }\n}\n\nasync function handleAuthorize(request: Request, context: DoomApiContext): Promise<Response> {\n const body = await bodyOf(request);\n const repositoryId = repositoryIdOf(body?.repositoryId);\n const serverName = serverNameOf(body?.serverName);\n if (!repositoryId || !serverName) return json({ error: 'A valid repositoryId and serverName are required.' }, 400);\n const repositoryRoot = resolveRepository(context, repositoryId);\n if (!repositoryRoot) return json({ error: 'That repository is not available to this hub.' }, 404);\n try {\n return json(\n await manager.authorize(\n repositoryId,\n repositoryRoot,\n context.readRepositorySync?.(repositoryId),\n serverName,\n context.oauthRedirect?.(),\n ),\n 202,\n );\n } catch (error) {\n const failure = errorStatus(error);\n return json({ error: failure.message }, failure.status);\n }\n}\n\nasync function handleAuthorizationFlow(request: Request, context: DoomApiContext, path: string): Promise<Response> {\n const flowId = path.slice(AUTHORIZATION_FLOW_PREFIX.length);\n const repositoryId = repositoryIdOf(new URL(request.url).searchParams.get(MCP_REPOSITORY_ID_QUERY));\n if (!repositoryId || !FLOW_ID.test(flowId))\n return json({ error: 'A valid repositoryId and flow id are required.' }, 400);\n if (!resolveRepository(context, repositoryId)) {\n return json({ error: 'That repository is not available to this hub.' }, 404);\n }\n if (request.method === routes.cancelAuthorization.method) {\n const flow = await manager.cancelAuthorization(flowId, repositoryId);\n return flow ? json(flow) : json({ error: 'That authorization flow was not found.' }, 404);\n }\n const flow = manager.getAuthorization(flowId, repositoryId);\n return flow ? json(flow) : json({ error: 'That authorization flow was not found.' }, 404);\n}\n\nexport const mcpHubApi: DoomApi = {\n basePath: 'mcp',\n start(context) {\n return {\n async fetch(request) {\n const path = new URL(request.url).pathname;\n if (request.method === routes.catalog.method && path === routes.catalog.path) {\n return await handleCatalog(request, context);\n }\n if (request.method === routes.discover.method && path === routes.discover.path) {\n return await handleDiscovery(request, context);\n }\n if (request.method === routes.authorize.method && path === routes.authorize.path) {\n return await handleAuthorize(request, context);\n }\n if (\n (request.method === routes.readAuthorization.method ||\n request.method === routes.cancelAuthorization.method) &&\n path.startsWith(AUTHORIZATION_FLOW_PREFIX)\n ) {\n return await handleAuthorizationFlow(request, context, path);\n }\n return json({ error: 'Not found.' }, 404);\n },\n close() {\n void manager.dispose();\n },\n };\n },\n};\n","import { defineRoute } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { mcpHubApi } from '../../../../services/mcpHubApi';\n\n/**\n * Mounts this package's HTTP API at `mcp`, which the folder names.\n *\n * The folder is the declaration: the build reads the base path off it and hands\n * the browser a client bound to the same segment, so the settings panel can no\n * longer spell a workspace mount by hand.\n */\nexport default defineRoute(mcpHubApi);\n","import { defineServerCommand, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { McpServerScope } from '../_lib/serverRoot';\nexport default defineServerCommand(\n (context: WithRoot<DoomServerPluginContext, McpServerScope>) => context.root.commands[0]!,\n);\n","import { defineServerTool, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport type { McpServerScope } from '../_lib/serverRoot';\nexport default defineServerTool((context: WithRoot<DoomServerPluginContext, McpServerScope>) => context.root.tools[0]!);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport apiRoute from '../src/extensions/(backend)/api/mcp/route.server';\nimport commandMcp from '../src/extensions/workspaces/sessions/(backend)/command/mcp.server';\nimport toolMcpUse from '../src/extensions/workspaces/sessions/(backend)/tool/mcp_use.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-mcp',\n global: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n workspace: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n get commands(): DoomServerSessionPlugin['commands'] { return [via({ name: 'mcp' }, at(commandMcp, contextSession))]; },\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'mcp_use' }, at(toolMcpUse, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-mcp",
3
- "version": "0.0.1-alpha.90",
3
+ "version": "0.0.1-alpha.92",
4
4
  "description": "Domain-aware MCP server selection and access boundaries for Pi sessions composed with DoomPi.",
5
5
  "keywords": [
6
6
  "ai",
@@ -73,10 +73,10 @@
73
73
  "access": "public"
74
74
  },
75
75
  "dependencies": {
76
- "@agimon-ai/doompi-config": "0.0.1-alpha.88",
77
- "@agimon-ai/doompi-core": "0.0.1-alpha.89",
78
- "@agimon-ai/doompi-ui": "0.0.1-alpha.89",
79
- "@agimon-ai/doompi-web-components": "0.0.1-alpha.47",
76
+ "@agimon-ai/doompi-config": "0.0.1-alpha.90",
77
+ "@agimon-ai/doompi-core": "0.0.1-alpha.91",
78
+ "@agimon-ai/doompi-ui": "0.0.1-alpha.91",
79
+ "@agimon-ai/doompi-web-components": "0.0.1-alpha.49",
80
80
  "@agimon-ai/doompi-web-security": "0.0.1-alpha.46",
81
81
  "@agimon-ai/mcp-proxy": "0.31.30",
82
82
  "@deepseek-ai/cordis": "4.0.2",