@agimon-ai/po-mcp 0.0.0-alpha.74 → 0.0.0-alpha.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +52 -0
  2. package/dist/extensions/server.cjs +127 -49
  3. package/dist/extensions/server.cjs.map +1 -1
  4. package/dist/extensions/server.mjs +128 -50
  5. package/dist/extensions/server.mjs.map +1 -1
  6. package/dist/index-BcP-x1SE.d.mts +58 -0
  7. package/dist/index-BcP-x1SE.d.mts.map +1 -0
  8. package/dist/index.cjs +15 -3
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.mts +4 -9
  11. package/dist/index.d.mts.map +1 -1
  12. package/dist/index.mjs +9 -1
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/localServers.cjs +1 -1
  15. package/dist/localServers.d.mts +2 -39
  16. package/dist/localServers.mjs +1 -1
  17. package/dist/{mcpCatalog-rxpMjGIW.mjs → mcpCatalog-BiSdyG0A.mjs} +6 -5
  18. package/dist/mcpCatalog-BiSdyG0A.mjs.map +1 -0
  19. package/dist/{mcpCatalog-Be0BcPOu.cjs → mcpCatalog-Domudw3m.cjs} +5 -5
  20. package/dist/mcpCatalog-Domudw3m.cjs.map +1 -0
  21. package/dist/sessionServers-CJNAexGl.cjs +357 -0
  22. package/dist/sessionServers-CJNAexGl.cjs.map +1 -0
  23. package/dist/sessionServers-LBfUXsdp.mjs +328 -0
  24. package/dist/sessionServers-LBfUXsdp.mjs.map +1 -0
  25. package/dist/sessionServers.cjs +4 -0
  26. package/dist/sessionServers.d.mts +2 -0
  27. package/dist/sessionServers.mjs +1 -0
  28. package/package.json +14 -9
  29. package/dist/localServers.d.mts.map +0 -1
  30. package/dist/mcpCatalog-Be0BcPOu.cjs.map +0 -1
  31. package/dist/mcpCatalog-rxpMjGIW.mjs.map +0 -1
  32. package/dist/sessionServers-aDZVqS6t.mjs +0 -182
  33. package/dist/sessionServers-aDZVqS6t.mjs.map +0 -1
  34. package/dist/sessionServers-xi5PL_GP.cjs +0 -199
  35. package/dist/sessionServers-xi5PL_GP.cjs.map +0 -1
package/README.md CHANGED
@@ -78,6 +78,58 @@ session Cordis root.
78
78
  Downstream clients run in-process through `@agimon-ai/po-mcp-proxy`; this adapter does not start its
79
79
  Hono server.
80
80
 
