qwen-code/integration-tests/cli
Heyang Wang 1344f34147
feat(mcp): reconcile MCP servers live on settings change (#5561)
* feat(mcp): reconcile MCP servers live on settings change

Hot-reload MCP servers when settings.json changes (issue #3696 sub-task 3):
editing mcpServers / mcp.allowed / mcp.excluded now connects, disconnects, or
restarts only the affected servers in place, without restarting the session or
losing conversation context.

- Part A: Config runtime setters + reinitializeMcpServers incremental
  reconcile; align the shared-pool path with the #4615 pending-approval gate
- Part B: SettingsWatcher subscriber (hotReload.ts), gated on a mcpServers +
  gating-list diff; flip the three MCP schema keys to hot-reloadable
- Part D: re-fire the approval modal for a gated server left pending by an edit
- Part E: /mcp shows why a gated server was skipped (pending / rejected)
- Record connection fingerprints on the bulk and lazy-connect paths so an edit
  to a server first connected via those paths is not silently dropped
- Design doc (en/zh) incl. the admission-stance boundary clarification

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

# Conflicts:
#	packages/cli/src/config/settingsSchema.test.ts

# Conflicts:
#	packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx

# Conflicts:
#	packages/cli/src/gemini.tsx

* feat(mcp): reconcile MCP servers live on settings change

Hot-reload MCP servers when settings.json changes (issue #3696 sub-task 3):
editing mcpServers / mcp.allowed / mcp.excluded now connects, disconnects, or
restarts only the affected servers in place, without restarting the session or
losing conversation context.

- Part A: Config runtime setters + reinitializeMcpServers incremental
  reconcile; align the shared-pool path with the #4615 pending-approval gate
- Part B: SettingsWatcher subscriber (hotReload.ts), gated on a mcpServers +
  gating-list diff; flip the three MCP schema keys to hot-reloadable
- Part D: re-fire the approval modal for a gated server left pending by an edit
- Part E: /mcp shows why a gated server was skipped (pending / rejected)
- Record connection fingerprints on the bulk and lazy-connect paths so an edit
  to a server first connected via those paths is not silently dropped
- Design doc (en/zh) incl. the admission-stance boundary clarification

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(mcp): harden hot-reload teardown and reconcile (review follow-ups)

Address reviewer findings on the MCP hot-reload changes:

- Extract purgeServerRegistries() and use it at every teardown path, fixing
  the discovery-timeout handler which leaked prompts/resources (only tools
  were purged) for a server that stalled tools/list past the timeout.
- Surface reconcile failures via AppEvent.LogError so a failed settings edit
  is visible to the user, not just under --debug.
- Make a single-session config edit to a discovery filter (trust /
  includeTools / excludeTools) reconnect the server so discover() re-applies
  it: connectionIdOf stays transport-only; add singleSessionConnectedKeyOf and
  rename connectionFingerprints -> connectedConfigKeys.
- Make a coalesced reinitializeMcpServers await the in-flight pass + its drain
  (store mcpReconcilePromise) so the caller no longer emits approval events /
  logs "complete" before its change is applied; coalesced callers share the
  failure.
- Assert removeResourcesByServer in the fingerprint-change tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(mcp): bound hot-reload MCP admission and explain why servers are unavailable (#3696) (#5561)

- K: treat the startup --allowed-mcp-server-names flag as an immutable upper
  bound — a runtime settings edit may narrow MCP admission within it but never
  widen beyond it; with no flag, settings fully drive admission.
- H: preserve an explicit `mcp.allowed: []` as deny-all (don't collapse to
  undefined / allow-all), matching boot semantics, and make mcpGatingEqual
  distinguish absent (allow-all) from [] (deny-all) so the change reconciles.
- B: classify why an MCP server is unavailable (removed / not_allowed /
  excluded / pending_approval) and route the tool-not-found message to the
  right recovery action; track removals against the gating-independent merged
  map (dropping the prev-effective snapshot param).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(mcp): document hot-reload admission bound, deny-all, and unavailable reasons (Part F)

Reflect the K/H/B changes in the sub-task 3 design doc: add Part F (CLI
--allowed-mcp-server-names as an immutable upper bound, mcp.allowed: [] as
deny-all, and getMcpServerUnavailableReason routing the tool-not-found message),
and fix the now-superseded "settings can widen beyond the startup allowlist"
admission-stance note and verification item 11.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(serve): pre-approve gated MCP servers in daemon baseline harness

The pool/daemon discovery path now honors #4615 pending-approval gating, so the workspace-scoped MCP servers the amplification suite declares in .qwen/settings.json are skipped as pending and never spawn (the suite timed out waiting for grandchildren). Add approveWorkspaceMcpServers() to the harness (keyed by the realpath workspace to match the daemon's canonicalized --workspace) and pre-approve the fixtures before boot, mirroring simple-mcp-server.test.ts.

---------

Co-authored-by: heyang.why <heyang.why@alibaba-inc.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:50:37 +00:00
..
_daemon-benchmark-helpers.ts test(cli): add daemon startup benchmark (#5825) 2026-06-25 06:56:13 +00:00
_daemon-harness.ts feat(mcp): reconcile MCP servers live on settings change (#5561) 2026-06-25 14:50:37 +00:00
_daemon-perf-report.ts feat(daemon): merge daemon-mode feature batch into main (#4490) 2026-06-12 00:34:49 +08:00
acp-cron.test.ts feat(core): enable loop/cron tools by default (#4950) 2026-06-10 23:21:53 +08:00
acp-integration.test.ts revert(core): revert Protocol enum & model-identity decoupling (#5089) (#5745) 2026-06-23 16:32:38 +08:00
cron-tools.test.ts feat(core): enable loop/cron tools by default (#4950) 2026-06-10 23:21:53 +08:00
edit.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00
extensions-install.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00
file-system.test.ts fix(cli): keep v5 settings migration idempotent (#5676) 2026-06-23 01:28:48 +08:00
json-output.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00
json-schema.test.ts fix(test): repair stale --json-schema integration assertion (#4075) 2026-05-12 12:00:57 +08:00
list_directory.test.ts Merge remote-tracking branch 'origin/main' into feat/in-session-cron-loops 2026-03-30 19:08:25 +08:00
mcp_server_cyclic_schema.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00
mock-acp-typecheck.test.ts feat(daemon): merge daemon-mode feature batch into main (#4490) 2026-06-12 00:34:49 +08:00
monitor.test.ts ci(e2e): stabilize MCP/CLI flows and cancel stale main runs (#4039) 2026-05-12 16:09:30 +08:00
notebook-edit.test.ts feat(core): add NotebookEdit tool for Jupyter notebooks 2026-05-21 00:06:15 +08:00
qwen-config-dir.test.ts revert(core): revert Protocol enum & model-identity decoupling (#5089) (#5745) 2026-06-23 16:32:38 +08:00
qwen-daemon-loadtest.test.ts feat(daemon): merge daemon-mode feature batch into main (#4490) 2026-06-12 00:34:49 +08:00
qwen-daemon-startup-benchmark.test.ts test(cli): add daemon startup benchmark (#5825) 2026-06-25 06:56:13 +00:00
qwen-daemon-vs-cli-benchmark.test.ts feat(daemon): merge daemon-mode feature batch into main (#4490) 2026-06-12 00:34:49 +08:00
qwen-serve-baseline.test.ts feat(mcp): reconcile MCP servers live on settings change (#5561) 2026-06-25 14:50:37 +00:00
qwen-serve-routes.test.ts feat(serve): Add daemon workspace voice and control APIs (#5765) 2026-06-24 23:48:57 +00:00
qwen-serve-streaming.test.ts ci: collapse PR checks into Ubuntu gate (#5767) 2026-06-23 22:08:43 +08:00
read_many_files.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00
run_shell_command.test.ts ci(e2e): stabilize MCP/CLI flows and cancel stale main runs (#4039) 2026-05-12 16:09:30 +08:00
save_memory.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00
settings-migration.test.ts revert(core): revert Protocol enum & model-identity decoupling (#5089) (#5745) 2026-06-23 16:32:38 +08:00
simple-mcp-server.test.ts fix(ci): restore release integration env controls (#5121) 2026-06-15 15:56:29 +08:00
sleep-interception.test.ts test(integration): harden flaky sleep-interception e2e against skipped tool calls (#4936) 2026-06-11 00:08:26 +08:00
stdin-context.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00
telemetry.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00
todo_write.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00
tool-search.test.ts feat(core): enable loop/cron tools by default (#4950) 2026-06-10 23:21:53 +08:00
utf-bom-encoding.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00
write_file.test.ts refactor(tests): reorganize integration tests by execution mode 2026-03-29 05:49:17 +00:00