@maplezzk/mcps 1.1.6 → 1.4.1
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/README.md +110 -380
- package/README.zh.md +370 -0
- package/dist/commands/call.js +75 -18
- package/dist/tests/unit/call.test.js +111 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,61 +1,60 @@
|
|
|
1
1
|
# mcps - MCP CLI Manager
|
|
2
2
|
|
|
3
|
-
[English](./
|
|
3
|
+
[English](./README.md) | [简体中文](./README.zh.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A powerful command-line interface for managing and interacting with [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Features
|
|
8
8
|
|
|
9
|
-
- 🔌
|
|
10
|
-
- 🛠️
|
|
11
|
-
- 🚀
|
|
12
|
-
- 🔄
|
|
13
|
-
- 📊
|
|
14
|
-
- 🔍
|
|
15
|
-
- 🚨
|
|
16
|
-
- ✅ **自动化测试**:完整的测试套件,确保代码质量
|
|
9
|
+
- 🔌 **Server Management**: Easily add, remove, list, and update MCP servers (Stdio, SSE, and HTTP modes)
|
|
10
|
+
- 🛠️ **Tool Discovery**: List available tools from any configured server
|
|
11
|
+
- 🚀 **Tool Execution**: Call tools directly from the CLI with automatic argument parsing
|
|
12
|
+
- 🔄 **Daemon Mode**: Maintain persistent connections to MCP servers for better performance
|
|
13
|
+
- 📊 **Table Output**: Clear server status and tool listings
|
|
14
|
+
- 🔍 **Tool Filtering**: Filter tools by keywords with simple mode
|
|
15
|
+
- 🚨 **Verbose Logging**: Optional detailed logging for debugging
|
|
17
16
|
|
|
18
|
-
##
|
|
17
|
+
## Installation
|
|
19
18
|
|
|
20
19
|
```bash
|
|
21
20
|
npm install -g @maplezzk/mcps
|
|
22
21
|
```
|
|
23
22
|
|
|
24
|
-
##
|
|
23
|
+
## Quick Start
|
|
25
24
|
|
|
26
25
|
```bash
|
|
27
|
-
# 1.
|
|
26
|
+
# 1. Add a server
|
|
28
27
|
mcps add fetch --command uvx --args mcp-server-fetch
|
|
29
28
|
|
|
30
|
-
# 2.
|
|
29
|
+
# 2. Start the daemon
|
|
31
30
|
mcps start
|
|
32
31
|
|
|
33
|
-
# 3.
|
|
32
|
+
# 3. Check server status
|
|
34
33
|
mcps status
|
|
35
34
|
|
|
36
|
-
# 4.
|
|
35
|
+
# 4. List available tools
|
|
37
36
|
mcps tools fetch
|
|
38
37
|
|
|
39
|
-
# 5.
|
|
38
|
+
# 5. Call a tool
|
|
40
39
|
mcps call fetch fetch url="https://example.com"
|
|
41
40
|
```
|
|
42
41
|
|
|
43
|
-
##
|
|
42
|
+
## Usage Guide
|
|
44
43
|
|
|
45
|
-
### 1.
|
|
44
|
+
### 1. Daemon Mode
|
|
46
45
|
|
|
47
|
-
mcps
|
|
46
|
+
mcps supports a daemon mode that maintains persistent connections to MCP servers, significantly improving performance for frequent calls.
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
**Start Daemon:**
|
|
50
49
|
```bash
|
|
51
|
-
#
|
|
50
|
+
# Normal mode
|
|
52
51
|
mcps start
|
|
53
52
|
|
|
54
|
-
#
|
|
53
|
+
# Verbose mode (show connection process for each server and disabled servers)
|
|
55
54
|
mcps start --verbose
|
|
56
55
|
```
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
Output example:
|
|
59
58
|
```
|
|
60
59
|
Starting daemon in background...
|
|
61
60
|
[Daemon] Connecting to 7 server(s)...
|
|
@@ -66,26 +65,26 @@ Starting daemon in background...
|
|
|
66
65
|
Daemon started successfully on port 4100.
|
|
67
66
|
```
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
**Restart Connections:**
|
|
70
69
|
```bash
|
|
71
|
-
#
|
|
70
|
+
# Reset all connections
|
|
72
71
|
mcps restart
|
|
73
72
|
|
|
74
|
-
#
|
|
73
|
+
# Reset connection for a specific server
|
|
75
74
|
mcps restart my-server
|
|
76
75
|
```
|
|
77
76
|
|
|
78
|
-
|
|
77
|
+
**Stop Daemon:**
|
|
79
78
|
```bash
|
|
80
79
|
mcps stop
|
|
81
80
|
```
|
|
82
81
|
|
|
83
|
-
|
|
82
|
+
**Check Daemon Status:**
|
|
84
83
|
```bash
|
|
85
84
|
mcps status
|
|
86
85
|
```
|
|
87
86
|
|
|
88
|
-
|
|
87
|
+
Output example:
|
|
89
88
|
```
|
|
90
89
|
Daemon is running (v1.0.29)
|
|
91
90
|
|
|
@@ -98,14 +97,14 @@ gitlab-mr-creator Connected 30
|
|
|
98
97
|
Total: 3 connection(s)
|
|
99
98
|
```
|
|
100
99
|
|
|
101
|
-
### 2.
|
|
100
|
+
### 2. Server Management
|
|
102
101
|
|
|
103
|
-
|
|
102
|
+
**List all servers (configuration):**
|
|
104
103
|
```bash
|
|
105
104
|
mcps ls
|
|
106
105
|
```
|
|
107
106
|
|
|
108
|
-
|
|
107
|
+
Output example:
|
|
109
108
|
```
|
|
110
109
|
NAME TYPE ENABLED COMMAND/URL
|
|
111
110
|
───────────────── ────── ─────── ─────────────
|
|
@@ -115,66 +114,66 @@ my-server stdio ✗ npx my-server
|
|
|
115
114
|
Total: 3 server(s)
|
|
116
115
|
```
|
|
117
116
|
|
|
118
|
-
|
|
117
|
+
**Add Stdio Server:**
|
|
119
118
|
```bash
|
|
120
|
-
#
|
|
119
|
+
# Add local Node.js server
|
|
121
120
|
mcps add my-server --command node --args ./build/index.js
|
|
122
121
|
|
|
123
|
-
#
|
|
122
|
+
# Use npx/uvx to add server
|
|
124
123
|
mcps add fetch --command uvx --args mcp-server-fetch
|
|
125
124
|
|
|
126
|
-
#
|
|
125
|
+
# Add server with environment variables
|
|
127
126
|
mcps add my-db --command npx --args @modelcontextprotocol/server-postgres --env POSTGRES_CONNECTION_STRING="${DATABASE_URL}"
|
|
128
127
|
```
|
|
129
128
|
|
|
130
|
-
|
|
129
|
+
**Add SSE Server:**
|
|
131
130
|
```bash
|
|
132
131
|
mcps add remote-server --type sse --url http://localhost:8000/sse
|
|
133
132
|
```
|
|
134
133
|
|
|
135
|
-
|
|
134
|
+
**Add Streamable HTTP Server:**
|
|
136
135
|
```bash
|
|
137
136
|
mcps add my-http-server --type http --url http://localhost:8000/mcp
|
|
138
137
|
```
|
|
139
138
|
|
|
140
|
-
|
|
139
|
+
**Remove Server:**
|
|
141
140
|
```bash
|
|
142
141
|
mcps rm my-server
|
|
143
142
|
```
|
|
144
143
|
|
|
145
|
-
|
|
144
|
+
**Update Server:**
|
|
146
145
|
```bash
|
|
147
|
-
#
|
|
146
|
+
# Refresh all server connections
|
|
148
147
|
mcps update
|
|
149
148
|
|
|
150
|
-
#
|
|
149
|
+
# Update specific server command
|
|
151
150
|
mcps update my-server --command new-command
|
|
152
151
|
|
|
153
|
-
#
|
|
152
|
+
# Update specific server arguments
|
|
154
153
|
mcps update my-server --args arg1 arg2
|
|
155
154
|
|
|
156
|
-
#
|
|
155
|
+
# Update both command and arguments
|
|
157
156
|
mcps update my-server --command node --args ./new-build/index.js
|
|
158
157
|
```
|
|
159
158
|
|
|
160
|
-
### 3.
|
|
159
|
+
### 3. Tool Interaction
|
|
161
160
|
|
|
162
|
-
|
|
161
|
+
**List available tools on a server:**
|
|
163
162
|
```bash
|
|
164
|
-
#
|
|
163
|
+
# Detailed mode (show all information)
|
|
165
164
|
mcps tools chrome-devtools
|
|
166
165
|
|
|
167
|
-
#
|
|
166
|
+
# Simple mode (show only tool names)
|
|
168
167
|
mcps tools chrome-devtools --simple
|
|
169
168
|
|
|
170
|
-
#
|
|
169
|
+
# Filter tools by keyword
|
|
171
170
|
mcps tools chrome-devtools --tool screenshot
|
|
172
171
|
|
|
173
|
-
#
|
|
172
|
+
# Multiple keywords + simple mode
|
|
174
173
|
mcps tools gitlab-mr-creator --tool file --tool wiki --simple
|
|
175
174
|
```
|
|
176
175
|
|
|
177
|
-
|
|
176
|
+
Detailed mode output example:
|
|
178
177
|
```
|
|
179
178
|
Available Tools for chrome-devtools:
|
|
180
179
|
|
|
@@ -193,7 +192,7 @@ Available Tools for chrome-devtools:
|
|
|
193
192
|
...
|
|
194
193
|
```
|
|
195
194
|
|
|
196
|
-
|
|
195
|
+
Simple mode output example:
|
|
197
196
|
```
|
|
198
197
|
$ mcps tools chrome-devtools -s
|
|
199
198
|
click
|
|
@@ -209,43 +208,43 @@ take_snapshot
|
|
|
209
208
|
Total: 26 tool(s)
|
|
210
209
|
```
|
|
211
210
|
|
|
212
|
-
|
|
211
|
+
**Call Tools:**
|
|
213
212
|
|
|
214
|
-
|
|
213
|
+
Syntax:
|
|
215
214
|
```bash
|
|
216
215
|
mcps call <server_name> <tool_name> [arguments...]
|
|
217
216
|
```
|
|
218
217
|
|
|
219
|
-
- `<server_name>`:
|
|
220
|
-
- `<tool_name>`:
|
|
221
|
-
- `[arguments...]`:
|
|
218
|
+
- `<server_name>`: Name of the configured MCP server
|
|
219
|
+
- `<tool_name>`: Name of the tool to call
|
|
220
|
+
- `[arguments...]`: Arguments passed as `key=value` pairs. The CLI attempts to automatically parse values as JSON (numbers, booleans, objects).
|
|
222
221
|
|
|
223
|
-
|
|
222
|
+
Examples:
|
|
224
223
|
```bash
|
|
225
|
-
#
|
|
224
|
+
# Simple string argument
|
|
226
225
|
mcps call fetch fetch url="https://example.com"
|
|
227
226
|
|
|
228
|
-
#
|
|
227
|
+
# Multiple arguments
|
|
229
228
|
mcps call fetch fetch url="https://example.com" max_length=5000
|
|
230
229
|
|
|
231
|
-
# JSON
|
|
230
|
+
# JSON object argument
|
|
232
231
|
mcps call my-server createUser user='{"name": "Alice", "age": 30}'
|
|
233
232
|
|
|
234
|
-
#
|
|
233
|
+
# Boolean/number arguments
|
|
235
234
|
mcps call chrome-devtools take_screenshot fullPage=true quality=90
|
|
236
235
|
|
|
237
|
-
#
|
|
236
|
+
# Mixed arguments
|
|
238
237
|
mcps call my-server config debug=true timeout=5000 options='{"retries": 3}'
|
|
239
238
|
```
|
|
240
239
|
|
|
241
|
-
##
|
|
240
|
+
## Configuration File
|
|
242
241
|
|
|
243
|
-
|
|
242
|
+
By default, the configuration file is stored at:
|
|
244
243
|
`~/.mcps/mcp.json`
|
|
245
244
|
|
|
246
|
-
|
|
245
|
+
You can change the storage location by setting the `MCPS_CONFIG_DIR` environment variable.
|
|
247
246
|
|
|
248
|
-
|
|
247
|
+
Configuration file example:
|
|
249
248
|
```json
|
|
250
249
|
{
|
|
251
250
|
"servers": [
|
|
@@ -269,343 +268,74 @@ mcps call my-server config debug=true timeout=5000 options='{"retries": 3}'
|
|
|
269
268
|
}
|
|
270
269
|
```
|
|
271
270
|
|
|
272
|
-
##
|
|
271
|
+
## Environment Variables
|
|
273
272
|
|
|
274
|
-
- `MCPS_CONFIG_DIR`:
|
|
275
|
-
- `MCPS_PORT`: Daemon
|
|
276
|
-
- `MCPS_VERBOSE`:
|
|
273
|
+
- `MCPS_CONFIG_DIR`: Configuration file directory (default: `~/.mcps`)
|
|
274
|
+
- `MCPS_PORT`: Daemon port (default: `4100`)
|
|
275
|
+
- `MCPS_VERBOSE`: Verbose logging mode (default: `false`)
|
|
277
276
|
|
|
278
|
-
##
|
|
277
|
+
## Command Reference
|
|
279
278
|
|
|
280
|
-
###
|
|
281
|
-
- `mcps ls` -
|
|
282
|
-
- `mcps add <name>` -
|
|
283
|
-
- `mcps rm <name>` -
|
|
284
|
-
- `mcps update [name]` -
|
|
279
|
+
### Server Management
|
|
280
|
+
- `mcps ls` - List all servers
|
|
281
|
+
- `mcps add <name>` - Add a new server
|
|
282
|
+
- `mcps rm <name>` - Remove a server
|
|
283
|
+
- `mcps update [name]` - Update server configuration
|
|
285
284
|
|
|
286
|
-
###
|
|
287
|
-
- `mcps start [-v]` -
|
|
288
|
-
- `mcps stop` -
|
|
289
|
-
- `mcps status` -
|
|
290
|
-
- `mcps restart [server]` -
|
|
285
|
+
### Daemon
|
|
286
|
+
- `mcps start [-v]` - Start daemon (`-v` for detailed logging)
|
|
287
|
+
- `mcps stop` - Stop daemon
|
|
288
|
+
- `mcps status` - Check daemon status
|
|
289
|
+
- `mcps restart [server]` - Restart daemon or specific server
|
|
291
290
|
|
|
292
|
-
###
|
|
293
|
-
- `mcps tools <server> [-s] [-t <name>...]` -
|
|
294
|
-
- `-s, --simple`:
|
|
295
|
-
- `-t, --tool`:
|
|
296
|
-
- `mcps call <server> <tool> [args...]` -
|
|
291
|
+
### Tool Interaction
|
|
292
|
+
- `mcps tools <server> [-s] [-t <name>...]` - List available tools
|
|
293
|
+
- `-s, --simple`: Show only tool names
|
|
294
|
+
- `-t, --tool`: Filter tools by name (can be used multiple times)
|
|
295
|
+
- `mcps call <server> <tool> [args...]` - Call a tool
|
|
297
296
|
|
|
298
|
-
##
|
|
297
|
+
## Performance
|
|
299
298
|
|
|
300
|
-
mcps
|
|
299
|
+
mcps optimizes performance through:
|
|
301
300
|
|
|
302
|
-
1.
|
|
303
|
-
2.
|
|
304
|
-
3.
|
|
301
|
+
1. **Daemon Mode**: Maintains persistent connections, avoiding repeated startup overhead
|
|
302
|
+
2. **Tool Caching**: Caches tool counts during connection, avoiding repeated queries
|
|
303
|
+
3. **Async Connections**: Parallel initialization of multiple server connections
|
|
305
304
|
|
|
306
|
-
|
|
307
|
-
-
|
|
308
|
-
-
|
|
309
|
-
-
|
|
305
|
+
Typical performance:
|
|
306
|
+
- Start daemon: 10-15 seconds (first time, depends on server count)
|
|
307
|
+
- Check status: ~200ms
|
|
308
|
+
- Call tool: ~50-100ms
|
|
310
309
|
|
|
311
|
-
##
|
|
310
|
+
## FAQ
|
|
312
311
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
### 环境准备
|
|
316
|
-
|
|
317
|
-
**前置要求:**
|
|
318
|
-
- Node.js >= 20
|
|
319
|
-
- npm >= 9
|
|
320
|
-
- Git
|
|
321
|
-
|
|
322
|
-
**克隆项目:**
|
|
323
|
-
```bash
|
|
324
|
-
git clone https://github.com/a13835614623/mcps.git
|
|
325
|
-
cd mcps
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
**安装依赖:**
|
|
329
|
-
```bash
|
|
330
|
-
npm install
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### 本地开发
|
|
334
|
-
|
|
335
|
-
**开发模式(使用 ts-node 直接运行):**
|
|
336
|
-
```bash
|
|
337
|
-
npm run dev -- <command>
|
|
338
|
-
# 例如
|
|
339
|
-
npm run dev -- ls
|
|
340
|
-
npm run dev -- start
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
**构建项目:**
|
|
344
|
-
```bash
|
|
345
|
-
npm run build
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
**运行构建后的版本:**
|
|
349
|
-
```bash
|
|
350
|
-
npm start -- <command>
|
|
351
|
-
# 或者
|
|
352
|
-
node dist/index.js <command>
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
### 测试
|
|
356
|
-
|
|
357
|
-
**运行测试:**
|
|
358
|
-
```bash
|
|
359
|
-
# 运行所有测试
|
|
360
|
-
npm test
|
|
361
|
-
|
|
362
|
-
# 监听模式(开发时推荐)
|
|
363
|
-
npm run test:watch
|
|
364
|
-
|
|
365
|
-
# 启动测试 UI 界面
|
|
366
|
-
npm run test:ui
|
|
367
|
-
|
|
368
|
-
# 生成测试覆盖率报告
|
|
369
|
-
npm run test:coverage
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
**测试要求:**
|
|
373
|
-
- 所有测试必须通过
|
|
374
|
-
- 新功能需要添加相应的测试
|
|
375
|
-
- 保持测试覆盖率在合理水平
|
|
376
|
-
|
|
377
|
-
### 提交规范
|
|
378
|
-
|
|
379
|
-
**提交信息格式:**
|
|
380
|
-
```
|
|
381
|
-
<type>: <description>
|
|
382
|
-
|
|
383
|
-
[optional body]
|
|
384
|
-
|
|
385
|
-
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
**提交类型(type):**
|
|
389
|
-
- `feat`: 新功能
|
|
390
|
-
- `fix`: 修复 bug
|
|
391
|
-
- `chore`: 构建过程或辅助工具的变动
|
|
392
|
-
- `docs`: 文档更新
|
|
393
|
-
- `refactor`: 重构(既不是新增功能,也不是修复 bug)
|
|
394
|
-
- `style`: 代码格式调整(不影响代码运行的变动)
|
|
395
|
-
- `test`: 增加测试
|
|
396
|
-
- `perf`: 性能优化
|
|
397
|
-
|
|
398
|
-
**示例:**
|
|
399
|
-
```bash
|
|
400
|
-
feat: 支持可配置的 daemon 启动超时时间
|
|
401
|
-
|
|
402
|
-
新增功能:
|
|
403
|
-
- 支持通过命令行参数 --timeout/-t 设置超时
|
|
404
|
-
- 支持通过环境变量 MCPS_DAEMON_TIMEOUT 设置超时
|
|
405
|
-
- 支持通过配置文件 daemonTimeout 字段设置超时
|
|
406
|
-
|
|
407
|
-
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
### PR 流程
|
|
411
|
-
|
|
412
|
-
**1. 创建功能分支:**
|
|
413
|
-
```bash
|
|
414
|
-
git checkout -b feature/your-feature-name
|
|
415
|
-
# 或
|
|
416
|
-
git checkout -b fix/your-bug-fix
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
**分支命名规范:**
|
|
420
|
-
- `feature/` - 新功能
|
|
421
|
-
- `fix/` - bug 修复
|
|
422
|
-
- `refactor/` - 重构
|
|
423
|
-
- `docs/` - 文档更新
|
|
424
|
-
- `chore/` - 构建/工具更新
|
|
425
|
-
|
|
426
|
-
**2. 开发并提交:**
|
|
427
|
-
```bash
|
|
428
|
-
# 进行开发...
|
|
429
|
-
npm run build # 确保构建成功
|
|
430
|
-
npm test # 确保测试通过
|
|
431
|
-
|
|
432
|
-
# 提交代码
|
|
433
|
-
git add .
|
|
434
|
-
git commit -m "feat: 你的功能描述"
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
**3. 更新版本号(如需要):**
|
|
438
|
-
```bash
|
|
439
|
-
# Patch 版本(bug 修复)
|
|
440
|
-
npm version patch
|
|
441
|
-
|
|
442
|
-
# Minor 版本(新功能)
|
|
443
|
-
npm version minor
|
|
444
|
-
|
|
445
|
-
# Major 版本(破坏性变更)
|
|
446
|
-
npm version major
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
**4. 推送并创建 PR:**
|
|
450
|
-
```bash
|
|
451
|
-
git push origin feature/your-feature-name
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
然后访问 GitHub 创建 Pull Request,或在命令行使用:
|
|
455
|
-
```bash
|
|
456
|
-
gh pr create --title "feat: 功能标题" --body "PR 描述"
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
**5. PR 检查清单:**
|
|
460
|
-
- ✅ CI 测试通过(GitHub Actions)
|
|
461
|
-
- ✅ 代码通过所有测试
|
|
462
|
-
- ✅ 新功能有对应的测试
|
|
463
|
-
- ✅ 提交信息符合规范
|
|
464
|
-
- ✅ PR 描述清晰说明了变更内容
|
|
465
|
-
- ✅ 版本号已正确更新(如需要)
|
|
466
|
-
|
|
467
|
-
**6. 解决冲突(如有):**
|
|
468
|
-
```bash
|
|
469
|
-
# 如果 main 分支有更新,先合并最新代码
|
|
470
|
-
git fetch origin
|
|
471
|
-
git merge origin/main
|
|
472
|
-
|
|
473
|
-
# 解决冲突后
|
|
474
|
-
git add .
|
|
475
|
-
git commit -m "chore: merge main and resolve conflicts"
|
|
476
|
-
git push origin feature/your-feature-name
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
### 发布流程
|
|
480
|
-
|
|
481
|
-
项目采用**自动化发布**流程:
|
|
482
|
-
|
|
483
|
-
**1. 版本管理:**
|
|
484
|
-
- 修改 `package.json` 中的版本号
|
|
485
|
-
- 或使用 `npm version` 命令
|
|
486
|
-
|
|
487
|
-
**2. 发布触发:**
|
|
488
|
-
- 当 PR 合并到 `main` 分支时
|
|
489
|
-
- 如果版本号发生变化
|
|
490
|
-
- GitHub Actions 自动发布到 npm
|
|
491
|
-
|
|
492
|
-
**3. 版本号规则:**
|
|
493
|
-
- `1.0.0` → `1.0.1` (Patch): bug 修复
|
|
494
|
-
- `1.0.1` → `1.1.0` (Minor): 新功能
|
|
495
|
-
- `1.1.0` → `2.0.0` (Major): 破坏性变更
|
|
496
|
-
|
|
497
|
-
**4. 预发布版本(可选):**
|
|
498
|
-
```bash
|
|
499
|
-
npm version prerelease --preid beta
|
|
500
|
-
# 生成 1.0.0-beta.0
|
|
501
|
-
```
|
|
502
|
-
|
|
503
|
-
预发布版本会发布到 npm 的 `beta` tag。
|
|
504
|
-
|
|
505
|
-
**5. 跳过发布:**
|
|
506
|
-
如果 PR 不需要发布,在标题中添加 `[skip release]`:
|
|
507
|
-
```
|
|
508
|
-
[skip release] chore: 更新文档
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
### CI/CD
|
|
512
|
-
|
|
513
|
-
**CI 检查(.github/workflows/ci.yml):**
|
|
514
|
-
- 每次 PR 和 push 都会触发
|
|
515
|
-
- 运行测试套件
|
|
516
|
-
- 构建项目
|
|
517
|
-
- 确保代码质量
|
|
518
|
-
|
|
519
|
-
**Release 自动化(.github/workflows/release.yml):**
|
|
520
|
-
- PR 合并后触发
|
|
521
|
-
- 检测版本号变化
|
|
522
|
-
- 自动发布到 npm
|
|
523
|
-
- 创建 GitHub Release
|
|
524
|
-
|
|
525
|
-
### 代码规范
|
|
526
|
-
|
|
527
|
-
**TypeScript:**
|
|
528
|
-
- 使用 TypeScript 进行类型检查
|
|
529
|
-
- 运行 `npm run build` 检查类型错误
|
|
530
|
-
|
|
531
|
-
**代码风格:**
|
|
532
|
-
- 遵循项目现有代码风格
|
|
533
|
-
- 使用有意义的变量和函数名
|
|
534
|
-
- 添加必要的注释
|
|
535
|
-
|
|
536
|
-
**项目结构:**
|
|
537
|
-
```
|
|
538
|
-
mcps/
|
|
539
|
-
├── src/
|
|
540
|
-
│ ├── commands/ # 命令实现
|
|
541
|
-
│ ├── core/ # 核心功能
|
|
542
|
-
│ ├── types/ # 类型定义
|
|
543
|
-
│ └── index.ts # 入口文件
|
|
544
|
-
├── test/ # 测试文件
|
|
545
|
-
├── dist/ # 构建输出
|
|
546
|
-
└── package.json
|
|
547
|
-
```
|
|
548
|
-
|
|
549
|
-
### 常见问题(开发)
|
|
550
|
-
|
|
551
|
-
**Q: 如何调试代码?**
|
|
552
|
-
```bash
|
|
553
|
-
# 使用开发模式运行
|
|
554
|
-
npm run dev -- start --verbose
|
|
555
|
-
|
|
556
|
-
# 或构建后直接运行
|
|
557
|
-
npm run build
|
|
558
|
-
node --inspect dist/index.js <command>
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
**Q: 测试失败了怎么办?**
|
|
562
|
-
```bash
|
|
563
|
-
# 运行特定测试文件
|
|
564
|
-
npm test -- <test-file>
|
|
565
|
-
|
|
566
|
-
# 查看详细输出
|
|
567
|
-
npm test -- --reporter=verbose
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
**Q: 如何本地测试 npm 包?**
|
|
571
|
-
```bash
|
|
572
|
-
# 在项目根目录
|
|
573
|
-
npm link
|
|
574
|
-
|
|
575
|
-
# 在其他项目中使用
|
|
576
|
-
npm link @maplezzk/mcps
|
|
577
|
-
mcps ls
|
|
578
|
-
```
|
|
579
|
-
|
|
580
|
-
## 常见问题
|
|
581
|
-
|
|
582
|
-
**Q: 如何查看所有服务器的运行状态?**
|
|
312
|
+
**Q: How to check the status of all servers?**
|
|
583
313
|
```bash
|
|
584
|
-
mcps status #
|
|
585
|
-
mcps ls #
|
|
314
|
+
mcps status # Check active connections
|
|
315
|
+
mcps ls # Check all configurations (including disabled)
|
|
586
316
|
```
|
|
587
317
|
|
|
588
|
-
**Q:
|
|
318
|
+
**Q: What if a server fails to connect?**
|
|
589
319
|
```bash
|
|
590
|
-
#
|
|
320
|
+
# View detailed logs
|
|
591
321
|
mcps start --verbose
|
|
592
322
|
|
|
593
|
-
#
|
|
323
|
+
# Restart that server
|
|
594
324
|
mcps restart my-server
|
|
595
325
|
```
|
|
596
326
|
|
|
597
|
-
**Q:
|
|
598
|
-
|
|
327
|
+
**Q: How to temporarily disable a server?**
|
|
328
|
+
Set `"disabled": true` in the configuration file, or use `mcps update` to modify the configuration.
|
|
599
329
|
|
|
600
|
-
**Q:
|
|
330
|
+
**Q: How to quickly find tools when there are many?**
|
|
601
331
|
```bash
|
|
602
|
-
#
|
|
332
|
+
# Filter tools by keyword
|
|
603
333
|
mcps tools my-server --tool keyword
|
|
604
334
|
|
|
605
|
-
#
|
|
335
|
+
# Show only names
|
|
606
336
|
mcps tools my-server --simple
|
|
607
337
|
```
|
|
608
338
|
|
|
609
|
-
##
|
|
339
|
+
## License
|
|
610
340
|
|
|
611
341
|
ISC
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
# mcps - MCP CLI Manager
|
|
2
|
+
|
|
3
|
+
[English](./README.md) | [简体中文](./README.zh.md)
|
|
4
|
+
|
|
5
|
+
一个用于管理和交互 [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) 服务的强大命令行工具。
|
|
6
|
+
|
|
7
|
+
## 功能特性
|
|
8
|
+
|
|
9
|
+
- 🔌 **服务管理**:轻松添加、移除、查看和更新 MCP 服务(支持 Stdio、SSE 和 HTTP 模式)
|
|
10
|
+
- 🛠️ **工具发现**:查看已配置服务中所有可用的工具
|
|
11
|
+
- 🚀 **工具执行**:直接在命令行调用工具,支持参数自动解析
|
|
12
|
+
- 🔄 **守护进程**:保持与 MCP 服务的长连接,显著提高性能
|
|
13
|
+
- 📊 **表格输出**:清晰的服务器状态和工具列表展示
|
|
14
|
+
- 🔍 **工具筛选**:按关键词筛选工具,支持简洁模式
|
|
15
|
+
- 🚨 **详细日志**:可选的详细日志模式,方便调试
|
|
16
|
+
- ✅ **自动化测试**:完整的测试套件,确保代码质量
|
|
17
|
+
|
|
18
|
+
## 安装
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g @maplezzk/mcps
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 快速开始
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 1. 添加一个服务
|
|
28
|
+
mcps add fetch --command uvx --args mcp-server-fetch
|
|
29
|
+
|
|
30
|
+
# 2. 启动守护进程
|
|
31
|
+
mcps start
|
|
32
|
+
|
|
33
|
+
# 3. 查看服务状态
|
|
34
|
+
mcps status
|
|
35
|
+
|
|
36
|
+
# 4. 查看可用工具
|
|
37
|
+
mcps tools fetch
|
|
38
|
+
|
|
39
|
+
# 5. 调用工具
|
|
40
|
+
mcps call fetch fetch url="https://example.com"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 使用指南
|
|
44
|
+
|
|
45
|
+
### 1. 守护进程 (Daemon Mode)
|
|
46
|
+
|
|
47
|
+
mcps 支持守护进程模式,可以保持与 MCP 服务的长连接,显著提高频繁调用的性能。
|
|
48
|
+
|
|
49
|
+
**启动守护进程:**
|
|
50
|
+
```bash
|
|
51
|
+
# 普通模式
|
|
52
|
+
mcps start
|
|
53
|
+
|
|
54
|
+
# 详细模式(显示每个服务器的连接过程和禁用的服务器)
|
|
55
|
+
mcps start --verbose
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
输出示例:
|
|
59
|
+
```
|
|
60
|
+
Starting daemon in background...
|
|
61
|
+
[Daemon] Connecting to 7 server(s)...
|
|
62
|
+
[Daemon] - chrome-devtools... Connected ✓
|
|
63
|
+
[Daemon] - fetch... Connected ✓
|
|
64
|
+
[Daemon] - gitlab-mr-creator... Connected ✓
|
|
65
|
+
[Daemon] Connected: 7/7
|
|
66
|
+
Daemon started successfully on port 4100.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**重启连接:**
|
|
70
|
+
```bash
|
|
71
|
+
# 重置所有连接
|
|
72
|
+
mcps restart
|
|
73
|
+
|
|
74
|
+
# 仅重置特定服务的连接
|
|
75
|
+
mcps restart my-server
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**停止守护进程:**
|
|
79
|
+
```bash
|
|
80
|
+
mcps stop
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**查看守护进程状态:**
|
|
84
|
+
```bash
|
|
85
|
+
mcps status
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
输出示例:
|
|
89
|
+
```
|
|
90
|
+
Daemon is running (v1.0.29)
|
|
91
|
+
|
|
92
|
+
Active Connections:
|
|
93
|
+
NAME STATUS TOOLS
|
|
94
|
+
───────────────── ────────── ──────
|
|
95
|
+
chrome-devtools Connected 26
|
|
96
|
+
fetch Connected 1
|
|
97
|
+
gitlab-mr-creator Connected 30
|
|
98
|
+
Total: 3 connection(s)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 2. 服务管理 (Server Management)
|
|
102
|
+
|
|
103
|
+
**查看所有服务(配置信息):**
|
|
104
|
+
```bash
|
|
105
|
+
mcps ls
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
输出示例:
|
|
109
|
+
```
|
|
110
|
+
NAME TYPE ENABLED COMMAND/URL
|
|
111
|
+
───────────────── ────── ─────── ─────────────
|
|
112
|
+
chrome-devtools stdio ✓ npx -y chrome-devtools-mcp ...
|
|
113
|
+
fetch stdio ✓ uvx mcp-server-fetch
|
|
114
|
+
my-server stdio ✗ npx my-server
|
|
115
|
+
Total: 3 server(s)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**添加 Stdio 服务:**
|
|
119
|
+
```bash
|
|
120
|
+
# 添加本地 Node.js 服务
|
|
121
|
+
mcps add my-server --command node --args ./build/index.js
|
|
122
|
+
|
|
123
|
+
# 使用 npx/uvx 添加服务
|
|
124
|
+
mcps add fetch --command uvx --args mcp-server-fetch
|
|
125
|
+
|
|
126
|
+
# 添加带环境变量的服务
|
|
127
|
+
mcps add my-db --command npx --args @modelcontextprotocol/server-postgres --env POSTGRES_CONNECTION_STRING="${DATABASE_URL}"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**添加 SSE 服务:**
|
|
131
|
+
```bash
|
|
132
|
+
mcps add remote-server --type sse --url http://localhost:8000/sse
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**添加 Streamable HTTP 服务:**
|
|
136
|
+
```bash
|
|
137
|
+
mcps add my-http-server --type http --url http://localhost:8000/mcp
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**移除服务:**
|
|
141
|
+
```bash
|
|
142
|
+
mcps rm my-server
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**更新服务:**
|
|
146
|
+
```bash
|
|
147
|
+
# 刷新所有服务连接
|
|
148
|
+
mcps update
|
|
149
|
+
|
|
150
|
+
# 更新特定服务的命令
|
|
151
|
+
mcps update my-server --command new-command
|
|
152
|
+
|
|
153
|
+
# 更新特定服务的参数
|
|
154
|
+
mcps update my-server --args arg1 arg2
|
|
155
|
+
|
|
156
|
+
# 同时更新命令和参数
|
|
157
|
+
mcps update my-server --command node --args ./new-build/index.js
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 3. 工具交互 (Tool Interaction)
|
|
161
|
+
|
|
162
|
+
**查看服务下的可用工具:**
|
|
163
|
+
```bash
|
|
164
|
+
# 详细模式(显示所有信息)
|
|
165
|
+
mcps tools chrome-devtools
|
|
166
|
+
|
|
167
|
+
# 简洁模式(只显示工具名称)
|
|
168
|
+
mcps tools chrome-devtools --simple
|
|
169
|
+
|
|
170
|
+
# 筛选工具(按关键词)
|
|
171
|
+
mcps tools chrome-devtools --tool screenshot
|
|
172
|
+
|
|
173
|
+
# 多个关键词 + 简洁模式
|
|
174
|
+
mcps tools gitlab-mr-creator --tool file --tool wiki --simple
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
详细模式输出示例:
|
|
178
|
+
```
|
|
179
|
+
Available Tools for chrome-devtools:
|
|
180
|
+
|
|
181
|
+
- take_screenshot
|
|
182
|
+
Take a screenshot of the page or element.
|
|
183
|
+
Arguments:
|
|
184
|
+
format*: string (Type of format to save the screenshot as...)
|
|
185
|
+
quality: number (Compression quality from 0-100)
|
|
186
|
+
uid: string (The uid of an element to screenshot...)
|
|
187
|
+
...
|
|
188
|
+
|
|
189
|
+
- click
|
|
190
|
+
Clicks on the provided element
|
|
191
|
+
Arguments:
|
|
192
|
+
uid*: string (The uid of an element...)
|
|
193
|
+
...
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
简洁模式输出示例:
|
|
197
|
+
```
|
|
198
|
+
$ mcps tools chrome-devtools -s
|
|
199
|
+
click
|
|
200
|
+
close_page
|
|
201
|
+
drag
|
|
202
|
+
emulate
|
|
203
|
+
evaluate_script
|
|
204
|
+
fill
|
|
205
|
+
...
|
|
206
|
+
take_screenshot
|
|
207
|
+
take_snapshot
|
|
208
|
+
|
|
209
|
+
Total: 26 tool(s)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**调用工具:**
|
|
213
|
+
|
|
214
|
+
语法:
|
|
215
|
+
```bash
|
|
216
|
+
mcps call <server_name> <tool_name> [arguments...]
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
- `<server_name>`: 已配置的 MCP 服务名称
|
|
220
|
+
- `<tool_name>`: 要调用的工具名称
|
|
221
|
+
- `[arguments...]`: 以 `key=value` 形式传递的参数。CLI 会尝试自动将值解析为 JSON(数字、布尔值、对象)。
|
|
222
|
+
|
|
223
|
+
示例:
|
|
224
|
+
```bash
|
|
225
|
+
# 简单的字符串参数
|
|
226
|
+
mcps call fetch fetch url="https://example.com"
|
|
227
|
+
|
|
228
|
+
# 带多个参数
|
|
229
|
+
mcps call fetch fetch url="https://example.com" max_length=5000
|
|
230
|
+
|
|
231
|
+
# JSON 对象参数
|
|
232
|
+
mcps call my-server createUser user='{"name": "Alice", "age": 30}'
|
|
233
|
+
|
|
234
|
+
# 布尔值/数字参数
|
|
235
|
+
mcps call chrome-devtools take_screenshot fullPage=true quality=90
|
|
236
|
+
|
|
237
|
+
# 混合参数
|
|
238
|
+
mcps call my-server config debug=true timeout=5000 options='{"retries": 3}'
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## 配置文件
|
|
242
|
+
|
|
243
|
+
默认情况下,配置文件存储在:
|
|
244
|
+
`~/.mcps/mcp.json`
|
|
245
|
+
|
|
246
|
+
您可以通过设置 `MCPS_CONFIG_DIR` 环境变量来更改存储位置。
|
|
247
|
+
|
|
248
|
+
配置文件示例:
|
|
249
|
+
```json
|
|
250
|
+
{
|
|
251
|
+
"servers": [
|
|
252
|
+
{
|
|
253
|
+
"name": "fetch",
|
|
254
|
+
"type": "stdio",
|
|
255
|
+
"command": "uvx",
|
|
256
|
+
"args": ["mcp-server-fetch"]
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"name": "my-server",
|
|
260
|
+
"type": "stdio",
|
|
261
|
+
"command": "node",
|
|
262
|
+
"args": ["./build/index.js"],
|
|
263
|
+
"env": {
|
|
264
|
+
"API_KEY": "${API_KEY}"
|
|
265
|
+
},
|
|
266
|
+
"disabled": false
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## 环境变量
|
|
273
|
+
|
|
274
|
+
- `MCPS_CONFIG_DIR`: 配置文件目录(默认:`~/.mcps`)
|
|
275
|
+
- `MCPS_PORT`: Daemon 端口(默认:`4100`)
|
|
276
|
+
- `MCPS_VERBOSE`: 详细日志模式(默认:`false`)
|
|
277
|
+
|
|
278
|
+
## 命令参考
|
|
279
|
+
|
|
280
|
+
### 服务管理
|
|
281
|
+
- `mcps ls` - 列出所有服务
|
|
282
|
+
- `mcps add <name>` - 添加新服务
|
|
283
|
+
- `mcps rm <name>` - 移除服务
|
|
284
|
+
- `mcps update [name]` - 更新服务配置
|
|
285
|
+
|
|
286
|
+
### 守护进程
|
|
287
|
+
- `mcps start [-v]` - 启动守护进程(`-v` 显示详细日志)
|
|
288
|
+
- `mcps stop` - 停止守护进程
|
|
289
|
+
- `mcps status` - 查看守护进程状态
|
|
290
|
+
- `mcps restart [server]` - 重启守护进程或特定服务
|
|
291
|
+
|
|
292
|
+
### 工具交互
|
|
293
|
+
- `mcps tools <server> [-s] [-t <name>...]` - 查看可用工具
|
|
294
|
+
- `-s, --simple`: 只显示工具名称
|
|
295
|
+
- `-t, --tool`: 按名称筛选工具(可重复使用)
|
|
296
|
+
- `mcps call <server> <tool> [args...]` - 调用工具
|
|
297
|
+
|
|
298
|
+
## 性能优化
|
|
299
|
+
|
|
300
|
+
mcps 通过以下方式优化性能:
|
|
301
|
+
|
|
302
|
+
1. **守护进程模式**:保持长连接,避免重复启动开销
|
|
303
|
+
2. **工具缓存**:连接时缓存工具数量,避免重复查询
|
|
304
|
+
3. **异步连接**:并行初始化多个服务器连接
|
|
305
|
+
|
|
306
|
+
典型性能:
|
|
307
|
+
- 启动守护进程:10-15 秒(首次,取决于服务数量)
|
|
308
|
+
- 查看状态:~200ms
|
|
309
|
+
- 调用工具:~50-100ms
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
## 开发工作流
|
|
313
|
+
|
|
314
|
+
欢迎贡献代码!
|
|
315
|
+
|
|
316
|
+
**快速开始:**
|
|
317
|
+
```bash
|
|
318
|
+
# 克隆项目
|
|
319
|
+
git clone https://github.com/maplezzk/mcps.git
|
|
320
|
+
cd mcps
|
|
321
|
+
npm install
|
|
322
|
+
|
|
323
|
+
# 开发模式
|
|
324
|
+
npm run dev -- <command>
|
|
325
|
+
|
|
326
|
+
# 构建和测试
|
|
327
|
+
npm run build
|
|
328
|
+
npm test
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**重要规范:**
|
|
332
|
+
- 不要直接在 `main` 分支提交代码
|
|
333
|
+
- 使用 `npm version` 更新版本号(禁止手动修改)
|
|
334
|
+
- 新功能必须包含单元测试
|
|
335
|
+
|
|
336
|
+
📖 **完整开发文档**:[DEVELOPMENT.md](./DEVELOPMENT.md)
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
## 常见问题
|
|
340
|
+
|
|
341
|
+
**Q: 如何查看所有服务器的运行状态?**
|
|
342
|
+
```bash
|
|
343
|
+
mcps status # 查看活跃连接
|
|
344
|
+
mcps ls # 查看所有配置(包括禁用的)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Q: 某个服务连接失败了怎么办?**
|
|
348
|
+
```bash
|
|
349
|
+
# 查看详细日志
|
|
350
|
+
mcps start --verbose
|
|
351
|
+
|
|
352
|
+
# 重启该服务
|
|
353
|
+
mcps restart my-server
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**Q: 如何临时禁用某个服务?**
|
|
357
|
+
在配置文件中设置 `"disabled": true`,或使用 `mcps update` 修改配置。
|
|
358
|
+
|
|
359
|
+
**Q: 工具太多怎么快速找到?**
|
|
360
|
+
```bash
|
|
361
|
+
# 筛选工具名称
|
|
362
|
+
mcps tools my-server --tool keyword
|
|
363
|
+
|
|
364
|
+
# 只显示名称
|
|
365
|
+
mcps tools my-server --simple
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## 许可证
|
|
369
|
+
|
|
370
|
+
ISC
|
package/dist/commands/call.js
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
2
3
|
import { configManager } from '../core/config.js';
|
|
3
4
|
import { DaemonClient } from '../core/daemon-client.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse call command arguments
|
|
7
|
+
* @param args - Command line arguments in key=value format
|
|
8
|
+
* @param raw - Whether to treat all values as raw strings
|
|
9
|
+
* @returns Parsed parameters object
|
|
10
|
+
*/
|
|
11
|
+
export function parseCallArgs(args, raw) {
|
|
12
|
+
const params = {};
|
|
13
|
+
if (!args)
|
|
14
|
+
return params;
|
|
15
|
+
args.forEach((arg) => {
|
|
16
|
+
const eqIndex = arg.indexOf('=');
|
|
17
|
+
if (eqIndex > 0) {
|
|
18
|
+
const key = arg.slice(0, eqIndex);
|
|
19
|
+
const valStr = arg.slice(eqIndex + 1);
|
|
20
|
+
if (raw) {
|
|
21
|
+
// --raw mode: treat all values as strings
|
|
22
|
+
params[key] = valStr;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// Default mode: try JSON parsing
|
|
26
|
+
try {
|
|
27
|
+
params[key] = JSON.parse(valStr);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
params[key] = valStr;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return params;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Load parameters from JSON string or file
|
|
39
|
+
* @param jsonValue - JSON string (starts with { or [) or file path
|
|
40
|
+
* @returns Parsed parameters object
|
|
41
|
+
*/
|
|
42
|
+
export function loadJsonParams(jsonValue) {
|
|
43
|
+
const trimmed = jsonValue.trim();
|
|
44
|
+
// Check if it's a JSON string (starts with { or [)
|
|
45
|
+
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
|
|
46
|
+
return JSON.parse(jsonValue);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Treat as file path
|
|
50
|
+
const jsonContent = readFileSync(jsonValue, 'utf-8');
|
|
51
|
+
return JSON.parse(jsonContent);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
4
54
|
function printResult(result) {
|
|
5
55
|
if (result.content) {
|
|
6
56
|
result.content.forEach((item) => {
|
|
@@ -22,6 +72,8 @@ function printResult(result) {
|
|
|
22
72
|
export const registerCallCommand = (program) => {
|
|
23
73
|
program.command('call <server> <tool> [args...]')
|
|
24
74
|
.description('Call a tool on a server. Arguments format: key=value')
|
|
75
|
+
.option('-r, --raw', 'Treat all values as raw strings (no JSON parsing)')
|
|
76
|
+
.option('-j, --json <file>', 'Load parameters from a JSON file')
|
|
25
77
|
.addHelpText('after', `
|
|
26
78
|
Examples:
|
|
27
79
|
$ mcps call my-server echo message="Hello World"
|
|
@@ -29,28 +81,33 @@ Examples:
|
|
|
29
81
|
$ mcps call my-server config debug=true
|
|
30
82
|
$ mcps call my-server createUser user='{"name":"Alice","age":30}'
|
|
31
83
|
|
|
84
|
+
# Use --raw to treat all values as strings
|
|
85
|
+
$ mcps call my-server createUser --raw id="123" name="Alice"
|
|
86
|
+
|
|
87
|
+
# Use --json to load parameters from a file
|
|
88
|
+
$ mcps call my-server createUser --json params.json
|
|
89
|
+
|
|
32
90
|
Notes:
|
|
33
91
|
- Arguments are parsed as key=value pairs.
|
|
34
|
-
-
|
|
35
|
-
-
|
|
92
|
+
- By default, values are automatically parsed as JSON if possible (numbers, booleans, objects).
|
|
93
|
+
- Use --raw to disable JSON parsing and treat all values as strings.
|
|
94
|
+
- Use --json to load parameters from a JSON file or JSON string.
|
|
36
95
|
- For strings with spaces, wrap the value in quotes (e.g., msg="hello world").
|
|
37
96
|
`)
|
|
38
|
-
.action(async (serverName, toolName, args) => {
|
|
39
|
-
|
|
40
|
-
if
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
});
|
|
97
|
+
.action(async (serverName, toolName, args, options) => {
|
|
98
|
+
let params = {};
|
|
99
|
+
// Load from JSON file or string if specified
|
|
100
|
+
if (options.json) {
|
|
101
|
+
try {
|
|
102
|
+
params = loadJsonParams(options.json);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error(chalk.red(`Failed to parse JSON: ${error.message}`));
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
params = parseCallArgs(args, options.raw);
|
|
54
111
|
}
|
|
55
112
|
// Check if server exists in config first
|
|
56
113
|
const serverConfig = configManager.getServer(serverName);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { parseCallArgs, loadJsonParams } from '../../commands/call.js';
|
|
6
|
+
describe('call command', () => {
|
|
7
|
+
describe('parseCallArgs', () => {
|
|
8
|
+
it('should parse string values in default mode', () => {
|
|
9
|
+
const args = ['name=Alice', 'url=https://example.com'];
|
|
10
|
+
const result = parseCallArgs(args, false);
|
|
11
|
+
expect(result).toEqual({
|
|
12
|
+
name: 'Alice',
|
|
13
|
+
url: 'https://example.com'
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
it('should parse numbers and booleans in default mode', () => {
|
|
17
|
+
const args = ['count=10', 'active=true', 'score=3.14'];
|
|
18
|
+
const result = parseCallArgs(args, false);
|
|
19
|
+
expect(result).toEqual({
|
|
20
|
+
count: 10,
|
|
21
|
+
active: true,
|
|
22
|
+
score: 3.14
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
it('should parse JSON objects in default mode', () => {
|
|
26
|
+
const args = ['user={"name":"Alice","age":30}'];
|
|
27
|
+
const result = parseCallArgs(args, false);
|
|
28
|
+
expect(result).toEqual({
|
|
29
|
+
user: { name: 'Alice', age: 30 }
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
it('should treat all values as strings in raw mode', () => {
|
|
33
|
+
const args = ['id=123', 'count=10', 'active=true', 'pi=3.14'];
|
|
34
|
+
const result = parseCallArgs(args, true);
|
|
35
|
+
expect(result).toEqual({
|
|
36
|
+
id: '123',
|
|
37
|
+
count: '10',
|
|
38
|
+
active: 'true',
|
|
39
|
+
pi: '3.14'
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it('should handle empty args', () => {
|
|
43
|
+
expect(parseCallArgs(undefined, false)).toEqual({});
|
|
44
|
+
expect(parseCallArgs([], false)).toEqual({});
|
|
45
|
+
});
|
|
46
|
+
it('should handle args without equals sign', () => {
|
|
47
|
+
const args = ['invalid', 'name=Alice', 'noequals'];
|
|
48
|
+
const result = parseCallArgs(args, false);
|
|
49
|
+
expect(result).toEqual({
|
|
50
|
+
name: 'Alice'
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
it('should handle values with equals sign', () => {
|
|
54
|
+
const args = ['equation=1+1=2', 'url=https://example.com?a=1&b=2'];
|
|
55
|
+
const result = parseCallArgs(args, false);
|
|
56
|
+
expect(result).toEqual({
|
|
57
|
+
equation: '1+1=2',
|
|
58
|
+
url: 'https://example.com?a=1&b=2'
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe('loadJsonParams', () => {
|
|
63
|
+
let tempDir;
|
|
64
|
+
beforeEach(() => {
|
|
65
|
+
tempDir = path.join(os.tmpdir(), `mcps-test-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`);
|
|
66
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
67
|
+
});
|
|
68
|
+
afterEach(() => {
|
|
69
|
+
if (fs.existsSync(tempDir)) {
|
|
70
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
it('should parse JSON string starting with {', () => {
|
|
74
|
+
const jsonStr = '{"key": "value", "number": 42}';
|
|
75
|
+
const result = loadJsonParams(jsonStr);
|
|
76
|
+
expect(result).toEqual({
|
|
77
|
+
key: 'value',
|
|
78
|
+
number: 42
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
it('should parse JSON string starting with [', () => {
|
|
82
|
+
const jsonStr = '[{"id": 1}, {"id": 2}]';
|
|
83
|
+
const result = loadJsonParams(jsonStr);
|
|
84
|
+
expect(result).toEqual([{ id: 1 }, { id: 2 }]);
|
|
85
|
+
});
|
|
86
|
+
it('should load and parse JSON from file', () => {
|
|
87
|
+
const testFile = path.join(tempDir, 'params.json');
|
|
88
|
+
const testData = { name: 'test', value: 123 };
|
|
89
|
+
fs.writeFileSync(testFile, JSON.stringify(testData));
|
|
90
|
+
const result = loadJsonParams(testFile);
|
|
91
|
+
expect(result).toEqual(testData);
|
|
92
|
+
});
|
|
93
|
+
it('should handle JSON string with leading/trailing whitespace', () => {
|
|
94
|
+
const jsonStr = ' {"key": "value"} ';
|
|
95
|
+
const result = loadJsonParams(jsonStr);
|
|
96
|
+
expect(result).toEqual({ key: 'value' });
|
|
97
|
+
});
|
|
98
|
+
it('should throw error for invalid JSON string', () => {
|
|
99
|
+
expect(() => loadJsonParams('not valid json')).toThrow();
|
|
100
|
+
});
|
|
101
|
+
it('should throw error for non-existent file', () => {
|
|
102
|
+
const nonExistentFile = path.join(tempDir, 'non-existent.json');
|
|
103
|
+
expect(() => loadJsonParams(nonExistentFile)).toThrow();
|
|
104
|
+
});
|
|
105
|
+
it('should throw error for invalid JSON in file', () => {
|
|
106
|
+
const testFile = path.join(tempDir, 'invalid.json');
|
|
107
|
+
fs.writeFileSync(testFile, 'not valid json');
|
|
108
|
+
expect(() => loadJsonParams(testFile)).toThrow();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maplezzk/mcps",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "A CLI to manage and use MCP servers",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"license": "ISC",
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
19
|
-
"url": "https://github.com/
|
|
19
|
+
"url": "https://github.com/maplezzk/mcps"
|
|
20
20
|
},
|
|
21
21
|
"type": "module",
|
|
22
22
|
"bin": {
|