@cjhyy/code-shell-core 0.9.5 → 0.9.7

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 (89) hide show
  1. package/dist/automation/scheduler.d.ts +3 -0
  2. package/dist/automation/scheduler.js +21 -0
  3. package/dist/context/manager.d.ts +8 -2
  4. package/dist/context/manager.js +20 -4
  5. package/dist/context/notes.d.ts +39 -0
  6. package/dist/context/notes.js +314 -0
  7. package/dist/credentials/access.d.ts +9 -1
  8. package/dist/credentials/access.js +15 -4
  9. package/dist/credentials/store.d.ts +11 -0
  10. package/dist/credentials/store.js +44 -9
  11. package/dist/credentials/types.d.ts +4 -0
  12. package/dist/credentials/types.js +4 -0
  13. package/dist/credentials/use-credential-tool.js +12 -2
  14. package/dist/engine/engine-workspace-authority.js +10 -3
  15. package/dist/engine/engine.d.ts +8 -4
  16. package/dist/engine/engine.js +115 -15
  17. package/dist/engine/prompt-cache-diagnostics.js +10 -1
  18. package/dist/engine/run-goal.js +7 -3
  19. package/dist/engine/run-tooling.d.ts +3 -0
  20. package/dist/engine/run-tooling.js +25 -23
  21. package/dist/engine/run-types.d.ts +20 -0
  22. package/dist/engine/run-workspace.js +5 -21
  23. package/dist/engine/subagent-spawner.d.ts +3 -0
  24. package/dist/engine/subagent-spawner.js +48 -17
  25. package/dist/engine/turn-loop.d.ts +14 -4
  26. package/dist/engine/turn-loop.js +120 -28
  27. package/dist/engine/types.d.ts +19 -0
  28. package/dist/index.d.ts +4 -4
  29. package/dist/index.js +2 -2
  30. package/dist/links/index.d.ts +1 -0
  31. package/dist/links/index.js +1 -0
  32. package/dist/links/link-action-tool.d.ts +2 -1
  33. package/dist/links/link-action-tool.js +80 -44
  34. package/dist/links/status.d.ts +53 -0
  35. package/dist/links/status.js +175 -0
  36. package/dist/llm/prompt-cache.d.ts +35 -3
  37. package/dist/llm/prompt-cache.js +63 -3
  38. package/dist/llm/providers/openai.d.ts +3 -0
  39. package/dist/llm/providers/openai.js +57 -14
  40. package/dist/prompt/section-loader.js +1 -0
  41. package/dist/prompt/sections/browser.md +4 -2
  42. package/dist/prompt/sections/context-notes.md +9 -0
  43. package/dist/protocol/background-result-wakeup.d.ts +8 -1
  44. package/dist/protocol/background-result-wakeup.js +76 -38
  45. package/dist/protocol/chat-session-manager.d.ts +7 -1
  46. package/dist/protocol/chat-session-manager.js +44 -8
  47. package/dist/protocol/chat-session.d.ts +2 -0
  48. package/dist/protocol/chat-session.js +4 -1
  49. package/dist/protocol/server.d.ts +4 -0
  50. package/dist/protocol/server.js +355 -62
  51. package/dist/protocol/session-message-result.d.ts +12 -0
  52. package/dist/protocol/session-message-result.js +42 -0
  53. package/dist/protocol/session-message-workspace.d.ts +21 -0
  54. package/dist/protocol/session-message-workspace.js +57 -0
  55. package/dist/protocol/types.d.ts +4 -0
  56. package/dist/session/session-manager.js +8 -7
  57. package/dist/session/session-message.d.ts +17 -2
  58. package/dist/session/transcript.d.ts +17 -0
  59. package/dist/session/transcript.js +271 -16
  60. package/dist/settings/schema.d.ts +9 -0
  61. package/dist/settings/schema.js +4 -0
  62. package/dist/themes/paths.js +20 -1
  63. package/dist/tool-system/browser-bridge.d.ts +21 -1
  64. package/dist/tool-system/browser-discovery.d.ts +6 -0
  65. package/dist/tool-system/browser-discovery.js +17 -0
  66. package/dist/tool-system/builtin/agent.js +23 -9
  67. package/dist/tool-system/builtin/browser-tools.js +30 -9
  68. package/dist/tool-system/builtin/context-notes.d.ts +12 -0
  69. package/dist/tool-system/builtin/context-notes.js +188 -0
  70. package/dist/tool-system/builtin/index.js +50 -3
  71. package/dist/tool-system/builtin/mcp-tools.d.ts +5 -3
  72. package/dist/tool-system/builtin/mcp-tools.js +10 -10
  73. package/dist/tool-system/builtin/send-message-to-session.js +19 -3
  74. package/dist/tool-system/builtin/tool-search.js +15 -3
  75. package/dist/tool-system/context.d.ts +9 -0
  76. package/dist/tool-system/executor.js +5 -3
  77. package/dist/tool-system/mcp-compat.d.ts +3 -0
  78. package/dist/tool-system/mcp-compat.js +51 -0
  79. package/dist/tool-system/mcp-manager.d.ts +27 -26
  80. package/dist/tool-system/mcp-manager.js +273 -111
  81. package/dist/tool-system/mcp-workspace.d.ts +18 -0
  82. package/dist/tool-system/mcp-workspace.js +56 -0
  83. package/dist/tool-system/permission.d.ts +6 -0
  84. package/dist/tool-system/permission.js +45 -9
  85. package/dist/tool-system/plan-mode-allowlist.js +5 -0
  86. package/dist/tool-system/sandbox/seatbelt.js +71 -2
  87. package/dist/tool-system/session-tool-host.js +9 -1
  88. package/dist/types.d.ts +4 -2
  89. package/package.json +1 -1