81
+ ## Temporary connections for packages
82
+
83
+ Trusted session plugins inject `PO_MCP_SERVICE` from `@agimon-ai/po-core/mcp` and call
84
+ `readPoMcp(scoped)` inside that injection on their session Cordis root. `po-mcp` provides
85
+ this portable contract through `PO_MCP_CONTRACT`. This is not a model-visible management
86
+ API or a package-identity boundary. The caller authorizes the destination, binds code-mode
87
+ calls to the owning session, and passes the run's abort signal for establishment.
88
+
89
+ ```ts
90
+ const connection = await servers.register(
91
+ {
92
+ name: 'development',
93
+ url: 'https://example.com/mcp',
94
+ apiKey: { mode: 'bearer', environmentVariable: 'DEVELOPMENT_API_KEY' },
95
+ },
96
+ signal,
97
+ );
98
+ try {
99
+ // Tools also join this session's normal MCP surface.
100
+ const tools = connection.snapshot().tools;
101
+ if (tools.includes('ping')) await connection.invoke('ping', {});
102
+ } finally {
103
+ await connection.dispose();
104
+ }
105
+ ```
106
+
107
+ `register` connects immediately and returns an identity-owned handle with `name`, live
108
+ `snapshot()`, validated `invoke(tool, args?, signal?)`, and asynchronous idempotent `dispose()`.
109
+ HTTP/SSE no-auth connections require HTTP loopback with an explicit port and never start OAuth.
110
+ API-key connections also accept HTTPS. URL userinfo, fragments, URL environment interpolation,
111
+ reserved names, and all existing or pending-removal names are rejected. Registrations never
112
+ replace a connection. Snapshot and invocation cannot observe a same-name replacement.
113
+
114
+ API keys use `{ mode: 'bearer', environmentVariable }` or
115
+ `{ mode: 'header', name: 'X-Api-Key', environmentVariable }`. Trusted server code may
116
+ instead supply `value` programmatically. Do not print keys or add credential-bearing call records.
117
+ Literal keys embedded in `exec` source still persist in saved scripts and transcripts. Environment
118
+ references read only the owning session's admitted environment.
119
+ The key stays in the session overlay, outside proxy configuration, disk caches, and the
120
+ vault. The existing proxy API-key transport pins credentials to the destination origin,
121
+ refuses redirects, and never starts OAuth.
122
+
123
+ Establishment cancellation rolls back its partial entry and connection. Once connected, normal
124
+ `exec` completion does not dispose the registration. `dispose()` remains available after run
125
+ cancellation or selection changes. Call it in `finally` when development ends, including failed
126
+ stop paths. Provider shutdown retires handles and closes connections; it does not stop external
127
+ MCP server processes. No saved MCP config is changed.
128
+
129
+ The existing `@agimon-ai/po-mcp/localServers` and `/sessionServers` APIs remain compatibility
130
+ adapters with their original name-based result and cleanup methods. New consumers use the core
131
+ contract and owned handles.
132
+
81
133
  ## Direct tools and configured identity
82
134
 
83
135
  Main sessions and native child agents receive permitted named MCP tools with their descriptions
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_rolldown_runtime = require("../rolldown-runtime-C0BPl7ul.cjs");
6
- const require_mcpCatalog = require("../mcpCatalog-Be0BcPOu.cjs");
7
- const require_sessionServers = require("../sessionServers-xi5PL_GP.cjs");
6
+ const require_mcpCatalog = require("../mcpCatalog-Domudw3m.cjs");
7
+ const require_sessionServers = require("../sessionServers-CJNAexGl.cjs");
8
8
  const require_projection = require("../projection-DBpXsw0W.cjs");
9
9
  let node_crypto = require("node:crypto");
10
10
  let node_fs_promises = require("node:fs/promises");
@@ -14,6 +14,7 @@ node_path = require_rolldown_runtime.__toESM(node_path, 1);
14
14
  let _agimon_ai_po_config_agentPluginMcp = require("@agimon-ai/po-config/agentPluginMcp");
15
15
  let node_os = require("node:os");
16
16
  node_os = require_rolldown_runtime.__toESM(node_os, 1);
17
+ let _agimon_ai_po_core_mcpSession = require("@agimon-ai/po-core/mcpSession");
17
18
  let _agimon_ai_po_core_help = require("@agimon-ai/po-core/help");
18
19
  let _agimon_ai_po_mcp_proxy = require("@agimon-ai/po-mcp-proxy");
19
20
  let typebox_value = require("typebox/value");
@@ -27,8 +28,10 @@ let _agimon_ai_po_core_piSettings = require("@agimon-ai/po-core/piSettings");
27
28
  let _agimon_ai_po_core_childSession = require("@agimon-ai/po-core/childSession");
28
29
  let _agimon_ai_po_core_codemode = require("@agimon-ai/po-core/codemode");
29
30
  let _agimon_ai_po_core_headless = require("@agimon-ai/po-core/headless");
31
+ let _agimon_ai_po_core_mcp = require("@agimon-ai/po-core/mcp");
30
32
  let _agimon_ai_po_core_mcpStatus = require("@agimon-ai/po-core/mcpStatus");
31
33
  let _agimon_ai_po_core_mcpToolResolver = require("@agimon-ai/po-core/mcpToolResolver");
