github / github/copilot-cli

Extension SDK: Allow mid-turn tool list rebuild after MCP enable/disable

Open
#3,577 0 comments 0 reactions 0 assignees View on GitHub
area:mcp area:plugins
Dominant language
Shell
Stars
11.2k
Forks
1.9k
Avg merge
14h 16m
Merged PRs (30d)
6

Description

### Describe the feature or problem you'd like to solve

When an extension calls rpc.mcp.enable() mid-turn, the MCP server connects successfully (confirmed via mcp_server_status_changed events), but its tools don't appear in the LLM's tool list until tools_changed_notice fires at the next turn. session.rpc.tools.initializeAndValidate() is callable from joinSession() extensions but is a no-op (returns {} instantly). There is no way for an extension to force the runtime to rebuild the LLM's active tool list mid-turn. Tested with 3 MCP servers (mail, workiq, s360-breeze) — none had tools available same-turn.

### Proposed solution

Expose an API that lets extensions trigger a mid-turn tool list rebuild. Options:

1. `session.rpc.tools.rebuild()` — new method that forces the runtime to rebuild and inject the tool list mid-turn
2. Make `initializeAndValidate()` functional for extension sessions via `joinSession()` (currently a no-op)
3. Allow extensions to programmatically trigger `tools_changed_notice` mid-turn

This would benefit any extension that dynamically loads/unloads MCP servers for token optimization. Currently users must waste a turn after every MCP load, degrading the experience.

Diagnostic evidence and test methodology: https://github.com/gacurtin_microsoft/constellation/issues/4

### Example prompts or workflows

1. User: "Check my S360 compliance" → Extension loads s360-breeze MCP → Extension calls tools.rebuild() → LLM immediately calls s360-breeze tools — all in one turn

2. User: "Switch to comms profile" → Extension enables teams + mail MCPs, disables others → calls tools.rebuild() once → LLM sees all new tools immediately

3. User: "Search my email for the budget report" → Extension loads mail MCP on demand → rebuild → LLM calls mail-SearchMessages — no wasted turn

Use case: Constellation (https://github.com/lowdrag84/constellation) — profile-based MCP manager saving 16K-33K tokens/turn by only loading needed MCPs. Everything works except this one-turn delay.

### Additional context

## Diagnostic Evidence

APIs tested from extension via joinSession():

| API | Status |
|-----|--------|
| session.rpc.tools.initializeAndValidate() | Callable but no-op — returns {} in ~29ms |
| session.rpc.tools (full namespace) | Only has: handlePendingToolCall, initializeAndValidate |
| session.on('mcp_server_status_changed') | Works — events fire with "connected" status |
| session.rpc.mcp.list() | Works — returns {servers: [...]} |
| tools_changed_notice | Only fires between turns, not triggerable |

## Live Test Results

| MCP Server | Connected? | Tools Same-Turn? | Tools Appeared Via |
|------------|-----------|-----------------|-------------------|
| mail | ✅ | ❌ | tools_changed_notice (next turn) |
| workiq | ✅ | ❌ | tools_changed_notice (~90s later) |
| s360-breeze | ✅ | ❌ | tools_changed_notice (~90s later) |

## Environment
- Copilot CLI v1.0.56-1
- Extension SDK: @github/copilot-sdk/extension via joinSession()
- OS: Windows 11
- Extension: Constellation (profile-based MCP manager)

Contributor guide

Open the contributing guide

Research direction

Start with the joinSession() extension entry point and session.rpc.tools.initializeAndValidate(), then trace how mcp_server_status_changed and tools_changed_notice affect the active tool list. Compare the listed API options and live MCP results; done means an extension can rebuild and expose newly enabled MCP tools during the same turn.

Written by the indexing model from the issue text.

Assessment

Tech stack
shell
Domain
api, developer-experience, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.