@@ -24,7 +24,7 @@ export const mcpToolDef = {
24
24
  required: ["server", "tool"],
25
25
  },
26
26
  };
27
- export async function mcpToolExecute(args) {
27
+ export async function mcpToolExecute(args, ctx) {
28
28
  const server = args.server;
29
29
  const tool = args.tool;
30
30
  const toolArgs = args.arguments ?? {};
@@ -33,12 +33,12 @@ export async function mcpToolExecute(args) {
33
33
  const signal = args.__signal;
34
34
  try {
35
35
  const { MCPManager } = await import("../mcp-manager.js");
36
- const manager = MCPManager.getInstance();
37
- const result = await manager.callTool(server, tool, toolArgs, signal);
36
+ const manager = MCPManager.forContext(ctx);
37
+ const result = await manager.callTool(server, tool, toolArgs, signal, ctx);
38
38
  return typeof result === "string" ? result : JSON.stringify(result, null, 2);
39
39
  }
40
40
  catch (err) {
41
- return `MCP tool error: ${err.message}`;
41
+ return { ok: false, error: `MCP tool error: ${err.message}` };
42
42
  }
43
43
  }
44
44
  // ─── ListMcpResources — list available MCP resources ────────────
@@ -55,7 +55,7 @@ export const listMcpResourcesToolDef = {
55
55
  },
56
56
  },
57
57
  };
