`resumeSession` silently ignores the `mcpServers` config field
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 68/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 静か
- 技術スタック
- javascript
- 領域
- api
調査の方向性
エントリーポイント CopilotClient.resumeSession から始め、mcpServers の処理を createSession と比較し、提供された再現手順と session.mcp_servers_loaded イベントを確認に使用します。{ memory: ... } で再開すると ["memory"] のみが発行され、以前の everything サーバーが切断または非表示になり、置き換え後のサーバーのツールのみが公開されれば完了です。
索引モデルが issue の本文から書いたものです。
説明
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
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_loadedshould emit["memory"].- The previously-loaded
everythingserver 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-sdk0.2.1 and 0.2.2 (both affected)- CLI binary 1.0.34, Node 22.14, Linux
- 主要言語
- Java
- スター
- 10.5k
- フォーク
- 1.5k
- 平均マージ
- 1日 9時間
- マージ済み PR(30日)
- 130
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
github/copilot-sdk のほかの issue
-
agentic-workflows
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
github/copilot-sdk#2760 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
github/copilot-sdk#2759 ·
-
documentation
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
github/copilot-sdk#2758 ·
-
agentic-workflows
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
github/copilot-sdk#2709 · コメント 1 件 ·
-
難易度 1/5 1時間未満 初心者へのやさしさ 78/100
github/copilot-sdk#2673 ·
github/copilot-sdk の issue をすべて見る
似ている issue
-
area/plugin
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
kestra-io/plugin-kestra#190 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
google-ai-edge/LiteRT-LM#3739 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
integra-team-red/meet-map#249 ·
-
[Studio][Bug] Cancelled create-user dialog keeps the password and admin switch for the next attempt オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
apache/rocketmq-dashboard#5064 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
wso2/dpdp-accelerator#287 ·