github / github/copilot-sdk

`resumeSession` silently ignores the `mcpServers` config field

Abierto
#1,113 0 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Java
Estrellas
10.5k
Forks
1.5k
Merge medio
1 d 11 h
PR fusionados (30 d)
127

Descripción

`CopilotClient.resumeSession(id, { mcpServers: ... })` does not apply the `mcpServers` value passed on resume. The servers connected during the
original `createSession` call remain connected; any servers declared on resume are never loaded. Other fields in `ResumeSessionConfig` (`tools`,
`skillDirectories`, `systemMessage`) *are* applied on the same call, so the behaviour is asymmetric.

### Reproduction

```js
import { CopilotClient } from '@github/copilot-sdk'

const baseConfig = {
model: 'gpt-4.1',
streaming: true,
onPermissionRequest: async () => ({ decision: 'allow', persist: false })
}

// Two different public MCP reference servers — distinct tool sets.
const mcpEverything = {
type: 'local',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-everything'],
tools: '*'
}
const mcpMemory = {
type: 'local',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-memory'],
tools: '*'
}

const LIST_PROMPT =
'Pick any MCP tool you actually have access to right now and call it ' +
'(any reasonable args). Then in one short sentence, name the tool you ' +
'just called and which MCP server it belongs to.'

async function ask (session, prompt) {
const response = await session.sendAndWait({ prompt }, 60_000)
return response?.data?.content ?? ''
}

const client = new CopilotClient({ autoStart: true })
await client.start()

const logServers = (phase) => (event) => {
if (event.type === 'session.mcp_servers_loaded') {
const names = (event.data?.servers ?? []).map(s => s.name)
console.log(` [SDK event in ${phase}] session.mcp_servers_loaded → ${JSON.stringify(names)}`)
}
}

console.log('\n=== 1. createSession with mcpServers = { everything } ===')
const sessionA = await client.createSession({
...baseConfig,
mcpServers: { everything: mcpEverything }
})
sessionA.on(logServers('createSession'))
console.log(' LLM reply: ' + await ask(sessionA, LIST_PROMPT))

console.log('\n=== 2. resumeSession(sameId, mcpServers = { memory }) ===')
const sessionB = await client.resumeSession(sessionA.id ?? sessionA.sessionId, {
...baseConfig,
mcpServers: { memory: mcpMemory } // ← DIFFERENT server
})
sessionB.on(logServers('resumeSession'))
console.log(' LLM reply: ' + await ask(sessionB, LIST_PROMPT))

await client.disconnect?.()
process.exit(0)
```

#### Run with:
```
npm i @github/copilot-sdk
node repro.mjs
```
(Node 22, `npx` on PATH, and a logged-in Copilot CLI — run
`./node_modules/.bin/copilot login` once.)

### Observed behavior

```
=== 1. createSession with mcpServers = { everything } ===
[SDK event in createSession] session.mcp_servers_loaded → ["everything"]
LLM reply: I called the get-sum tool from the "everything" MCP server.

=== 2. resumeSession(sameId, mcpServers = { memory }) ===
[SDK event in resumeSession] session.mcp_servers_loaded → ["everything"]
LLM reply: I called the get-tiny-image tool from the "everything" MCP server.
```

After step 2 the SDK is still publishing `["everything"]` in `session.mcp_servers_loaded`, and the LLM can only call tools from `everything` — even though the resume config explicitly passed `{ memory: ... }` and did **not** include `everything`.

### Expected behavior

After `resumeSession(id, { mcpServers: { memory: ... } })`:

- `session.mcp_servers_loaded` should emit `["memory"]`.
- The previously-loaded `everything` server should be disconnected (or at least no longer be visible as a tool source).
- The LLM should only be able to call tools from `memory` (e.g. `read_graph`, `create_entities`).

### Impact

Prevents agent-switching mid-conversation (same use case as #567). Only workaround is `deleteSession` + `createSession` — which wipes history, defeating the point of `resumeSession`.

### Environment
- `@github/copilot-sdk` 0.2.1 and 0.2.2 (both affected)
- CLI binary 1.0.34, Node 22.14, Linux

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.