mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-07-09 17:19:02 +00:00
* 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>
129 lines
3.8 KiB
JSON
129 lines
3.8 KiB
JSON
{
|
|
"name": "@qwen-code/qwen-code",
|
|
"version": "0.19.2",
|
|
"description": "Qwen Code",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "git+https://github.com/QwenLM/qwen-code.git"
|
|
},
|
|
"type": "module",
|
|
"main": "dist/index.js",
|
|
"types": "dist/index.d.ts",
|
|
"bin": {
|
|
"qwen": "dist/index.js"
|
|
},
|
|
"exports": {
|
|
".": {
|
|
"types": "./dist/index.d.ts",
|
|
"import": "./dist/index.js"
|
|
},
|
|
"./export": {
|
|
"types": "./dist/src/export/index.d.ts",
|
|
"import": "./dist/src/export/index.js"
|
|
}
|
|
},
|
|
"scripts": {
|
|
"build": "node ../../scripts/build_package.js",
|
|
"start": "node dist/index.js",
|
|
"debug": "node --inspect-brk dist/index.js",
|
|
"lint": "eslint . --ext .ts,.tsx",
|
|
"format": "prettier --write .",
|
|
"test": "vitest run",
|
|
"test:ci": "vitest run",
|
|
"typecheck": "tsc --noEmit",
|
|
"check-i18n": "tsx ../../scripts/check-i18n.ts"
|
|
},
|
|
"files": [
|
|
"dist"
|
|
],
|
|
"config": {
|
|
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.19.2"
|
|
},
|
|
"dependencies": {
|
|
"@agentclientprotocol/sdk": "^0.14.1",
|
|
"@google/genai": "2.6.0",
|
|
"@iarna/toml": "^2.2.5",
|
|
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
"@qwen-code/acp-bridge": "file:../acp-bridge",
|
|
"@qwen-code/audio-capture": "file:../audio-capture",
|
|
"@qwen-code/channel-base": "file:../channels/base",
|
|
"@qwen-code/channel-dingtalk": "file:../channels/dingtalk",
|
|
"@qwen-code/channel-qqbot": "file:../channels/qqbot",
|
|
"@qwen-code/channel-feishu": "file:../channels/feishu",
|
|
"@qwen-code/channel-telegram": "file:../channels/telegram",
|
|
"@qwen-code/channel-weixin": "file:../channels/weixin",
|
|
"@qwen-code/qwen-code-core": "file:../core",
|
|
"@qwen-code/web-templates": "file:../web-templates",
|
|
"@types/update-notifier": "^6.0.8",
|
|
"ansi-regex": "^6.2.2",
|
|
"chokidar": "^4.0.3",
|
|
"command-exists": "^1.2.9",
|
|
"comment-json": "^4.2.5",
|
|
"diff": "^7.0.0",
|
|
"dotenv": "^17.1.0",
|
|
"express": "^5.2.1",
|
|
"fast-deep-equal": "^3.1.3",
|
|
"fzf": "^0.5.2",
|
|
"glob": "^10.5.0",
|
|
"highlight.js": "^11.11.1",
|
|
"ink": "7.0.3",
|
|
"ink-gradient": "^3.0.0",
|
|
"ink-link": "^4.1.0",
|
|
"ink-spinner": "^5.0.0",
|
|
"lowlight": "^3.3.0",
|
|
"p-limit": "^7.3.0",
|
|
"prompts": "^2.4.2",
|
|
"react": "^19.2.4",
|
|
"read-package-up": "^11.0.0",
|
|
"shell-quote": "^1.8.3",
|
|
"simple-git": "^3.28.0",
|
|
"string-width": "^7.1.0",
|
|
"strip-ansi": "^7.1.0",
|
|
"strip-json-comments": "^3.1.1",
|
|
"tar": "^7.5.2",
|
|
"undici": "^6.22.0",
|
|
"update-notifier": "^7.3.1",
|
|
"wrap-ansi": "^10.0.0",
|
|
"ws": "^8.18.0",
|
|
"yargs": "^17.7.2",
|
|
"zod": "^3.23.8"
|
|
},
|
|
"devDependencies": {
|
|
"@babel/runtime": "^7.27.6",
|
|
"@testing-library/react": "^16.3.0",
|
|
"@types/archiver": "^6.0.3",
|
|
"@types/command-exists": "^1.2.3",
|
|
"@types/diff": "^7.0.2",
|
|
"@types/dotenv": "^6.1.1",
|
|
"@types/express": "^5.0.3",
|
|
"@types/node": "^22.0.0",
|
|
"@types/prompts": "^2.4.9",
|
|
"@types/ws": "^8.5.0",
|
|
"@types/react": "^19.1.8",
|
|
"@types/react-dom": "^19.1.6",
|
|
"@types/semver": "^7.7.0",
|
|
"@types/shell-quote": "^1.7.5",
|
|
"@types/supertest": "^6.0.3",
|
|
"@types/yargs": "^17.0.32",
|
|
"archiver": "^7.0.1",
|
|
"ink-testing-library": "^4.0.0",
|
|
"jsdom": "^26.1.0",
|
|
"pretty-format": "^30.0.2",
|
|
"react-dom": "^19.1.0",
|
|
"supertest": "^7.2.2",
|
|
"typescript": "^5.3.3",
|
|
"vitest": "^3.1.1"
|
|
},
|
|
"optionalDependencies": {
|
|
"@teddyzhu/clipboard": "^0.0.5",
|
|
"@teddyzhu/clipboard-darwin-arm64": "0.0.5",
|
|
"@teddyzhu/clipboard-darwin-x64": "0.0.5",
|
|
"@teddyzhu/clipboard-linux-arm64-gnu": "0.0.5",
|
|
"@teddyzhu/clipboard-linux-x64-gnu": "0.0.5",
|
|
"@teddyzhu/clipboard-win32-arm64-msvc": "0.0.5",
|
|
"@teddyzhu/clipboard-win32-x64-msvc": "0.0.5"
|
|
},
|
|
"engines": {
|
|
"node": ">=22"
|
|
}
|
|
}
|