34
+ let _agimon_ai_po_core_platform = require("@agimon-ai/po-core/platform");
32
35
  let node_dns_promises = require("node:dns/promises");
33
36
  node_dns_promises = require_rolldown_runtime.__toESM(node_dns_promises, 1);
34
37
  let node_https = require("node:https");
@@ -2718,6 +2721,11 @@ var McpSession = class {
2718
2721
  toolRestriction;
2719
2722
  enabled = true;
2720
2723
  startup;
2724
+ initialConfiguration() {
2725
+ const configuration = (0, _agimon_ai_po_core_mcpSession.readPoMcpSessionConfig)(this.options.environment ?? {});
2726
+ if (!configuration) throw new Error("MCP session configuration must be supplied by the host.");
2727
+ return configuration;
2728
+ }
2721
2729
  /** Resolved per tool call, so a registration outlives the container it was made under. */
2722
2730
  getClientManager = () => this.runtime?.getServices()?.clientManager;
2723
2731
  constructor(options) {
@@ -2754,7 +2762,7 @@ var McpSession = class {
2754
2762
  * Returns the servers it seeded, so a caller can report what the session started
2755
2763
  * with before anything connected.
2756
2764
  */
2757
- async install(configuration = require_mcpCatalog.readSessionConfig(this.options.environment)) {
2765
+ async install(configuration = this.initialConfiguration()) {
2758
2766
  const generation = ++this.lifecycleGeneration;
2759
2767
  await this.bindConfiguration(configuration);
2760
2768
  if (generation !== this.lifecycleGeneration) return this.catalog.toSnapshot();
@@ -2929,7 +2937,7 @@ var McpSession = class {
2929
2937
  if (!this.enabled || this.configuredServerNames().length === 0) return;
2930
2938
  const [{ MemoryTokenStore }, { McpRuntimeOwner }, { VaultTokenStore }] = await Promise.all([
2931
2939
  import("@agimon-ai/po-mcp-proxy"),
2932
- Promise.resolve().then(() => require("../mcpCatalog-Be0BcPOu.cjs")).then((n) => n.mcpRuntime_exports),
2940
+ Promise.resolve().then(() => require("../mcpCatalog-Domudw3m.cjs")).then((n) => n.mcpRuntime_exports),
2933
2941
  Promise.resolve().then(() => vaultTokenStore_exports)
2934
2942
  ]);
2935
2943
  if (generation !== this.lifecycleGeneration) return;
@@ -2961,6 +2969,14 @@ var McpSession = class {
2961
2969
  scopeOf: (serverName) => Object.hasOwn(this.groups.serverScopes, serverName) ? this.groups.serverScopes[serverName] : void 0,
2962
2970
  onMissing: (miss) => this.recordSecretMiss(miss, generation)
2963
2971
  }),
2972
+ resolveUrlCredentials: async (target) => {
2973
+ target.signal?.throwIfAborted();
2974
+ if (generation !== this.lifecycleGeneration || this.hasConfiguredServer(target.serverName)) return void 0;
2975
+ const entry = this.options.sessionServers?.().get(target.serverName);
2976
+ const key = entry?.apiKey;
2977
+ if (!entry || !key || entry.config.transport !== target.transport || !("url" in entry.config.config) || entry.config.config.url !== target.url || canonicalJson(key.auth) !== canonicalJson(target.auth)) return void 0;
2978
+ return key.auth.mode === "bearer" ? { Authorization: `Bearer ${key.value}` } : { [key.auth.name]: key.value };
2979
+ },
2964
2980
  onAuthorizationUrl: (url, serverName) => this.onAuthorizationUrl(url, serverName, generation),
2965
2981
  onServerStateChange: (change) => this.onServerStateChange(change, generation),
2966
2982
  onOutputSchemaWarning: (warning) => {
@@ -3332,6 +3348,7 @@ var McpSession = class {
3332
3348
  if (change.state !== "connecting" && change.state !== "needs-auth") this.authorizationUrls.delete(change.serverName);
3333
3349
  const runtime = this.runtime;
3334
3350
  const services = runtime?.getServices();
3351
+ const entry = this.options.sessionServers?.().get(change.serverName);
3335
3352
  (change.state === "connected" && services ? services.clientManager.ensureConnected(change.serverName).then((connection) => connection.listTools()) : Promise.resolve([])).then((tools) => ({
3336
3353
  tools,
3337
3354
  error: void 0
@@ -3339,7 +3356,7 @@ var McpSession = class {
3339
3356
  tools: [],
3340
3357
  error: `Could not discover tools for MCP server "${change.serverName}".`
3341
3358
  })).then(({ tools, error }) => {
3342
- if (generation !== this.lifecycleGeneration || !runtime?.isCurrent(services) || this.disconnectedServers.has(change.serverName)) return;
3359
+ if (generation !== this.lifecycleGeneration || !runtime?.isCurrent(services) || this.disconnectedServers.has(change.serverName) || this.options.sessionServers?.().get(change.serverName) !== entry) return;
3343
3360
  if (error) this.catalog.addDiagnostic(error);
3344
3361
  this.catalog.applyStateChange(error ? {
3345
3362
  ...change,
@@ -3440,11 +3457,10 @@ function createMcpSessionApi(source, countTokens) {
3440
3457
  }
3441
3458
  //#endregion
3442
3459
  //#region src/services/serverRuntime/index.ts
3443
- async function sessionConfiguration(execution, workspaceRoot) {
3460
+ async function sessionConfiguration(execution, workspaceRoot, loaded) {
3444
3461
  if (workspaceRoot !== void 0) {
3445
- const loaded = (0, _agimon_ai_po_config_harnessStore.loadHarnessState)({ ...execution.environment });
3446
- const projection = loaded.state.mcpProjection;
3447
- if (loaded.filePath && loaded.state.root === workspaceRoot && execution.repoRoot === workspaceRoot && loaded.state.mcp && loaded.state.majorMode === execution.selection.majorMode && JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) && JSON.stringify(loaded.state.layers) === JSON.stringify(execution.selection.activeLayers) && (0, _agimon_ai_po_core_mcpProjection.isPoMcpProjection)(projection) && projection.repoRoot === workspaceRoot) return require_projection.mcpSessionConfigFromProjection(projection, execution.cwd);
3462
+ const projection = loaded?.state.mcpProjection;
3463
+ if (loaded?.filePath && loaded.state.root === workspaceRoot && execution.repoRoot === workspaceRoot && loaded.state.mcp && loaded.state.majorMode === execution.selection.majorMode && JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) && JSON.stringify(loaded.state.layers) === JSON.stringify(execution.selection.activeLayers) && (0, _agimon_ai_po_core_mcpProjection.isPoMcpProjection)(projection) && projection.repoRoot === workspaceRoot) return require_projection.mcpSessionConfigFromProjection(projection, execution.cwd);
3448
3464
  return {
3449
3465
  enabled: false,
3450
3466
  repoRoot: execution.cwd,
@@ -3454,8 +3470,11 @@ async function sessionConfiguration(execution, workspaceRoot) {
3454
3470
  }
3455
3471
  return require_mcpCatalog.readSessionConfig(execution.environment, execution.cwd);
3456
3472
  }
3457
- function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver, publishFile, assertPackageActive, getVault) {
3473
+ function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver, publishFile, assertPackageActive, getVault, getFs) {
3458
3474
  let active;
3475
+ let stopActive;
3476
+ let disposed = false;
3477
+ let disposal;
3459
3478
  let currentSelection;
3460
3479
  let staleSelection = false;
3461
3480
  let cleanup;
@@ -3478,6 +3497,7 @@ function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver, pu
3478
3497
  sessionServers: () => sessionServers
3479
3498
  });
3480
3499
  const assertAvailable = () => {
3500
+ if (disposed) throw new Error("The MCP runtime has been disposed.");
3481
3501
  if (!active) throw new Error("The MCP runtime has not started yet.");
3482
3502
  if (staleSelection) throw new Error("The MCP projection is stale for the current selection.");
3483
3503
  };
@@ -3486,6 +3506,11 @@ function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver, pu
3486
3506
  session,
3487
3507
  entries: sessionServers,
3488
3508
  environment,
3509
+ invoke: (server, tool, args, signal) => invoke({
3510
+ server,
3511
+ tool,
3512
+ arguments: args
3513
+ }, signal),
3489
3514
  assertAdmitted(sessionId, signal) {
3490
3515
  assertPackageActive?.();
3491
3516
  assertAvailable();
@@ -3525,11 +3550,13 @@ function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver, pu
3525
3550
  }
3526
3551
  if (active !== execution) return;
3527
3552
  const resolver = getResolver?.();
3528
- const loaded = workspaceRoot ? (0, _agimon_ai_po_config_harnessStore.loadHarnessState)({ ...execution.environment }) : void 0;
3553
+ const fs = getFs?.();
3554
+ if (workspaceRoot && !fs) throw new Error("MCP session configuration requires the host filesystem.");
3555
+ const loaded = workspaceRoot && fs ? await (0, _agimon_ai_po_config_harnessStore.loadHarnessStateAsync)(fs, { ...execution.environment }, (0, _agimon_ai_po_core_platform.withAbortSignal)(lifetime.signal, _agimon_ai_po_core_platform.BACKGROUND_CONTEXT)) : void 0;
3529
3556
  const authorized = workspaceRoot && loaded?.filePath && loaded.state.root === workspaceRoot && execution.repoRoot === workspaceRoot && loaded.state.mcp && (0, _agimon_ai_po_core_mcpProjection.isPoMcpProjection)(loaded.state.mcpProjection) && loaded.state.mcpProjection.repoRoot === workspaceRoot && loaded.state.mcpProjection.enabled;
3530
3557
  if (!resolver || !authorized) {
3531
3558
  if (active === execution && selection === currentSelection) {
3532
- if (workspaceRoot === void 0 || JSON.stringify(execution.selection.domains) === JSON.stringify(selection.domains)) await session.reconfigure(await sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);
3559
+ if (workspaceRoot === void 0 || JSON.stringify(execution.selection.domains) === JSON.stringify(selection.domains)) await session.reconfigure(await sessionConfiguration(execution, workspaceRoot, loaded), execution.cwd, execution.repoRoot);
3533
3560
  staleSelection = workspaceRoot !== void 0 && JSON.stringify(execution.selection.domains) !== JSON.stringify(selection.domains);
3534
3561
  }
3535
3562
  return;
@@ -3548,8 +3575,13 @@ function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver, pu
3548
3575
  await candidate.cleanup();
3549
3576
  throw error;
3550
3577
  }
3551
- }).then(() => {
3552
- for (const name of sessionServers.keys()) if (session.hasConfiguredServer(name)) sessionServers.delete(name);
3578
+ }).then(async () => {
3579
+ for (const [name, entry] of sessionServers) {
3580
+ if (!session.hasConfiguredServer(name)) continue;
3581
+ sessionServers.delete(name);
3582
+ delete entry.apiKey;
3583
+ await entry.tokenStore.clear(name);
3584
+ }
3553
3585
  sessionTools.refresh();
3554
3586
  }).catch(async (error) => {
3555
3587
  if (active !== execution || selection !== currentSelection) return;
@@ -3581,6 +3613,7 @@ function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver, pu
3581
3613
  const activity = {
3582
3614
  name: "po-mcp-runtime",
3583
3615
  async start(execution) {
3616
+ if (disposed) throw new Error("The MCP runtime has been disposed.");
3584
3617
  active = execution;
3585
3618
  lifetime = new AbortController();
3586
3619
  currentSelection = execution.selection;
@@ -3620,44 +3653,53 @@ function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver, pu
3620
3653
  loadTokenizer().then(() => {
3621
3654
  if (active === execution) publish();
3622
3655
  });
3656
+ let stopping;
3657
+ const stop = () => {
3658
+ stopping ??= (async () => {
3659
+ stopPublishing();
3660
+ if (active !== execution) return;
3661
+ lifetime.abort();
3662
+ setHelp();
3663
+ testServers.clear();
3664
+ active = void 0;
3665
+ currentSelection = void 0;
3666
+ staleSelection = true;
3667
+ sessionTools.refresh();
3668
+ authorizing.clear();
3669
+ await transition;
3670
+ const retiredCleanup = cleanup;
3671
+ cleanup = void 0;
3672
+ try {
3673
+ await session.dispose();
3674
+ } finally {
3675
+ await session.install({
3676
+ enabled: false,
3677
+ repoRoot: execution.cwd,
3678
+ stagingDirectory: execution.cwd
3679
+ });
3680
+ await retiredCleanup?.();
3681
+ execution.client.setStatus(MCP_STATUS_KEY, void 0);
3682
+ execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, void 0);
3683
+ execution.client.setStatus(_agimon_ai_po_core_contextApi.CONTEXT_TOOL_WARNINGS_STATUS_KEY, void 0);
3684
+ }
3685
+ })().finally(async () => {
3686
+ if (stopActive === stop) stopActive = void 0;
3687
+ await testServers.settleRemovals();
3688
+ });
3689
+ return stopping;
3690
+ };
3691
+ stopActive = stop;
3623
3692
  try {
3624
3693
  await refresh(execution, execution.selection);
3625
- publish();
3694
+ if (active === execution) publish();
3626
3695
  } catch (error) {
3627
- await execution.client.notify({
3696
+ if (active === execution) await execution.client.notify({
3628
3697
  title: "Po MCP unavailable",
3629
3698
  body: error instanceof Error ? error.message : String(error),
3630
3699
  level: "warning"
3631
3700
  });
3632
3701
  }
3633
- return async () => {
3634
- stopPublishing();
3635
- if (active !== execution) return;
3636
- lifetime.abort();
3637
- setHelp();
3638
- sessionServers.clear();
3639
- active = void 0;
3640
- currentSelection = void 0;
3641
- staleSelection = true;
3642
- sessionTools.refresh();
3643
- authorizing.clear();
3644
- await transition;
3645
- const retiredCleanup = cleanup;
3646
- cleanup = void 0;
3647
- try {
3648
- await session.dispose();
3649
- } finally {
3650
- await session.install({
3651
- enabled: false,
3652
- repoRoot: execution.cwd,
3653
- stagingDirectory: execution.cwd
3654
- });
3655
- await retiredCleanup?.();
3656
- execution.client.setStatus(MCP_STATUS_KEY, void 0);
3657
- execution.client.setStatus(MCP_SESSION_AUTH_STATUS_KEY, void 0);
3658
- execution.client.setStatus(_agimon_ai_po_core_contextApi.CONTEXT_TOOL_WARNINGS_STATUS_KEY, void 0);
3659
- }
3660
- };
3702
+ return stop;
3661
3703
  }
3662
3704
  };
3663
3705
  const invoke = async (parameters, signal) => {
@@ -3759,6 +3801,28 @@ function createMcpServerRuntime(environment = {}, workspaceRoot, getResolver, pu
3759
3801
  testServerTool: testServers.tool,
3760
3802
  testServerNamespace: testServers.namespace,
3761
3803
  localServers: testServers.localServers,
3804
+ sessionServers: testServers.sessionServers,
3805
+ mcp: testServers.mcp,
3806
+ dispose() {
3807
+ if (disposal) return disposal;
3808
+ disposed = true;
3809
+ lifetime.abort();
3810
+ testServers.retire();
3811
+ const stop = stopActive;
3812
+ disposal = (async () => {
3813
+ try {
3814
+ if (stop) await stop();
3815
+ else {
3816
+ await transition;
3817
+ await session.dispose();
3818
+ }
3819
+ } finally {
3820
+ sessionTools.dispose();
3821
+ await testServers.settleRemovals();
3822
+ }
3823
+ })();
3824
+ return disposal;
3825
+ },
3762
3826
  isHelpActive: () => helpActive,
3763
3827
  onHelpChange(listener) {
3764
3828
  helpListeners.add(listener);
@@ -3787,17 +3851,24 @@ const createMcpServerRoot = (context) => {
3787
3851
  host: () => appHost,
3788
3852
  signal: context?.signal
3789
3853
  });
3790
- const runtime = createMcpServerRuntime(context?.agent?.context?.environment, context?.host.context.workspaceRoot, () => resolver, publishFile, () => appHost?.assertActive("@agimon-ai/po-mcp"), () => serverScope?.resolve(_agimon_ai_po_vault.PO_VAULT_CONTRACT));
3854
+ const runtime = createMcpServerRuntime(context?.agent?.context?.environment, context?.host.context.workspaceRoot, () => resolver, publishFile, () => appHost?.assertActive("@agimon-ai/po-mcp"), () => serverScope?.resolve(_agimon_ai_po_vault.PO_VAULT_CONTRACT), () => context && (0, _agimon_ai_po_core_platform.readPoFs)(context.context));
3791
3855
  const generation = `${context?.agent?.context?.sessionId ?? crypto.randomUUID()}:mcp-server`;
3792
3856
  const { session } = runtime;
3793
3857
  const tools = [...runtime.tools, ...createFileTransferTools(context)];
3794
3858
  const apps = createMcpAppsService(runtime.sessionTools, () => appHost, context?.signal);
3795
3859
  const namespace = createMcpNamespace(runtime.sessionTools, hostContext?.sessionId);
3796
3860
  const mountSession = (cordis) => {
3797
- cordis.inject([_agimon_ai_po_core_serverPlugin.PO_SERVER_SCOPE_SERVICE], (scoped) => {
3861
+ cordis.inject([_agimon_ai_po_core_serverPlugin.PO_SERVER_SCOPE_SERVICE], async (scoped) => {
3798
3862
  serverScope = (0, _agimon_ai_po_core_serverPlugin.requirePoServerScope)(scoped);
3799
- return () => {
3863
+ const withdraw = await serverScope.provide(_agimon_ai_po_core_mcp.PO_MCP_CONTRACT, runtime.mcp);
3864
+ return async () => {
3800
3865
  serverScope = void 0;
3866
+ const closing = runtime.dispose();
3867
+ try {
3868
+ await withdraw();
3869
+ } finally {
3870
+ await closing;
3871
+ }
3801
3872
  };
3802
3873
  });
3803
3874
  cordis.inject([_agimon_ai_po_core_codemode.PO_CODEMODE_SERVICE], (scoped) => {
@@ -3888,7 +3959,8 @@ const createMcpServerRoot = (context) => {
3888
3959
  provider.provide(MCP_SESSION_TOOLS_SERVICE, runtime.sessionTools);
3889
3960
  provider.provide(_agimon_ai_po_core_childSession.PO_CHILD_SESSION_MCP_TOOL_SERVICE, runtime.childTool);
3890
3961
  provider.provide(require_sessionServers.PO_MCP_LOCAL_SERVERS_SERVICE, runtime.localServers);
3891
- return () => runtime.sessionTools.dispose();
3962
+ provider.provide(require_sessionServers.PO_MCP_SESSION_SERVERS_SERVICE, runtime.sessionServers);
3963
+ return () => runtime.dispose();
3892
3964
  });
3893
3965
  };
3894
3966
  return {
@@ -3898,7 +3970,13 @@ const createMcpServerRoot = (context) => {
3898
3970
  },
3899
3971
  activities: runtime.activities,
3900
3972
  services: [mountMcpHeadlessTools(tools), mountSession],
3901
- onDispose: apps.dispose
3973
+ onDispose: async () => {
3974
+ try {
3975
+ await runtime.dispose();
3976
+ } finally {
3977
+ apps.dispose();
3978
+ }
3979
+ }
3902
3980
  };
3903
3981
  };
3904
3982
  //#endregion