58
- export async function listMcpResourcesTool(args) {
58
+ export async function listMcpResourcesTool(args, ctx) {
59
59
  const server = args.server ?? "";
60
60
  // The executor injects the session's allowed-server set (see executor.ts).
61
61
  // When no explicit server filter is given, we must only enumerate resources
@@ -64,11 +64,11 @@ export async function listMcpResourcesTool(args) {
64
64
  const allowed = args.__allowedMcpServers;
65
65
  try {
66
66
  const { MCPManager } = await import("../mcp-manager.js");
67
- const manager = MCPManager.getInstance();
67
+ const manager = MCPManager.forContext(ctx);
68
68
  // Forward the run's abort signal (registry injects __signal) so Stop cancels
69
69
  // promptly instead of waiting out the SDK's default request timeout.
70
70
  const signal = args.__signal;
71
- let resources = await manager.listResources(server || undefined, signal);
71
+ let resources = await manager.listResources(server || undefined, signal, ctx);
72
72
  if (allowed && resources) {
73
73
  resources = resources.filter((r) => {
74
74
  // Resource entries may carry the owning server on `serverName`/`server`;
@@ -106,14 +106,14 @@ export const readMcpResourceToolDef = {
106
106
  required: ["server", "uri"],
107
107
  },
108
108
  };
109
- export async function readMcpResourceTool(args) {
109
+ export async function readMcpResourceTool(args, ctx) {
110
110
  const server = args.server;
111
111
  const uri = args.uri;
112
112
  try {
113
113
  const { MCPManager } = await import("../mcp-manager.js");
114
- const manager = MCPManager.getInstance();
114
+ const manager = MCPManager.forContext(ctx);
115
115
  const signal = args.__signal;
116
- const content = await manager.readResource(server, uri, signal);
116
+ const content = await manager.readResource(server, uri, signal, ctx);
117
117
  return typeof content === "string" ? content : JSON.stringify(content, null, 2);
118
118
  }
119
119
  catch (err) {
@@ -3,7 +3,9 @@ export const sendMessageToSessionToolDef = {
3
3
  name: SEND_MESSAGE_TO_SESSION_TOOL_NAME,
4
4
  description: "Send a message to another host-authorized Session in the current project. " +
5
5
  "Use this exactly like a person sending a message in that Session: the message becomes the target Session's next user turn and queues or starts its work. " +
6
- "When you have later additions, call this tool again with another message. The call creates no persistent relationship or automatic subscription.",
6
+ "The result reports whether this turn is queued, started, or already completed. " +
7
+ "For queued or started turns, that turn's answer or failure is returned to this Session automatically; do not poll by sending the task again. " +
8
+ "When you have later additions, call this tool again with another message. This does not subscribe to unrelated future target turns.",
7
9
  inputSchema: {
8
10
  type: "object",
9
11
  properties: {
@@ -54,8 +56,22 @@ export async function sendMessageToSessionTool(args, ctx) {
54
56
  if (message.length > 48_000)
55
57
  return "Error: message exceeds 48000 characters.";
56
58
  try {
57
- const target = await service.send({ targetSessionId, message });
58
- return `Message sent to "${target.title}" (${target.sessionId}); its Session has queued the turn.`;
59
+ const target = await service.send({
60
+ targetSessionId,
61
+ message,
62
+ ...(ctx?.signal ? { signal: ctx.signal } : {}),
63
+ });
64
+ const receipt = target.receipt;
65
+ const label = `"${target.title}" (${target.sessionId})`;
66
+ if (!receipt) {
67
+ // Compatibility with custom hosts that implement the original router.
68
+ return `Message accepted by ${label}. This host did not provide execution status or automatic reply delivery.`;
69
+ }
70
+ if (receipt.status === "completed") {
71
+ return `Message ${receipt.messageId} completed in ${label}.\n\n${receipt.result?.text ?? ""}`;
72
+ }
73
+ const status = receipt.status === "started" ? "started" : "queued (not yet confirmed started)";
74
+ return `Message ${receipt.messageId} accepted by ${label}; status: ${status}. This turn's answer or failure will be returned to this Session automatically.`;
59
75
  }
60
76
  catch (error) {
61
77
  return `Error: ${error instanceof Error ? error.message : String(error)}`;
@@ -6,6 +6,8 @@
6
6
  * saving context by not loading all MCP tool schemas upfront.
7
7
  */
8
8
  import { isRegisteredMcpToolAllowed } from "../mcp-tool-policy.js";
9
+ import { browserDiscoveryScore, isBuiltinBrowserTool } from "../browser-discovery.js";
10
+ import { PLAN_MODE_ALLOWED_TOOLS } from "../plan-mode-allowlist.js";
9
11
  export const toolSearchToolDef = {
10
12
  name: "ToolSearch",
11
13
  description: "Search only the tools available in the current Session context by name or keyword. " +
@@ -59,8 +61,18 @@ export async function toolSearchTool(args, ctx) {
59
61
  // its server is in this session's allowedMcpServers. Undefined set = no
60
62
  // gating (sub-agents / hosts that don't populate it).
61
63
  const visible = (tool) => {
62
- if (tool.source !== "mcp")
63
- return true;
64
+ if (ctx.disabledBuiltins?.has(tool.name))
65
+ return false;
66
+ if (ctx.allowedToolNames && !ctx.allowedToolNames.has(tool.name))
67
+ return false;
68
+ if (ctx.planMode && !PLAN_MODE_ALLOWED_TOOLS.has(tool.name))
69
+ return false;
70
+ if (tool.source !== "mcp") {
71
+ if (isBuiltinBrowserTool(tool) && !ctx.browser)
72
+ return false;
73
+ const guard = ctx.toolRegistry.getAvailabilityGuard(tool.name);
74
+ return !guard || !ctx.toolVisibility || guard(ctx.toolVisibility);
75
+ }
64
76
  const allowed = ctx.allowedMcpServers;
65
77
  return ((!allowed || allowed.has(tool.serverName ?? "")) &&
66
78
  isRegisteredMcpToolAllowed(tool, ctx.mcpToolPolicies));
@@ -124,7 +136,7 @@ function searchDetailedTools(allTools, query, maxResults) {
124
136
  const keywords = queryLower.split(/\s+/);
125
137
  // Score each tool
126
138
  const scored = allTools.map((tool) => {
127
- let score = 0;
139
+ let score = browserDiscoveryScore(tool, query);
128
140
  const nameLower = tool.name.toLowerCase();
129
141
  const descLower = tool.description.toLowerCase();
130
142
  for (const kw of keywords) {
@@ -23,6 +23,7 @@ import type { SessionWorkspace } from "../types.js";
23
23
  import type { ApprovalRouter } from "./permission.js";
24
24
  import type { ChildWriterLease, LiveChildControl } from "./builtin/agent-registry.js";
25
25
  import type { McpToolPolicy } from "./mcp-tool-policy.js";
26
+ import type { SessionContextNotes } from "../context/notes.js";
26
27
  /**
27
28
  * Narrow view of the owning Engine that tools are allowed to call back into.
28
29
  * Defined here (in the low-level tool-system) rather than importing the
@@ -189,12 +190,16 @@ export interface SubAgentSpawnResult {
189
190
  */
190
191
  export interface ToolVisibilityContext {
191
192
  cwd: string;
193
+ /** Resolved native context strategy; omitted for external runtimes. */
194
+ contextStrategy?: "summary" | "notes";
192
195
  workspace?: import("../workspace/workspace-context.js").WorkspaceContext;
193
196
  hasGoal: boolean;
194
197
  /** Resolved Session identity for per-session extension-tool visibility. */
195
198
  sessionId?: string;
196
199
  settingsScope?: import("../settings/manager.js").SettingsScope;
197
200
  host?: string;
201
+ /** A browser bridge is wired for this run, independent of the host's name. */
202
+ hasBrowserAutomation?: boolean;
198
203
  isSubAgent?: boolean;
199
204
  behaviorProfile?: string;
200
205
  /** Host-authorized targets available to the cross-Session messaging builtin. */
@@ -231,6 +236,10 @@ export interface ToolRunYieldController {
231
236
  export interface ToolContext {
232
237
  /** Active working directory for this Engine. */
233
238
  cwd: string;
239
+ /** Resolved strategy for the current session's model context. */
240
+ contextStrategy?: "summary" | "notes";
241
+ /** Session-local working notes and history; never a cross-session memory store. */
242
+ contextNotes?: Pick<SessionContextNotes, "save" | "requestRollover" | "search" | "read">;
234
243
  /**
235
244
  * True when this call belongs to an external Agent Runtime rather than the
236
245
  * native Engine loop.
@@ -409,14 +409,16 @@ export class ToolExecutor {
409
409
  }
410
410
  if (decision === "ask") {
411
411
  const reason = permissionAskReason(hookResult.decision === "ask" ? hookResult.messages : undefined, permHook.decision === "ask" ? permHook.messages : undefined);
412
- const approved = await this.permission.handleAsk(call.toolName, call.args, reason, {
412
+ const approval = await this.permission.handleAskResult(call.toolName, call.args, reason, {
413
413
  sessionId: this.toolCtx?.sessionId,
414
414
  });
415
- if (!approved) {
415
+ if (!approval.approved) {
416
416
  return {
417
417
  id: call.id,
418
418
  toolName: call.toolName,
419
- error: `Permission denied by user for tool: ${call.toolName}`,
419
+ error: approval.failure && approval.failure !== "denied"
420
+ ? `Permission approval ${approval.failure} for tool: ${call.toolName}${approval.reason ? `. ${approval.reason}` : ""}`
421
+ : `Permission denied by user for tool: ${call.toolName}${approval.reason ? `. ${approval.reason}` : ""}`,
420
422
  isError: true,
421
423
  };
422
424
  }
@@ -0,0 +1,3 @@
1
+ import type { Tool as McpTool } from "@modelcontextprotocol/sdk/types.js";
2
+ export declare function adaptMcpToolSchema(implementation: string | undefined, tool: McpTool): McpTool["inputSchema"];
3
+ export declare function normalizeMcpToolArgs(implementation: string | undefined, tool: McpTool | undefined, args: Record<string, unknown>): Record<string, unknown>;
@@ -0,0 +1,51 @@
1
+ /** Compatibility for Chrome DevTools' optional output/context selectors.
2
+ * A blank selector is not an output filename or an intentional isolated context.
3
+ * Match the server implementation AND its declared tool shape; an unrelated
4
+ * tool's empty text, input path, or required parameter must remain untouched. */
5
+ function optionalChromeSelectors(implementation, tool) {
6
+ if (implementation !== "chrome_devtools")
7
+ return [];
8
+ const properties = tool.inputSchema.properties;
9
+ const required = new Set(tool.inputSchema.required ?? []);
10
+ if (!properties)
11
+ return [];
12
+ const expected = {
13
+ take_snapshot: { selectors: ["filePath"], signature: { verbose: "boolean" } },
14
+ take_screenshot: { selectors: ["filePath"], signature: { format: "string" } },
15
+ evaluate_script: { selectors: ["filePath"], signature: { function: "string" } },
16
+ get_network_request: {
17
+ selectors: ["requestFilePath", "responseFilePath"],
18
+ signature: { reqid: "number" },
19
+ },
20
+ new_page: { selectors: ["isolatedContext"], signature: { url: "string" } },
21
+ };
22
+ const contract = expected[tool.name];
23
+ if (!contract ||
24
+ Object.entries(contract.signature).some(([key, type]) => properties[key]?.type !== type))
25
+ return [];
26
+ return contract.selectors.filter((key) => properties[key]?.type === "string" && !required.has(key));
27
+ }
28
+ export function adaptMcpToolSchema(implementation, tool) {
29
+ const selectors = optionalChromeSelectors(implementation, tool);
30
+ if (!selectors.length)
31
+ return tool.inputSchema;
32
+ const properties = { ...tool.inputSchema.properties };
33
+ for (const key of selectors) {
34
+ const property = properties[key];
35
+ properties[key] = {
36
+ ...property,
37
+ minLength: Math.max(typeof property.minLength === "number" ? property.minLength : 0, 1),
38
+ description: `${property.description ?? ""} Omit this optional field when unused; do not send an empty string.`,
39
+ };
40
+ }
41
+ return { ...tool.inputSchema, properties };
42
+ }
43
+ export function normalizeMcpToolArgs(implementation, tool, args) {
44
+ const normalized = { ...args };
45
+ if (tool)
46
+ for (const key of optionalChromeSelectors(implementation, tool)) {
47
+ if (normalized[key] === "")
48
+ delete normalized[key];
49
+ }
50
+ return normalized;
51
+ }
@@ -8,6 +8,8 @@ import type { MCPServerConfig, RegisteredTool } from "../types.js";
8
8
  import type { CredentialType } from "../credentials/types.js";
9
9
  import { ToolRegistry } from "./registry.js";
10
10
  import { type CredentialAccess } from "../credentials/access.js";
11
+ import { type McpWorkspaceScope } from "./mcp-workspace.js";
12
+ export type { McpWorkspaceScope } from "./mcp-workspace.js";
11
13
  interface MCPResourceInfo {
12
14
  uri: string;
13
15
  name: string;
@@ -78,7 +80,7 @@ export declare function spillMcpImage(serverName: string, toolName: string, base
78
80
  }): Promise<string>;
79
81
  export declare function wrapMcpOutput(serverName: string, toolName: string, body: string): string;
80
82
  export declare function stripInternalToolArgs(args: Record<string, unknown>): Record<string, unknown>;
81
- export declare function buildRegisteredTool(serverName: string, tool: McpTool): RegisteredTool;
83
+ export declare function buildRegisteredTool(serverName: string, tool: McpTool, implementation?: string): RegisteredTool;
82
84
  /**
83
85
  * Per-server outcome of a connectAll() sweep (see the optional onServerEvent
84
86
  * parameter). The engine forwards these onto the `notification` hook so hosts
@@ -95,26 +97,21 @@ export declare class MCPManager {
95
97
  private connections;
96
98
  private registeredToolsByServer;
97
99
  private desiredServerNames;
98
- /**
99
- * In-flight connect()s keyed by server name. When the broadcast config
100
- * reload (server.ts forEachSession → every session's refreshRuntimeConfig)
101
- * calls connectAll for the SAME `added` server on this ONE shared pool, K
102
- * concurrent connect(name) calls would each start a fresh handshake because
103
- * `connections.has(name)` only becomes true AFTER the handshake completes —
104
- * a thundering herd of duplicate connections racing to set(). Coalescing by
105
- * name here collapses them to a SINGLE underlying connection; the late
106
- * callers await the same promise and return. Cleared in finally so a failed
107
- * connect can be retried later.
108
- */
100
+ /** Concurrent handshakes share only an identical server + cwd + root scope. */
109
101
  private connecting;
110
102
  /** Per-owner (engine) desired server sets — see reconcile()'s shared-pool note. */
111
103
  private desiredByOwner;
104
+ private scopeByOwner;
105
+ private connectionKeysByOwner;
106
+ private connectionGeneration;
112
107
  constructor(toolRegistry: ToolRegistry);
113
108
  static getInstance(): MCPManager;
109
+ /** Resolve generic MCP builtins through the current run, never another pool. */
110
+ static forContext(workspace?: McpWorkspaceScope): MCPManager;
114
111
  /**
115
112
  * Connect to all configured MCP servers and register their tools.
116
113
  */
117
- connectAll(servers: Record<string, MCPServerConfig>, owner?: unknown, onServerEvent?: (event: McpServerLifecycleEvent) => void): Promise<void>;
114
+ connectAll(servers: Record<string, MCPServerConfig>, owner?: unknown, onServerEvent?: (event: McpServerLifecycleEvent) => void, workspace?: McpWorkspaceScope): Promise<void>;
118
115
  reconcile(servers: Record<string, MCPServerConfig>, owner?: unknown): Promise<void>;
119
116
  /**
120
117
  * Remove one owner from the shared desired-server pool and disconnect servers
@@ -123,48 +120,52 @@ export declare class MCPManager {
123
120
  * worker shutdown.
124
121
  */
125
122
  unregisterOwner(owner: unknown): Promise<void>;
123
+ private pruneUnusedScopedConnections;
124
+ private managedConnectionKeys;
126
125
  private enabledServerNames;
127
126
  /** Union of every registered owner's desired set; null when none registered. */
128
127
  private unionDesired;
129
128
  /**
130
129
  * Connect to a single MCP server.
131
130
  *
132
- * Coalesces concurrent calls for the same `name`: an already-connected server
133
- * returns immediately, and a connect already in flight for this name is
134
- * awaited rather than restarted (#5 — thundering-herd guard on the shared
135
- * pool). The actual handshake lives in `performConnect`.
131
+ * Calls for the same server and canonical workspace scope share one pending
132
+ * handshake. Other workspace scopes always get their own transport.
136
133
  */
137
- connect(name: string, config: MCPServerConfig): Promise<void>;
134
+ connect(name: string, config: MCPServerConfig, workspace?: McpWorkspaceScope): Promise<void>;
138
135
  /**
139
136
  * Perform the actual handshake + tool discovery for one server. Separated
140
137
  * from `connect` so the coalescing/dedup logic stays in one place. Override
141
138
  * `connect` (not this) in test doubles that want to count handshakes.
142
139
  */
143
- protected performConnect(name: string, config: MCPServerConfig): Promise<void>;
140
+ protected performConnect(name: string, config: MCPServerConfig, workspace?: McpWorkspaceScope): Promise<void>;
144
141
  /**
145
142
  * Discover tools from an MCP server and register them.
146
143
  */
147
144
  private discoverTools;
145
+ private scopeForContext;
146
+ private findConnection;
147
+ private connectionForScope;
148
+ /** Refresh an engine's fork after pool discovery; retain all non-MCP tools. */
149
+ syncToolsToRegistry(registry: ToolRegistry, workspace?: McpWorkspaceScope, allowedServers?: ReadonlySet<string>): void;
150
+ private executeRegisteredTool;
148
151
  /**
149
152
  * Disconnect all MCP servers.
150
153
  */
151
154
  disconnectAll(): Promise<void>;
152
155
  disconnect(name: string): Promise<void>;
153
- /**
154
- * List connected servers.
155
- */
156
+ private disconnectConnection;
157
+ /** Names remain stable even when several isolated workspace transports exist. */
156
158
  listServers(): string[];
157
159
  /**
158
160
  * Call a tool on a specific MCP server.
159
161
  */
160
- callTool(serverName: string, toolName: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<unknown>;
162
+ callTool(serverName: string, toolName: string, args: Record<string, unknown>, signal?: AbortSignal, workspace?: McpWorkspaceScope): Promise<unknown>;
161
163
  /**
162
164
  * List resources from MCP servers.
163
165
  */
164
- listResources(serverName?: string, signal?: AbortSignal): Promise<MCPResourceInfo[]>;
166
+ listResources(serverName?: string, signal?: AbortSignal, workspace?: McpWorkspaceScope): Promise<MCPResourceInfo[]>;
165
167
  /**
166
168
  * Read a resource from an MCP server.
167
169
  */
168
- readResource(serverName: string, uri: string, signal?: AbortSignal): Promise<string>;
170
+ readResource(serverName: string, uri: string, signal?: AbortSignal, workspace?: McpWorkspaceScope): Promise<string>;
169
171
  }
170
- export {};