You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Feature Request: mutate the active tool list on a live session (SDK re-triage of #735)
Refiling per @patniko's invitation in #735 — the original closing comment specifically asked for fresh reproduction details from a current SDK user, and this is exactly that.
Problem
CopilotSession today takes its custom tool list once at creation (client.createSession({ tools })) and again at client.resumeSession({ tools }). There is no supported way to mutate the active tool list on a live session without terminating conversation state at the SDK layer.
This blocks a well-defined UX pattern that MCP-integrating hosts consistently hit: slow-auth MCP servers that connect after session creation.
Concrete production repro
Host: obsidian-copilot-agent — an Obsidian community plugin embedding Copilot Agent, shipped v0.8.0.
Scenario (verified end-to-end):
User opens Obsidian → plugin loads → the plugin's ConversationManager creates a CopilotSession for the active conversation. Tool list at this point = built-ins + already-connected MCP servers only.
User has an MCP server configured that uses Device Flow / OAuth (Microsoft Graph via WorkIQ is the concrete case, but any slow-auth server exhibits this). This server has not finished authenticating yet.
10–90 seconds later, the MCP server completes auth and connects. The plugin's McpManager fires a connect notification. New tools are discovered.
Expected: the user, mid-conversation, can ask the assistant to use the newly available tools.
Actual: the assistant reports it has no such tools. The tool list frozen at createSession(...) time is still what the CLI/model sees.
Only workaround: reload the plugin (loses the conversation) or switch conversations away and back (metadata-only conversations pick up the fresh tool list on their next createSession(...), at the cost of a session recreation).
Same pattern shows up with:
MCP servers that restart / crashloop (their tools should drop out for the duration).
MCP servers added post-hoc via the settings UI while a conversation is open.
Tool-schema changes on an already-connected server (session.tools_updated fires but the plugin has no way to act on it).
Related prior issues
#735 — setActiveTools() — filter visible tools without session teardown. Same underlying feature; closed as backlog trim, invited re-file.
#861 / #869 — MCP tool naming issues that hosts already work around, but the underlying wiring is the same code path a live-update method would touch.
What we already did to isolate the SDK gap
To be sure this is an SDK gap and not a host bug, obsidian-copilot-agent v0.8.0 landed a full readiness/refresh flow inside the plugin:
Watches McpManager state transitions with per-server 5s coalescing (proposal 0003 in-repo).
Attempts to refresh the live session's tools via a feature-detect: typeof session.updateTools === "function". With SDK 1.0.0 this always returns false, so we log a strict no-op (FR-011 in our spec) and surface a "server connected" toast only when we can actually act.
Surfaces an inline chat composer readiness pill so users at least know MCP is still coming up.
We deliberately did not attempt resumeSession(...) as a workaround because:
It creates a fresh session object; every event subscription (session.on, session.onPermissionRequest, canvas handlers, elicitation, tool handlers, hooks) has to be reattached. This is exactly the fragility Feature Request: session.setActiveTools() — filter visible tools without session teardown #735 warned about — the Node SDK exhibits the same class of issue as the Python SDK originally reported, just with different specifics.
There is no documented guarantee that resumeSession(sessionId, { tools }) preserves in-flight turn state or event ordering if called during sendAndWait.
Even at idle, doing a whole-object swap on every MCP transition is a lot of blast radius for what should be an in-place mutation.
So we hit the wall and shipped behind the no-op fallback.
Requested API
Not prescriptive on shape — a maintainer decision — but a minimum viable surface would be one of:
Filters previously registered tools by name for the next-turn context window. Simple, low-blast-radius, but requires the caller to register the full palette up front.
Option B (mirrors the existing setModel pattern for mid-session mutation):
Replaces the declared list wholesale. More flexible for MCP integration where the tool set genuinely changes (server connect adds new tool names, not just a filter over a pre-known palette).
For MCP-integrating hosts, B is strictly more useful because we don't know the tool names ahead of time — they come from the MCP server's tools/list response, which the CLI executes internally.
Semantics we would rely on (for either option)
Effect timing: next user turn onward. In-flight turn's tool declarations are frozen — mid-stream calls do not affect them. This matches the plugin's existing turn-boundary latch and is the least-surprising behavior for the model.
Ordering under concurrency: last-committed wins. Callers cannot reasonably serialize; the host already has to deal with rapid MCP flapping.
Disconnected session: rejects with a documented error type. Do not silently no-op — hosts need to distinguish "SDK doesn't support this" from "session is dead".
Conversation state: preserved (history, canvases, permission handlers, event subscribers). This is the entire point vs. resumeSession.
Handler registration (Option B only): tool handlers registered via defineTool and passed in the new list should be dispatched by name on subsequent turns.
Contribution offer
Happy to author the Node SDK side of the PR once the API shape is decided — the plugin-side integration is already coded behind a feature detect, so adoption is a version bump + swap-in.
Environment
@github/copilot-sdk@1.0.0 (Node)
Obsidian community plugin, Electron renderer process, requestUrl-routed MCP HTTP
Feature Request: mutate the active tool list on a live session (SDK re-triage of #735)
Refiling per @patniko's invitation in #735 — the original closing comment specifically asked for fresh reproduction details from a current SDK user, and this is exactly that.
Problem
CopilotSessiontoday takes its custom tool list once at creation (client.createSession({ tools })) and again atclient.resumeSession({ tools }). There is no supported way to mutate the active tool list on a live session without terminating conversation state at the SDK layer.This blocks a well-defined UX pattern that MCP-integrating hosts consistently hit: slow-auth MCP servers that connect after session creation.
Concrete production repro
Host:
obsidian-copilot-agent— an Obsidian community plugin embedding Copilot Agent, shipped v0.8.0.Scenario (verified end-to-end):
ConversationManagercreates aCopilotSessionfor the active conversation. Tool list at this point = built-ins + already-connected MCP servers only.McpManagerfires a connect notification. New tools are discovered.createSession(...)time is still what the CLI/model sees.createSession(...), at the cost of a session recreation).Same pattern shows up with:
session.tools_updatedfires but the plugin has no way to act on it).Related prior issues
What we already did to isolate the SDK gap
To be sure this is an SDK gap and not a host bug,
obsidian-copilot-agentv0.8.0 landed a full readiness/refresh flow inside the plugin:McpManagerstate transitions with per-server 5s coalescing (proposal 0003 in-repo).typeof session.updateTools === "function". With SDK1.0.0this always returns false, so we log a strict no-op (FR-011 in our spec) and surface a "server connected" toast only when we can actually act.We deliberately did not attempt
resumeSession(...)as a workaround because:session.on,session.onPermissionRequest, canvas handlers, elicitation, tool handlers, hooks) has to be reattached. This is exactly the fragility Feature Request: session.setActiveTools() — filter visible tools without session teardown #735 warned about — the Node SDK exhibits the same class of issue as the Python SDK originally reported, just with different specifics.resumeSession(sessionId, { tools })preserves in-flight turn state or event ordering if called duringsendAndWait.So we hit the wall and shipped behind the no-op fallback.
Requested API
Not prescriptive on shape — a maintainer decision — but a minimum viable surface would be one of:
Option A (mirrors #735 as originally proposed):
Filters previously registered tools by name for the next-turn context window. Simple, low-blast-radius, but requires the caller to register the full palette up front.
Option B (mirrors the existing
setModelpattern for mid-session mutation):Replaces the declared list wholesale. More flexible for MCP integration where the tool set genuinely changes (server connect adds new tool names, not just a filter over a pre-known palette).
For MCP-integrating hosts, B is strictly more useful because we don't know the tool names ahead of time — they come from the MCP server's
tools/listresponse, which the CLI executes internally.Semantics we would rely on (for either option)
resumeSession.defineTooland passed in the new list should be dispatched by name on subsequent turns.Contribution offer
Happy to author the Node SDK side of the PR once the API shape is decided — the plugin-side integration is already coded behind a feature detect, so adoption is a version bump + swap-in.
Environment
@github/copilot-sdk@1.0.0(Node)requestUrl-routed MCP HTTP/cc @patniko (per #735 close-comment invitation)