mcpsmgr 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1631 -0
- package/dist/index.js.map +1 -0
- package/docs/README_zh-CN.md +99 -0
- package/openspec/changes/archive/2026-03-12-fix-global-mcp-default-selection/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-03-12-fix-global-mcp-default-selection/design.md +41 -0
- package/openspec/changes/archive/2026-03-12-fix-global-mcp-default-selection/proposal.md +28 -0
- package/openspec/changes/archive/2026-03-12-fix-global-mcp-default-selection/specs/project-operations/spec.md +53 -0
- package/openspec/changes/archive/2026-03-12-fix-global-mcp-default-selection/tasks.md +9 -0
- package/openspec/changes/archive/2026-03-12-fix-init-server-detection/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-03-12-fix-init-server-detection/design.md +40 -0
- package/openspec/changes/archive/2026-03-12-fix-init-server-detection/proposal.md +25 -0
- package/openspec/changes/archive/2026-03-12-fix-init-server-detection/specs/project-operations/spec.md +25 -0
- package/openspec/changes/archive/2026-03-12-fix-init-server-detection/tasks.md +10 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/design.md +32 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/proposal.md +25 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/specs/project-operations/spec.md +30 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/specs/server-management/spec.md +15 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/tasks.md +17 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/design.md +104 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/proposal.md +34 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/specs/agent-adapters/spec.md +110 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/specs/central-storage/spec.md +38 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/specs/glm-integration/spec.md +66 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/specs/project-operations/spec.md +76 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/specs/server-management/spec.md +75 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/tasks.md +60 -0
- package/openspec/config.yaml +20 -0
- package/openspec/specs/agent-adapters/spec.md +148 -0
- package/openspec/specs/central-storage/spec.md +42 -0
- package/openspec/specs/glm-integration/spec.md +70 -0
- package/openspec/specs/project-operations/spec.md +138 -0
- package/openspec/specs/server-management/spec.md +93 -0
- package/package.json +33 -0
- package/src/__tests__/integration.test.ts +200 -0
- package/src/adapters/__tests__/adapters.test.ts +274 -0
- package/src/adapters/antigravity.ts +114 -0
- package/src/adapters/claude-code.ts +114 -0
- package/src/adapters/codex-cli.ts +135 -0
- package/src/adapters/env-args.ts +51 -0
- package/src/adapters/gemini-cli.ts +110 -0
- package/src/adapters/index.ts +32 -0
- package/src/adapters/json-file.ts +24 -0
- package/src/adapters/opencode.ts +114 -0
- package/src/commands/add.ts +68 -0
- package/src/commands/init.ts +136 -0
- package/src/commands/list.ts +77 -0
- package/src/commands/remove.ts +61 -0
- package/src/commands/server-add.ts +211 -0
- package/src/commands/server-list.ts +24 -0
- package/src/commands/server-remove.ts +12 -0
- package/src/commands/setup.ts +71 -0
- package/src/commands/sync.ts +98 -0
- package/src/index.ts +100 -0
- package/src/services/glm-client.ts +190 -0
- package/src/services/system-prompt.ts +61 -0
- package/src/services/web-reader.ts +130 -0
- package/src/types.ts +59 -0
- package/src/utils/config.ts +22 -0
- package/src/utils/paths.ts +11 -0
- package/src/utils/prompt.ts +3 -0
- package/src/utils/resolve-config.ts +13 -0
- package/src/utils/server-store.ts +56 -0
- package/tsconfig.json +17 -0
- package/tsup.config.ts +13 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
schema: spec-driven
|
|
2
|
+
|
|
3
|
+
# Project context (optional)
|
|
4
|
+
# This is shown to AI when creating artifacts.
|
|
5
|
+
# Add your tech stack, conventions, style guides, domain knowledge, etc.
|
|
6
|
+
# Example:
|
|
7
|
+
# context: |
|
|
8
|
+
# Tech stack: TypeScript, React, Node.js
|
|
9
|
+
# We use conventional commits
|
|
10
|
+
# Domain: e-commerce platform
|
|
11
|
+
|
|
12
|
+
# Per-artifact rules (optional)
|
|
13
|
+
# Add custom rules for specific artifacts.
|
|
14
|
+
# Example:
|
|
15
|
+
# rules:
|
|
16
|
+
# proposal:
|
|
17
|
+
# - Keep proposals under 500 words
|
|
18
|
+
# - Always include a "Non-goals" section
|
|
19
|
+
# tasks:
|
|
20
|
+
# - Break tasks into chunks of max 2 hours
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
## Purpose
|
|
2
|
+
|
|
3
|
+
为 5 个编程 agent 提供配置适配器, 处理各自不同的配置文件格式和路径.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
### Requirement: Adapter output format
|
|
8
|
+
|
|
9
|
+
All adapters SHALL output MCP server configs WITHOUT the `env`/`environment` field. The adapter SHALL:
|
|
10
|
+
|
|
11
|
+
1. Substitute `${VAR_NAME}` references in args with actual values from the env block
|
|
12
|
+
2. For remaining env vars (not referenced in args), use the `env` command as a wrapper with `KEY=value` args
|
|
13
|
+
3. Never include `env` or `environment` field in the output
|
|
14
|
+
|
|
15
|
+
When reading configs back (`fromAgentFormat`), the adapter SHALL handle both the new format (command = "env" with KEY=value args) and the legacy format (separate env/environment field) for backward compatibility.
|
|
16
|
+
|
|
17
|
+
#### Scenario: Args contain ${VAR} references
|
|
18
|
+
- **WHEN** a stdio config has args containing `${JINA_API_KEY}` and env `{ "JINA_API_KEY": "xxx" }`
|
|
19
|
+
- **THEN** the adapter substitutes `${JINA_API_KEY}` with `xxx` directly in the args, removes the env field, and does NOT use env command wrapper (since no remaining env vars)
|
|
20
|
+
|
|
21
|
+
#### Scenario: Env vars not referenced in args
|
|
22
|
+
- **WHEN** a stdio config has env vars `{ "BRAVE_API_KEY": "xxx" }` with no `${BRAVE_API_KEY}` in args
|
|
23
|
+
- **THEN** the adapter uses `env` command wrapper: `command: "env"`, args: `["BRAVE_API_KEY=xxx", "npx", ...]`
|
|
24
|
+
|
|
25
|
+
#### Scenario: Mixed - some referenced, some not
|
|
26
|
+
- **WHEN** a stdio config has `${API_KEY}` in args AND a separate `DEBUG` env var
|
|
27
|
+
- **THEN** `${API_KEY}` is substituted in args, `DEBUG` is passed via env command wrapper
|
|
28
|
+
|
|
29
|
+
#### Scenario: Write stdio config without env vars
|
|
30
|
+
- **WHEN** a stdio config has empty env vars
|
|
31
|
+
- **THEN** the adapter outputs config with the original command and args, and NO `env`/`environment` field
|
|
32
|
+
|
|
33
|
+
#### Scenario: Read new format config
|
|
34
|
+
- **WHEN** the adapter reads a config with `command: "env"` and args containing KEY=value entries
|
|
35
|
+
- **THEN** it extracts env vars from the KEY=value args and reconstructs the original command, args, and env
|
|
36
|
+
|
|
37
|
+
#### Scenario: Read legacy format config (backward compatibility)
|
|
38
|
+
- **WHEN** the adapter reads a config with a separate `env`/`environment` field
|
|
39
|
+
- **THEN** it parses the env vars from that field as before
|
|
40
|
+
|
|
41
|
+
### Requirement: Claude Code Adapter
|
|
42
|
+
|
|
43
|
+
系统 SHALL 提供 Claude Code 的配置适配器, 操作 `.mcp.json` 文件.
|
|
44
|
+
|
|
45
|
+
#### Scenario: 读取已有配置
|
|
46
|
+
|
|
47
|
+
- **WHEN** 项目根目录存在 `.mcp.json`
|
|
48
|
+
- **THEN** adapter 解析文件, 提取 `mcpServers` 下所有 MCP 服务条目
|
|
49
|
+
|
|
50
|
+
#### Scenario: 写入新服务
|
|
51
|
+
|
|
52
|
+
- **WHEN** 向 Claude Code 添加一个 MCP 服务
|
|
53
|
+
- **THEN** adapter 读取 `.mcp.json` (不存在则创建), 在 `mcpServers` 下添加服务条目, 使用 env command wrapper 格式 (stdio 有 env vars 时) 或 HTTP 格式 `{ "type": "http", "url": "...", "headers": {...} }`, 保留文件中已有的其他服务条目
|
|
54
|
+
|
|
55
|
+
#### Scenario: 同名冲突
|
|
56
|
+
|
|
57
|
+
- **WHEN** `.mcp.json` 中已存在同名服务
|
|
58
|
+
- **THEN** adapter 报告冲突, 不修改文件
|
|
59
|
+
|
|
60
|
+
### Requirement: Codex CLI Adapter
|
|
61
|
+
|
|
62
|
+
系统 SHALL 提供 Codex CLI 的配置适配器, 操作 `.codex/config.toml` 文件.
|
|
63
|
+
|
|
64
|
+
#### Scenario: 读取已有配置
|
|
65
|
+
|
|
66
|
+
- **WHEN** 项目中存在 `.codex/config.toml`
|
|
67
|
+
- **THEN** adapter 解析 TOML 文件, 提取 `[mcp_servers.*]` 下所有 MCP 服务条目
|
|
68
|
+
|
|
69
|
+
#### Scenario: 写入新服务
|
|
70
|
+
|
|
71
|
+
- **WHEN** 向 Codex CLI 添加一个 MCP 服务
|
|
72
|
+
- **THEN** adapter 读取 `.codex/config.toml` (不存在则创建 `.codex/` 目录和文件), 在 `[mcp_servers.<name>]` section 下添加服务配置, 使用 env command wrapper 格式 (有 env vars 时 command = "env"), MUST 保留文件中已有的非 MCP section 和注释
|
|
73
|
+
|
|
74
|
+
#### Scenario: 同名冲突
|
|
75
|
+
|
|
76
|
+
- **WHEN** `.codex/config.toml` 中 `[mcp_servers]` 下已存在同名服务
|
|
77
|
+
- **THEN** adapter 报告冲突, 不修改文件
|
|
78
|
+
|
|
79
|
+
### Requirement: Gemini CLI Adapter
|
|
80
|
+
|
|
81
|
+
系统 SHALL 提供 Gemini CLI 的配置适配器, 操作 `.gemini/settings.json` 文件.
|
|
82
|
+
|
|
83
|
+
#### Scenario: 读取已有配置
|
|
84
|
+
|
|
85
|
+
- **WHEN** 项目中存在 `.gemini/settings.json`
|
|
86
|
+
- **THEN** adapter 解析文件, 提取 `mcpServers` 下所有 MCP 服务条目
|
|
87
|
+
|
|
88
|
+
#### Scenario: 写入新服务
|
|
89
|
+
|
|
90
|
+
- **WHEN** 向 Gemini CLI 添加一个 MCP 服务
|
|
91
|
+
- **THEN** adapter 读取 `.gemini/settings.json` (不存在则创建 `.gemini/` 目录和文件), 在 `mcpServers` 下添加服务条目, 使用 env command wrapper 格式, 保留文件中已有的其他字段 (如 `mcp`, `theme` 等非 mcpServers 字段)
|
|
92
|
+
|
|
93
|
+
#### Scenario: 同名冲突
|
|
94
|
+
|
|
95
|
+
- **WHEN** `.gemini/settings.json` 中 `mcpServers` 下已存在同名服务
|
|
96
|
+
- **THEN** adapter 报告冲突, 不修改文件
|
|
97
|
+
|
|
98
|
+
### Requirement: OpenCode Adapter
|
|
99
|
+
|
|
100
|
+
系统 SHALL 提供 OpenCode 的配置适配器, 操作 `opencode.json` 文件.
|
|
101
|
+
|
|
102
|
+
#### Scenario: 读取已有配置
|
|
103
|
+
|
|
104
|
+
- **WHEN** 项目根目录存在 `opencode.json`
|
|
105
|
+
- **THEN** adapter 解析文件, 提取 `mcp` 下所有 MCP 服务条目
|
|
106
|
+
|
|
107
|
+
#### Scenario: 写入新服务 (stdio)
|
|
108
|
+
|
|
109
|
+
- **WHEN** 向 OpenCode 添加一个 stdio 类型的 MCP 服务
|
|
110
|
+
- **THEN** adapter 在 `mcp` 下添加服务条目, 格式为 `{ "type": "local", "command": ["env", "KEY=val", "<cmd>", ...] }` (有 env vars 时) 或 `{ "type": "local", "command": ["<cmd>", "<arg1>", ...] }` (无 env vars 时), 不使用 `environment` 字段
|
|
111
|
+
|
|
112
|
+
#### Scenario: 写入新服务 (http)
|
|
113
|
+
|
|
114
|
+
- **WHEN** 向 OpenCode 添加一个 http 类型的 MCP 服务
|
|
115
|
+
- **THEN** adapter 在 `mcp` 下添加服务条目, 格式为 `{ "type": "remote", "url": "...", "headers": {...} }`
|
|
116
|
+
|
|
117
|
+
#### Scenario: 同名冲突
|
|
118
|
+
|
|
119
|
+
- **WHEN** `opencode.json` 中 `mcp` 下已存在同名服务
|
|
120
|
+
- **THEN** adapter 报告冲突, 不修改文件
|
|
121
|
+
|
|
122
|
+
### Requirement: Antigravity Adapter
|
|
123
|
+
|
|
124
|
+
系统 SHALL 提供 Antigravity 的配置适配器, 操作 `~/.gemini/antigravity/mcp_config.json` (全局文件).
|
|
125
|
+
|
|
126
|
+
#### Scenario: 读取已有配置
|
|
127
|
+
|
|
128
|
+
- **WHEN** `~/.gemini/antigravity/mcp_config.json` 存在
|
|
129
|
+
- **THEN** adapter 解析文件, 提取 `mcpServers` 下所有 MCP 服务条目
|
|
130
|
+
|
|
131
|
+
#### Scenario: 写入新服务
|
|
132
|
+
|
|
133
|
+
- **WHEN** 向 Antigravity 添加一个 MCP 服务
|
|
134
|
+
- **THEN** adapter 读取 `~/.gemini/antigravity/mcp_config.json` (不存在则创建目录和文件), 在 `mcpServers` 下添加服务条目, 使用 env command wrapper 格式 或 HTTP 格式 `{ "serverUrl": "...", "headers": {...} }`, 注意 HTTP 时 url key MUST 为 `serverUrl`
|
|
135
|
+
|
|
136
|
+
#### Scenario: 同名冲突
|
|
137
|
+
|
|
138
|
+
- **WHEN** 配置文件中 `mcpServers` 下已存在同名服务
|
|
139
|
+
- **THEN** adapter 报告冲突, 不修改文件
|
|
140
|
+
|
|
141
|
+
### Requirement: Agent 自动检测
|
|
142
|
+
|
|
143
|
+
系统 SHALL 在项目目录中自动检测哪些 agent 的配置文件已存在.
|
|
144
|
+
|
|
145
|
+
#### Scenario: 检测项目中的 agent
|
|
146
|
+
|
|
147
|
+
- **WHEN** 系统需要确定项目使用了哪些 agent
|
|
148
|
+
- **THEN** 系统检查以下文件是否存在: `.mcp.json` (Claude Code), `.codex/` 目录 (Codex CLI), `.gemini/settings.json` (Gemini CLI), `opencode.json` (OpenCode); Antigravity 始终作为可选项列出 (因为仅全局配置)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
## Purpose
|
|
2
|
+
|
|
3
|
+
管理 `~/.mcps-manager/` 中央仓库的初始化, 配置文件和服务定义文件的存储.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
### Requirement: Setup 初始化中央仓库
|
|
8
|
+
|
|
9
|
+
系统 SHALL 提供 `mcpsmgr setup` 命令, 创建 `~/.mcps-manager/` 目录结构并交互式收集配置信息.
|
|
10
|
+
|
|
11
|
+
#### Scenario: 首次 setup
|
|
12
|
+
|
|
13
|
+
- **WHEN** 用户执行 `mcpsmgr setup` 且 `~/.mcps-manager/` 不存在
|
|
14
|
+
- **THEN** 系统创建 `~/.mcps-manager/` 目录 (权限 700) 和 `servers/` 子目录, 交互式要求用户输入 GLM5 API Key, 选择 GLM5 端点 (Coding 或通用), 并将配置保存到 `~/.mcps-manager/config.json` (权限 600). Web Reader API Key 默认复用 GLM5 API Key (同属智谱平台)
|
|
15
|
+
|
|
16
|
+
#### Scenario: 重复 setup
|
|
17
|
+
|
|
18
|
+
- **WHEN** 用户执行 `mcpsmgr setup` 且 `~/.mcps-manager/` 已存在
|
|
19
|
+
- **THEN** 系统提示配置已存在, 询问是否覆盖
|
|
20
|
+
|
|
21
|
+
### Requirement: config.json 结构
|
|
22
|
+
|
|
23
|
+
系统 SHALL 将全局配置保存在 `~/.mcps-manager/config.json` 中.
|
|
24
|
+
|
|
25
|
+
#### Scenario: 配置文件内容
|
|
26
|
+
|
|
27
|
+
- **WHEN** setup 完成后
|
|
28
|
+
- **THEN** config.json 包含 `glm.apiKey` (GLM5 API key), `glm.endpoint` (完整端点 URL), `webReader.apiKey` (Web Reader API key), `webReader.url` (Web Reader MCP 端点 URL)
|
|
29
|
+
|
|
30
|
+
### Requirement: 服务定义文件存储
|
|
31
|
+
|
|
32
|
+
系统 SHALL 将每个 MCP 服务定义保存为 `~/.mcps-manager/servers/{name}.json`, 文件权限 600.
|
|
33
|
+
|
|
34
|
+
#### Scenario: 服务定义文件结构
|
|
35
|
+
|
|
36
|
+
- **WHEN** 一个 MCP 服务被添加到中央仓库
|
|
37
|
+
- **THEN** 服务定义文件包含 `name` (服务名), `source` (来源 URL), `default` (基础配置, 含 transport/command/args/env 等), `overrides` (per-agent 配置覆盖, 可为空对象)
|
|
38
|
+
|
|
39
|
+
#### Scenario: 文件权限
|
|
40
|
+
|
|
41
|
+
- **WHEN** 服务定义文件被创建
|
|
42
|
+
- **THEN** 文件权限 MUST 设置为 600 (仅所有者可读写)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
## Purpose
|
|
2
|
+
|
|
3
|
+
集成 GLM5 大模型和智谱 Web Reader MCP, 实现 MCP 服务文档的自动分析和配置提取.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
### Requirement: GLM5 API 调用
|
|
8
|
+
|
|
9
|
+
系统 SHALL 调用 GLM5 Chat Completion API 分析 MCP 服务文档.
|
|
10
|
+
|
|
11
|
+
#### Scenario: 调用 GLM5 分析文档
|
|
12
|
+
|
|
13
|
+
- **WHEN** 用户通过 `mcpsmgr server add <url>` 添加服务
|
|
14
|
+
- **THEN** 系统构造请求: model 为 `glm-5`, system prompt 指示分析 MCP 文档并提取 5 个 agent 的配置, tools 中包含 webReader 函数定义, user message 包含用户提供的 URL, 发送到 config.json 中配置的 GLM5 端点
|
|
15
|
+
|
|
16
|
+
#### Scenario: GLM5 端点认证
|
|
17
|
+
|
|
18
|
+
- **WHEN** 调用 GLM5 API
|
|
19
|
+
- **THEN** 系统使用 `Authorization: Bearer <glm.apiKey>` 认证, Content-Type 为 `application/json`
|
|
20
|
+
|
|
21
|
+
### Requirement: Web Reader 工具集成
|
|
22
|
+
|
|
23
|
+
系统 SHALL 将智谱 Web Reader MCP 作为 GLM5 的 function calling tool 提供.
|
|
24
|
+
|
|
25
|
+
#### Scenario: 定义 webReader 工具
|
|
26
|
+
|
|
27
|
+
- **WHEN** 构造 GLM5 请求
|
|
28
|
+
- **THEN** tools 数组中包含 webReader 函数定义, 参数为 `url` (string, required), tool_choice 设为 `auto`
|
|
29
|
+
|
|
30
|
+
#### Scenario: 处理 GLM5 的工具调用
|
|
31
|
+
|
|
32
|
+
- **WHEN** GLM5 返回 `tool_calls` 要求调用 webReader
|
|
33
|
+
- **THEN** 系统提取 URL 参数, 向 Web Reader MCP 端点发送请求 (使用 `webReader.apiKey` 认证), 获取网页内容, 将结果作为 `role: "tool"` 消息回传给 GLM5 继续对话
|
|
34
|
+
|
|
35
|
+
#### Scenario: Web Reader 调用失败
|
|
36
|
+
|
|
37
|
+
- **WHEN** Web Reader MCP 返回错误或超时
|
|
38
|
+
- **THEN** 系统将错误信息回传给 GLM5, 由 GLM5 决定是否重试或基于已有信息返回结果
|
|
39
|
+
|
|
40
|
+
### Requirement: GitHub README 优先获取
|
|
41
|
+
|
|
42
|
+
系统 SHALL 对 GitHub `owner/repo` 格式优先获取 README.
|
|
43
|
+
|
|
44
|
+
#### Scenario: GitHub 简写解析
|
|
45
|
+
|
|
46
|
+
- **WHEN** 用户输入格式为 `owner/repo` (不含 `/` 以外的特殊字符, 不以 `http` 开头, 不以 `@` 开头)
|
|
47
|
+
- **THEN** 系统先尝试给 GLM5 的 user message 中提供 `https://github.com/{owner}/{repo}` 作为文档 URL, 并指示 GLM5 优先读取该仓库的 README
|
|
48
|
+
|
|
49
|
+
### Requirement: 分析结果结构化输出
|
|
50
|
+
|
|
51
|
+
GLM5 MUST 返回结构化 JSON 格式的分析结果.
|
|
52
|
+
|
|
53
|
+
#### Scenario: 标准分析结果
|
|
54
|
+
|
|
55
|
+
- **WHEN** GLM5 完成文档分析
|
|
56
|
+
- **THEN** 返回 JSON 包含: `name` (服务名, 从文档中提取), `default` (基础配置, 含 transport/command/args/env 等), `overrides` (per-agent 配置覆盖, key 为 agent id), `requiredEnvVars` (需要用户提供值的环境变量名列表)
|
|
57
|
+
|
|
58
|
+
#### Scenario: 分析结果展示
|
|
59
|
+
|
|
60
|
+
- **WHEN** GLM5 返回分析结果
|
|
61
|
+
- **THEN** 系统展示: 服务名, 来源 URL, 基础配置详情, 各 agent 的专属配置差异表 (含 transport 和差异说明), 让用户充分了解后选择是否信任
|
|
62
|
+
|
|
63
|
+
### Requirement: 多轮对话处理
|
|
64
|
+
|
|
65
|
+
系统 SHALL 支持 GLM5 function calling 的多轮对话.
|
|
66
|
+
|
|
67
|
+
#### Scenario: 多次工具调用
|
|
68
|
+
|
|
69
|
+
- **WHEN** GLM5 在一次对话中多次请求调用 webReader (如先读 README 再读其他页面)
|
|
70
|
+
- **THEN** 系统依次执行每次工具调用, 将结果回传, 直到 GLM5 返回最终分析结果 (不含 tool_calls)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
## Purpose
|
|
2
|
+
|
|
3
|
+
提供项目级的 MCP 服务管理操作, 包括初始化, 添加, 移除, 同步和状态查看.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
### Requirement: 项目初始化
|
|
8
|
+
|
|
9
|
+
系统 SHALL 支持 `mcpsmgr init` 命令, 在当前项目中交互式选择 agent 和 MCP 服务.
|
|
10
|
+
|
|
11
|
+
#### Scenario: 交互式初始化
|
|
12
|
+
|
|
13
|
+
- **WHEN** 用户在项目目录执行 `mcpsmgr init`
|
|
14
|
+
- **THEN** 系统自动检测已存在的 agent 配置文件并预选 (其中 `isGlobal` 为 `true` 的 agent SHALL 默认不选中), 展示所有支持的 agent 供用户勾选, 从中央仓库列出所有已保存的 MCP 服务供用户勾选, 展示即将执行的操作预览, 确认后将选中的服务写入选中的 agent 配置文件
|
|
15
|
+
|
|
16
|
+
#### Scenario: 服务器选择默认状态基于目标目录检测
|
|
17
|
+
|
|
18
|
+
- **WHEN** 用户完成 agent 选择后进入服务器选择步骤
|
|
19
|
+
- **THEN** 系统 SHALL 读取所有已选中 agent 的现有配置, 收集已存在的 MCP 服务名称. 对于已存在于任一已选中 agent 配置中的服务, SHALL 标记为 `(detected)` 并默认选中. 对于不存在于任何已选中 agent 配置中的服务, SHALL 默认不选中.
|
|
20
|
+
|
|
21
|
+
#### Scenario: 配置读取失败降级
|
|
22
|
+
|
|
23
|
+
- **WHEN** 读取某个已选中 agent 的现有配置时发生错误 (如文件损坏)
|
|
24
|
+
- **THEN** 系统 SHALL 跳过该 agent 的服务检测, 继续处理其他 agent, 不阻断初始化流程
|
|
25
|
+
|
|
26
|
+
#### Scenario: 中央仓库为空
|
|
27
|
+
|
|
28
|
+
- **WHEN** 用户执行 `mcpsmgr init` 但 `~/.mcps-manager/servers/` 下没有任何服务
|
|
29
|
+
- **THEN** 系统提示中央仓库为空, 建议先使用 `mcpsmgr server add` 添加服务
|
|
30
|
+
|
|
31
|
+
### Requirement: 项目添加服务
|
|
32
|
+
|
|
33
|
+
系统 SHALL 支持 `mcpsmgr add <server-name>` 命令, 将中央仓库中的服务添加到当前项目的 agent 配置中.
|
|
34
|
+
|
|
35
|
+
#### Scenario: 添加到已检测的 agent
|
|
36
|
+
|
|
37
|
+
- **WHEN** 用户执行 `mcpsmgr add context7`
|
|
38
|
+
- **THEN** 系统自动检测项目中已存在的 agent 配置文件, 展示列表供用户勾选 (其中 `isGlobal` 为 `true` 的 agent SHALL 默认不选中), 将服务写入勾选的 agent 配置文件
|
|
39
|
+
|
|
40
|
+
#### Scenario: 服务不存在于中央仓库
|
|
41
|
+
|
|
42
|
+
- **WHEN** 用户执行 `mcpsmgr add nonexistent`
|
|
43
|
+
- **THEN** 系统报错, 提示服务不存在于中央仓库
|
|
44
|
+
|
|
45
|
+
#### Scenario: 部分 agent 同名冲突
|
|
46
|
+
|
|
47
|
+
- **WHEN** 添加时某些 agent 配置文件中已存在同名服务
|
|
48
|
+
- **THEN** 系统对冲突的 agent 报告跳过, 对无冲突的 agent 正常写入
|
|
49
|
+
|
|
50
|
+
### Requirement: 项目移除服务
|
|
51
|
+
|
|
52
|
+
系统 SHALL 支持 `mcpsmgr remove <server-name>` 命令, 从当前项目的 agent 配置中移除单个 MCP 服务配置.
|
|
53
|
+
|
|
54
|
+
#### Scenario: 从多个 agent 移除
|
|
55
|
+
|
|
56
|
+
- **WHEN** 用户执行 `mcpsmgr remove brave-search`
|
|
57
|
+
- **THEN** 系统列出包含该服务的所有 agent 配置, 供用户勾选要移除的 (其中 `isGlobal` 为 `true` 的 agent SHALL 默认不选中), 从勾选的 agent 配置文件中删除该服务条目, 保留文件中的其他内容. 未勾选的 agent SHALL NOT 被删除任何 MCP 配置
|
|
58
|
+
|
|
59
|
+
#### Scenario: 无 agent 包含该服务
|
|
60
|
+
|
|
61
|
+
- **WHEN** 用户执行 `mcpsmgr remove nonexistent` 但没有任何 agent 配置包含该服务
|
|
62
|
+
- **THEN** 系统提示未在任何 agent 配置中找到该服务
|
|
63
|
+
|
|
64
|
+
#### Scenario: 取消选中 agent 不删除 MCP
|
|
65
|
+
|
|
66
|
+
- **WHEN** 用户在 remove 交互中取消选中某个 agent
|
|
67
|
+
- **THEN** 系统 SHALL NOT 删除该 agent 中的任何 MCP 配置, 仅跳过该 agent
|
|
68
|
+
|
|
69
|
+
### Requirement: 同步中央仓库变更
|
|
70
|
+
|
|
71
|
+
系统 SHALL 支持 `mcpsmgr sync` 命令, 将中央仓库的服务配置同步到当前项目的 agent 配置文件.
|
|
72
|
+
|
|
73
|
+
#### Scenario: 同步更新
|
|
74
|
+
|
|
75
|
+
- **WHEN** 用户修改了中央仓库中的服务配置 (如更新了 API key) 后执行 `mcpsmgr sync`
|
|
76
|
+
- **THEN** 系统读取各 agent 配置文件中已有的 MCP 服务, 与中央仓库比对, 展示变更预览, 用户确认后更新 agent 配置文件中对应服务的配置
|
|
77
|
+
|
|
78
|
+
#### Scenario: 同名冲突处理
|
|
79
|
+
|
|
80
|
+
- **WHEN** sync 过程中发现某个 agent 配置中的服务名与中央仓库同名但非 mcpsmgr 管理 (用户手动添加的)
|
|
81
|
+
- **THEN** 系统报告冲突, 跳过该服务在该 agent 的同步
|
|
82
|
+
|
|
83
|
+
### Requirement: 列出项目 MCP 状态
|
|
84
|
+
|
|
85
|
+
系统 SHALL 支持 `mcpsmgr list` 命令, 展示当前项目各 agent 的 MCP 服务状态矩阵.
|
|
86
|
+
|
|
87
|
+
#### Scenario: 状态矩阵展示
|
|
88
|
+
|
|
89
|
+
- **WHEN** 用户在项目目录执行 `mcpsmgr list`
|
|
90
|
+
- **THEN** 系统扫描所有 agent 的实际配置文件, 解析出已配置的 MCP 服务, 以表格形式展示 (行: 服务名, 列: agent 名, 值: 是否存在及 transport 类型)
|
|
91
|
+
|
|
92
|
+
#### Scenario: 无 agent 配置文件
|
|
93
|
+
|
|
94
|
+
- **WHEN** 项目中没有任何 agent 配置文件
|
|
95
|
+
- **THEN** 系统提示未检测到任何 agent 配置, 建议执行 `mcpsmgr init`
|
|
96
|
+
|
|
97
|
+
### Requirement: 交互中断优雅退出
|
|
98
|
+
|
|
99
|
+
所有项目级交互式命令 (init, add, remove, sync) SHALL 在用户按 Ctrl-C 中断 prompt 时正常退出, 不输出错误信息, 退出码为 0.
|
|
100
|
+
|
|
101
|
+
#### Scenario: init 命令中按 Ctrl-C
|
|
102
|
+
|
|
103
|
+
- **WHEN** 用户在 `mcpsmgr init` 的任意 prompt 步骤中按 Ctrl-C
|
|
104
|
+
- **THEN** 系统 SHALL 静默退出, 不输出错误堆栈, 不修改任何配置文件, 进程退出码为 0
|
|
105
|
+
|
|
106
|
+
#### Scenario: add 命令中按 Ctrl-C
|
|
107
|
+
|
|
108
|
+
- **WHEN** 用户在 `mcpsmgr add <server>` 的 agent 选择 prompt 中按 Ctrl-C
|
|
109
|
+
- **THEN** 系统 SHALL 静默退出, 不输出错误堆栈, 不修改任何配置文件, 进程退出码为 0
|
|
110
|
+
|
|
111
|
+
#### Scenario: remove 命令中按 Ctrl-C
|
|
112
|
+
|
|
113
|
+
- **WHEN** 用户在 `mcpsmgr remove <server>` 的 agent 选择 prompt 中按 Ctrl-C
|
|
114
|
+
- **THEN** 系统 SHALL 静默退出, 不输出错误堆栈, 不修改任何配置文件, 进程退出码为 0
|
|
115
|
+
|
|
116
|
+
#### Scenario: sync 命令中按 Ctrl-C
|
|
117
|
+
|
|
118
|
+
- **WHEN** 用户在 `mcpsmgr sync` 的确认 prompt 中按 Ctrl-C
|
|
119
|
+
- **THEN** 系统 SHALL 静默退出, 不输出错误堆栈, 不修改任何配置文件, 进程退出码为 0
|
|
120
|
+
|
|
121
|
+
#### Scenario: setup 命令中按 Ctrl-C
|
|
122
|
+
|
|
123
|
+
- **WHEN** 用户在 `mcpsmgr setup` 的任意 prompt 步骤中按 Ctrl-C
|
|
124
|
+
- **THEN** 系统 SHALL 静默退出, 不输出错误堆栈, 不修改任何配置文件, 进程退出码为 0
|
|
125
|
+
|
|
126
|
+
### Requirement: init 命令中取消勾选已检测服务触发删除
|
|
127
|
+
|
|
128
|
+
系统 SHALL 在 `mcpsmgr init` 中, 当用户取消勾选已检测到的 MCP 服务时, 将其视为删除意图, 在操作计划中展示并在确认后执行删除.
|
|
129
|
+
|
|
130
|
+
#### Scenario: 取消勾选已检测服务
|
|
131
|
+
|
|
132
|
+
- **WHEN** 用户在 `mcpsmgr init` 的服务选择步骤中, 取消勾选一个已被检测到 (标记为 `(detected)`) 的服务
|
|
133
|
+
- **THEN** 系统 SHALL 在操作计划中以 `- <server-name>` 格式展示该服务将被删除, 并在用户确认后, 从对应 agent 配置中移除该服务
|
|
134
|
+
|
|
135
|
+
#### Scenario: 仅从包含该服务的 agent 中删除
|
|
136
|
+
|
|
137
|
+
- **WHEN** 用户取消勾选一个已检测服务, 且多个已选 agent 中只有部分包含该服务
|
|
138
|
+
- **THEN** 系统 SHALL 仅从实际包含该服务的 agent 配置中执行删除, 不影响不包含该服务的 agent
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
## Purpose
|
|
2
|
+
|
|
3
|
+
管理中央仓库中 MCP 服务定义的添加, 移除和列出, 包括通过 GLM5 分析文档自动生成配置.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
### Requirement: 通过 URL 添加 MCP 服务
|
|
8
|
+
|
|
9
|
+
系统 SHALL 支持 `mcpsmgr server add <url-or-repo>` 命令, 通过 URL 或 GitHub `owner/repo` 简写添加 MCP 服务到中央仓库.
|
|
10
|
+
|
|
11
|
+
#### Scenario: 使用 GitHub 简写添加
|
|
12
|
+
|
|
13
|
+
- **WHEN** 用户执行 `mcpsmgr server add anthropics/mcp-brave-search`
|
|
14
|
+
- **THEN** 系统将 `anthropics/mcp-brave-search` 扩展为 `https://github.com/anthropics/mcp-brave-search`, 优先获取 README.md 内容, 调用 GLM5 分析文档, 提取服务名和配置, 展示分析结果供用户确认
|
|
15
|
+
|
|
16
|
+
#### Scenario: 使用完整 URL 添加
|
|
17
|
+
|
|
18
|
+
- **WHEN** 用户执行 `mcpsmgr server add https://docs.bigmodel.cn/cn/coding-plan/mcp/search-mcp-server`
|
|
19
|
+
- **THEN** 系统直接将 URL 传递给 GLM5 分析, 提取服务名和配置
|
|
20
|
+
|
|
21
|
+
#### Scenario: 不支持的输入格式
|
|
22
|
+
|
|
23
|
+
- **WHEN** 用户执行 `mcpsmgr server add @scope/package` 或 `mcpsmgr server add bare-name`
|
|
24
|
+
- **THEN** 系统报错, 提示需要提供 URL 或 `owner/repo` 格式
|
|
25
|
+
|
|
26
|
+
### Requirement: 同名服务检测
|
|
27
|
+
|
|
28
|
+
系统 SHALL 在添加服务时检测中央仓库中是否已存在同名服务.
|
|
29
|
+
|
|
30
|
+
#### Scenario: 中央仓库同名冲突
|
|
31
|
+
|
|
32
|
+
- **WHEN** 用户添加的服务名与 `~/.mcps-manager/servers/` 中已有服务同名
|
|
33
|
+
- **THEN** 系统报错, 提示服务已存在并建议先执行 `mcpsmgr server remove <name>`
|
|
34
|
+
|
|
35
|
+
### Requirement: GLM5 分析结果确认
|
|
36
|
+
|
|
37
|
+
系统 SHALL 展示 GLM5 的分析结果, 让用户选择是否信任.
|
|
38
|
+
|
|
39
|
+
#### Scenario: 用户信任分析结果
|
|
40
|
+
|
|
41
|
+
- **WHEN** GLM5 返回分析结果且用户选择信任
|
|
42
|
+
- **THEN** 系统使用分析结果中的配置, 交互式要求用户输入 requiredEnvVars 中的值 (每次按键以 `*` 显示, 支持粘贴), 提示信息中 SHALL 包含安全说明 "stored locally, never sent to servers", 输入的值不会传递给 GLM5 或其他 LLM, 直接按已生成的配置保存到中央仓库
|
|
43
|
+
|
|
44
|
+
#### Scenario: 用户不信任分析结果
|
|
45
|
+
|
|
46
|
+
- **WHEN** GLM5 返回分析结果且用户选择不信任
|
|
47
|
+
- **THEN** 系统回退到手动配置模式, 要求用户逐项输入 transport, command, args, env 等信息
|
|
48
|
+
|
|
49
|
+
### Requirement: 无文档 URL 回退
|
|
50
|
+
|
|
51
|
+
系统 SHALL 支持不提供文档 URL 时的手动配置.
|
|
52
|
+
|
|
53
|
+
#### Scenario: 文档 URL 留空
|
|
54
|
+
|
|
55
|
+
- **WHEN** 用户在添加流程中文档 URL 留空
|
|
56
|
+
- **THEN** 系统进入手动配置模式, 不调用 GLM5, 不生成 overrides, 仅保存 default 配置
|
|
57
|
+
|
|
58
|
+
### Requirement: 移除 MCP 服务
|
|
59
|
+
|
|
60
|
+
系统 SHALL 支持 `mcpsmgr server remove <name>` 命令, 从中央仓库删除服务定义.
|
|
61
|
+
|
|
62
|
+
#### Scenario: 成功移除
|
|
63
|
+
|
|
64
|
+
- **WHEN** 用户执行 `mcpsmgr server remove brave-search` 且服务存在
|
|
65
|
+
- **THEN** 系统删除 `~/.mcps-manager/servers/brave-search.json`
|
|
66
|
+
|
|
67
|
+
#### Scenario: 服务不存在
|
|
68
|
+
|
|
69
|
+
- **WHEN** 用户执行 `mcpsmgr server remove nonexistent`
|
|
70
|
+
- **THEN** 系统报错, 提示服务不存在
|
|
71
|
+
|
|
72
|
+
### Requirement: 列出中央仓库服务
|
|
73
|
+
|
|
74
|
+
系统 SHALL 支持 `mcpsmgr server list` 命令, 列出中央仓库中所有已保存的服务.
|
|
75
|
+
|
|
76
|
+
#### Scenario: 列出所有服务
|
|
77
|
+
|
|
78
|
+
- **WHEN** 用户执行 `mcpsmgr server list`
|
|
79
|
+
- **THEN** 系统读取 `~/.mcps-manager/servers/` 下所有 JSON 文件, 展示服务名, 来源, transport 类型, 是否有 overrides
|
|
80
|
+
|
|
81
|
+
### Requirement: server-add 交互中断优雅退出
|
|
82
|
+
|
|
83
|
+
`mcpsmgr server add` 命令 SHALL 在用户按 Ctrl-C 中断任意 prompt 时正常退出, 不输出错误信息, 退出码为 0.
|
|
84
|
+
|
|
85
|
+
#### Scenario: 自动模式中按 Ctrl-C
|
|
86
|
+
|
|
87
|
+
- **WHEN** 用户在 `mcpsmgr server add <url>` 的 GLM 分析确认或环境变量输入 prompt 中按 Ctrl-C
|
|
88
|
+
- **THEN** 系统 SHALL 静默退出, 不输出错误堆栈, 不保存任何服务配置, 进程退出码为 0
|
|
89
|
+
|
|
90
|
+
#### Scenario: 手动模式中按 Ctrl-C
|
|
91
|
+
|
|
92
|
+
- **WHEN** 用户在手动配置模式的任意 prompt 中按 Ctrl-C
|
|
93
|
+
- **THEN** 系统 SHALL 静默退出, 不输出错误堆栈, 不保存任何服务配置, 进程退出码为 0
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcpsmgr",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Unified MCP server manager for multiple coding agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mcpsmgr": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"mcp",
|
|
11
|
+
"cli",
|
|
12
|
+
"agent"
|
|
13
|
+
],
|
|
14
|
+
"author": "",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@inquirer/prompts": "^8.3.0",
|
|
18
|
+
"commander": "^14.0.3",
|
|
19
|
+
"smol-toml": "^1.6.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^25.4.0",
|
|
23
|
+
"tsup": "^8.5.1",
|
|
24
|
+
"typescript": "^5.9.3",
|
|
25
|
+
"vitest": "^4.0.18"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsup",
|
|
29
|
+
"dev": "tsup --watch",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest"
|
|
32
|
+
}
|
|
33
|
+
}
|