fix(cc-config): MCP scope was inverted — expose user/local, not user/project

readMcpServers only ever parses ~/.claude.json (top-level = user scope,
projects[<root>] = the panel's "projectScoped" bucket, which the CLI itself
calls `local`). The previous user/project scope choice was the exact
inverse: `--scope project` writes .mcp.json, which readMcpServers never
reads (a successful add would vanish), and every "projectScoped" row was
actually `local`, so Remove sent a scope the CLI could never match.

- cc-mcp-cli.js: MCP_SCOPES -> ["user", "local"]; drop the local
  mutationQueue/serialize in favor of cc-plugin-cli.js's exported one, so a
  plugin install and an MCP add can't spawn `claude` concurrently; drop the
  String(v) coercion in env/header flags (a wrong-typed value is now a 400,
  not a written "[object Object]"); assertEmbeddedValue allows empty strings
  (a legitimate empty stdio arg was previously a 400).
- cc-plugin-cli.js: export `serialize` for reuse.
- CcConfig.tsx: CcMcpScope narrowed to user/local; the projectScoped bucket's
  McpCard now sends scope="local"; rows sourced from
  ~/.claude/settings.json (no CLI scope addresses them) no longer render a
  Remove button. Cleaned up i18n keys my own earlier change made dead
  (explain.mcp.addCmd/remove/removeButton) and gave the scope <select> its
  own short option labels instead of reusing full-sentence section headings.
This commit is contained in:
2026-09-09 09:36:52 +07:00
parent fd4edaac98
commit 6d27c115d8
11 changed files with 159 additions and 59 deletions
+6 -6
View File
@@ -131,6 +131,8 @@
"projectScope": "Project-scoped servers",
"name": "Name",
"scope": "Scope",
"scopeUser": "User",
"scopeLocal": "This project",
"command": "Command",
"args": "Args",
"env": "Env names",
@@ -138,7 +140,8 @@
"headers": "Header names",
"kind": "Kind",
"source": "Source",
"noServers": "No MCP servers found."
"noServers": "No MCP servers found.",
"notRemovable": "Configured in settings.json — remove it there; no CLI scope addresses this entry."
},
"hooks": {
"noHooks": "No hooks configured.",
@@ -277,10 +280,7 @@
"body": "MCP server config lives inside `~/.claude.json`, the same file the live CLI writes to constantly. Concurrent writes from the dashboard would corrupt project state, so add/remove flow goes through Claude Code itself.",
"list": "List configured servers:",
"listCmd": "claude mcp list",
"add": "Add a server:",
"addCmd": "claude mcp add <name> <command> [args…]",
"remove": "Remove this server:",
"removeButton": "Copy remove command"
"add": "Add a server:"
},
"marketplaces": {
"title": "Marketplaces are where plugins come from",
@@ -326,7 +326,7 @@
"addMcpCommandPlaceholder": "npx -y @modelcontextprotocol/server-github",
"addMcpUrlPlaceholder": "https://mcp.example.com",
"addMcpButton": "Add",
"addMcpHelp": "Runs `claude mcp add`. Scope user/project only — a `local`-scoped server is the CLI's per-checkout layer and isn't offered here.",
"addMcpHelp": "Runs `claude mcp add`. \"This project\" scopes the server to the current checkout — the CLI's separate `project` scope (a shared `.mcp.json`) isn't offered here because this dashboard can't see servers stored there.",
"mcpAdded": "Added MCP server {{name}}.",
"mcpRemoved": "Removed MCP server {{name}}.",
"hookEvent": "Event name (e.g. PreToolUse)",
+6 -6
View File
@@ -126,6 +126,8 @@
"projectScope": "Máy chủ phạm vi dự án",
"name": "Tên",
"scope": "Phạm vi",
"scopeUser": "Người dùng",
"scopeLocal": "Dự án này",
"command": "Lệnh",
"args": "Tham số",
"env": "Tên env",
@@ -133,7 +135,8 @@
"headers": "Tên Header",
"kind": "Loại",
"source": "Nguồn",
"noServers": "Không tìm thấy máy chủ MCP."
"noServers": "Không tìm thấy máy chủ MCP.",
"notRemovable": "Được cấu hình trong settings.json — hãy xóa ở đó; không có phạm vi CLI nào áp dụng cho mục này."
},
"hooks": {
"noHooks": "Chưa cấu hình hook.",
@@ -272,10 +275,7 @@
"body": "Cấu hình MCP server nằm trong `~/.claude.json`, đúng tệp mà CLI đang chạy ghi liên tục. Ghi đồng thời từ dashboard sẽ phá hỏng trạng thái dự án, nên flow add/remove đi qua chính Claude Code.",
"list": "Liệt kê server đã cấu hình:",
"listCmd": "claude mcp list",
"add": "Thêm server:",
"addCmd": "claude mcp add <name> <command> [args…]",
"remove": "Gỡ server này:",
"removeButton": "Sao chép lệnh gỡ"
"add": "Thêm server:"
},
"marketplaces": {
"title": "Marketplace là nơi plugin đến từ đó",
@@ -321,7 +321,7 @@
"addMcpCommandPlaceholder": "npx -y @modelcontextprotocol/server-github",
"addMcpUrlPlaceholder": "https://mcp.example.com",
"addMcpButton": "Thêm",
"addMcpHelp": "Chạy lệnh `claude mcp add`. Chỉ có phạm vi user/project — phạm vi `local` của CLI (theo từng checkout) không được cung cấp ở đây.",
"addMcpHelp": "Chạy lệnh `claude mcp add`. \"Dự án này\" giới hạn server trong checkout hiện tại — phạm vi `project` riêng của CLI (một `.mcp.json` dùng chung) không được cung cấp ở đây vì dashboard không thể thấy các server lưu ở đó.",
"mcpAdded": "Đã thêm máy chủ MCP {{name}}.",
"mcpRemoved": "Đã xóa máy chủ MCP {{name}}.",
"hookEvent": "Tên sự kiện (vd PreToolUse)",