@maplezzk/mcps 1.4.1 → 1.5.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/README.md +54 -17
- package/README.zh.md +53 -16
- package/dist/commands/tools.js +32 -2
- package/dist/tests/unit/tools.test.js +170 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -160,12 +160,15 @@ mcps update my-server --command node --args ./new-build/index.js
|
|
|
160
160
|
|
|
161
161
|
**List available tools on a server:**
|
|
162
162
|
```bash
|
|
163
|
-
# Detailed mode (show all information)
|
|
163
|
+
# Detailed mode (show all information including nested object properties)
|
|
164
164
|
mcps tools chrome-devtools
|
|
165
165
|
|
|
166
166
|
# Simple mode (show only tool names)
|
|
167
167
|
mcps tools chrome-devtools --simple
|
|
168
168
|
|
|
169
|
+
# JSON output (raw tool schema)
|
|
170
|
+
mcps tools chrome-devtools --json
|
|
171
|
+
|
|
169
172
|
# Filter tools by keyword
|
|
170
173
|
mcps tools chrome-devtools --tool screenshot
|
|
171
174
|
|
|
@@ -173,23 +176,21 @@ mcps tools chrome-devtools --tool screenshot
|
|
|
173
176
|
mcps tools gitlab-mr-creator --tool file --tool wiki --simple
|
|
174
177
|
```
|
|
175
178
|
|
|
176
|
-
Detailed mode output example:
|
|
179
|
+
Detailed mode output example (with nested objects):
|
|
177
180
|
```
|
|
178
181
|
Available Tools for chrome-devtools:
|
|
179
182
|
|
|
180
183
|
- take_screenshot
|
|
181
184
|
Take a screenshot of the page or element.
|
|
182
185
|
Arguments:
|
|
183
|
-
format*: string (Type of format to save the screenshot as...)
|
|
186
|
+
format*: string ["jpeg", "png", "webp"] (Type of format to save the screenshot as...)
|
|
184
187
|
quality: number (Compression quality from 0-100)
|
|
185
188
|
uid: string (The uid of an element to screenshot...)
|
|
186
|
-
...
|
|
187
189
|
|
|
188
190
|
- click
|
|
189
191
|
Clicks on the provided element
|
|
190
192
|
Arguments:
|
|
191
193
|
uid*: string (The uid of an element...)
|
|
192
|
-
...
|
|
193
194
|
```
|
|
194
195
|
|
|
195
196
|
Simple mode output example:
|
|
@@ -212,31 +213,66 @@ Total: 26 tool(s)
|
|
|
212
213
|
|
|
213
214
|
Syntax:
|
|
214
215
|
```bash
|
|
215
|
-
mcps call <server_name> <tool_name> [arguments...]
|
|
216
|
+
mcps call <server_name> <tool_name> [options] [arguments...]
|
|
216
217
|
```
|
|
217
218
|
|
|
218
219
|
- `<server_name>`: Name of the configured MCP server
|
|
219
220
|
- `<tool_name>`: Name of the tool to call
|
|
220
|
-
- `[
|
|
221
|
+
- `[options]`: Optional flags (`--raw`, `--json`)
|
|
222
|
+
- `[arguments...]`: Arguments passed as `key=value` pairs
|
|
223
|
+
|
|
224
|
+
**Options:**
|
|
225
|
+
|
|
226
|
+
| Option | Description |
|
|
227
|
+
|--------|-------------|
|
|
228
|
+
| `-r, --raw` | Treat all values as raw strings (disable JSON parsing) |
|
|
229
|
+
| `-j, --json <value>` | Load parameters from JSON string or file |
|
|
230
|
+
|
|
231
|
+
**Default Mode (Auto JSON Parsing):**
|
|
221
232
|
|
|
222
|
-
|
|
233
|
+
By default, values are automatically parsed as JSON:
|
|
223
234
|
```bash
|
|
224
|
-
#
|
|
235
|
+
# String
|
|
225
236
|
mcps call fetch fetch url="https://example.com"
|
|
226
237
|
|
|
227
|
-
#
|
|
228
|
-
mcps call fetch fetch
|
|
238
|
+
# Numbers and booleans are parsed
|
|
239
|
+
mcps call fetch fetch max_length=5000 follow_redirects=true
|
|
240
|
+
# Sends: { "max_length": 5000, "follow_redirects": true }
|
|
229
241
|
|
|
230
|
-
# JSON object
|
|
242
|
+
# JSON object
|
|
231
243
|
mcps call my-server createUser user='{"name": "Alice", "age": 30}'
|
|
232
244
|
|
|
233
|
-
#
|
|
234
|
-
mcps call chrome-devtools take_screenshot fullPage=true quality=90
|
|
235
|
-
|
|
236
|
-
# Mixed arguments
|
|
245
|
+
# Mixed
|
|
237
246
|
mcps call my-server config debug=true timeout=5000 options='{"retries": 3}'
|
|
238
247
|
```
|
|
239
248
|
|
|
249
|
+
**--raw Mode (String Values Only):**
|
|
250
|
+
|
|
251
|
+
Use `--raw` to disable JSON parsing. All values remain as strings:
|
|
252
|
+
```bash
|
|
253
|
+
# IDs and codes stay as strings
|
|
254
|
+
mcps call my-db createOrder --raw order_id="12345" sku="ABC-001"
|
|
255
|
+
# Sends: { "order_id": "12345", "sku": "ABC-001" }
|
|
256
|
+
|
|
257
|
+
# SQL queries with special characters
|
|
258
|
+
mcps call alibaba-dms createDataChangeOrder --raw \
|
|
259
|
+
database_id="36005357" \
|
|
260
|
+
script="DELETE FROM table WHERE id = 'xxx';" \
|
|
261
|
+
logic=true
|
|
262
|
+
# Sends: { "database_id": "36005357", "script": "...", "logic": "true" }
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**--json Mode (Complex Parameters):**
|
|
266
|
+
|
|
267
|
+
For complex parameters, use `--json` to load from a JSON string or file:
|
|
268
|
+
```bash
|
|
269
|
+
# From JSON string
|
|
270
|
+
mcps call my-server createUser --json '{"name": "Alice", "age": 30}'
|
|
271
|
+
|
|
272
|
+
# From file
|
|
273
|
+
mcps call my-server createUser --json params.json
|
|
274
|
+
```
|
|
275
|
+
|
|
240
276
|
## Configuration File
|
|
241
277
|
|
|
242
278
|
By default, the configuration file is stored at:
|
|
@@ -289,8 +325,9 @@ Configuration file example:
|
|
|
289
325
|
- `mcps restart [server]` - Restart daemon or specific server
|
|
290
326
|
|
|
291
327
|
### Tool Interaction
|
|
292
|
-
- `mcps tools <server> [-s] [-t <name>...]` - List available tools
|
|
328
|
+
- `mcps tools <server> [-s] [-j] [-t <name>...]` - List available tools
|
|
293
329
|
- `-s, --simple`: Show only tool names
|
|
330
|
+
- `-j, --json`: Output raw JSON (for debugging)
|
|
294
331
|
- `-t, --tool`: Filter tools by name (can be used multiple times)
|
|
295
332
|
- `mcps call <server> <tool> [args...]` - Call a tool
|
|
296
333
|
|
package/README.zh.md
CHANGED
|
@@ -161,12 +161,15 @@ mcps update my-server --command node --args ./new-build/index.js
|
|
|
161
161
|
|
|
162
162
|
**查看服务下的可用工具:**
|
|
163
163
|
```bash
|
|
164
|
-
#
|
|
164
|
+
# 详细模式(显示所有信息,包括嵌套对象属性)
|
|
165
165
|
mcps tools chrome-devtools
|
|
166
166
|
|
|
167
167
|
# 简洁模式(只显示工具名称)
|
|
168
168
|
mcps tools chrome-devtools --simple
|
|
169
169
|
|
|
170
|
+
# JSON 输出(原始工具 schema)
|
|
171
|
+
mcps tools chrome-devtools --json
|
|
172
|
+
|
|
170
173
|
# 筛选工具(按关键词)
|
|
171
174
|
mcps tools chrome-devtools --tool screenshot
|
|
172
175
|
|
|
@@ -174,23 +177,21 @@ mcps tools chrome-devtools --tool screenshot
|
|
|
174
177
|
mcps tools gitlab-mr-creator --tool file --tool wiki --simple
|
|
175
178
|
```
|
|
176
179
|
|
|
177
|
-
|
|
180
|
+
详细模式输出示例(包含嵌套对象):
|
|
178
181
|
```
|
|
179
182
|
Available Tools for chrome-devtools:
|
|
180
183
|
|
|
181
184
|
- take_screenshot
|
|
182
185
|
Take a screenshot of the page or element.
|
|
183
186
|
Arguments:
|
|
184
|
-
format*: string (Type of format to save the screenshot as...)
|
|
187
|
+
format*: string ["jpeg", "png", "webp"] (Type of format to save the screenshot as...)
|
|
185
188
|
quality: number (Compression quality from 0-100)
|
|
186
189
|
uid: string (The uid of an element to screenshot...)
|
|
187
|
-
...
|
|
188
190
|
|
|
189
191
|
- click
|
|
190
192
|
Clicks on the provided element
|
|
191
193
|
Arguments:
|
|
192
194
|
uid*: string (The uid of an element...)
|
|
193
|
-
...
|
|
194
195
|
```
|
|
195
196
|
|
|
196
197
|
简洁模式输出示例:
|
|
@@ -213,31 +214,66 @@ Total: 26 tool(s)
|
|
|
213
214
|
|
|
214
215
|
语法:
|
|
215
216
|
```bash
|
|
216
|
-
mcps call <server_name> <tool_name> [arguments...]
|
|
217
|
+
mcps call <server_name> <tool_name> [options] [arguments...]
|
|
217
218
|
```
|
|
218
219
|
|
|
219
220
|
- `<server_name>`: 已配置的 MCP 服务名称
|
|
220
221
|
- `<tool_name>`: 要调用的工具名称
|
|
221
|
-
- `[
|
|
222
|
+
- `[options]`: 可选参数(`--raw`, `--json`)
|
|
223
|
+
- `[arguments...]`: 以 `key=value` 形式传递的参数
|
|
224
|
+
|
|
225
|
+
**选项:**
|
|
226
|
+
|
|
227
|
+
| 选项 | 说明 |
|
|
228
|
+
|------|------|
|
|
229
|
+
| `-r, --raw` | 将所有值作为原始字符串处理(禁用 JSON 解析) |
|
|
230
|
+
| `-j, --json <value>` | 从 JSON 字符串或文件加载参数 |
|
|
231
|
+
|
|
232
|
+
**默认模式(自动 JSON 解析):**
|
|
222
233
|
|
|
223
|
-
|
|
234
|
+
默认情况下,参数值会被自动解析为 JSON:
|
|
224
235
|
```bash
|
|
225
|
-
#
|
|
236
|
+
# 字符串
|
|
226
237
|
mcps call fetch fetch url="https://example.com"
|
|
227
238
|
|
|
228
|
-
#
|
|
229
|
-
mcps call fetch fetch
|
|
239
|
+
# 数字和布尔值会被解析
|
|
240
|
+
mcps call fetch fetch max_length=5000 follow_redirects=true
|
|
241
|
+
# 实际发送: { "max_length": 5000, "follow_redirects": true }
|
|
230
242
|
|
|
231
|
-
# JSON
|
|
243
|
+
# JSON 对象
|
|
232
244
|
mcps call my-server createUser user='{"name": "Alice", "age": 30}'
|
|
233
245
|
|
|
234
|
-
# 布尔值/数字参数
|
|
235
|
-
mcps call chrome-devtools take_screenshot fullPage=true quality=90
|
|
236
|
-
|
|
237
246
|
# 混合参数
|
|
238
247
|
mcps call my-server config debug=true timeout=5000 options='{"retries": 3}'
|
|
239
248
|
```
|
|
240
249
|
|
|
250
|
+
**--raw 模式(仅字符串值):**
|
|
251
|
+
|
|
252
|
+
使用 `--raw` 禁用 JSON 解析,所有值保持为字符串:
|
|
253
|
+
```bash
|
|
254
|
+
# ID 和编码保持为字符串
|
|
255
|
+
mcps call my-db createOrder --raw order_id="12345" sku="ABC-001"
|
|
256
|
+
# 实际发送: { "order_id": "12345", "sku": "ABC-001" }
|
|
257
|
+
|
|
258
|
+
# 带特殊字符的 SQL 查询
|
|
259
|
+
mcps call alibaba-dms createDataChangeOrder --raw \
|
|
260
|
+
database_id="36005357" \
|
|
261
|
+
script="DELETE FROM table WHERE id = 'xxx';" \
|
|
262
|
+
logic=true
|
|
263
|
+
# 实际发送: { "database_id": "36005357", "script": "...", "logic": "true" }
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**--json 模式(复杂参数):**
|
|
267
|
+
|
|
268
|
+
对于复杂参数,使用 `--json` 从 JSON 字符串或文件加载:
|
|
269
|
+
```bash
|
|
270
|
+
# JSON 字符串
|
|
271
|
+
mcps call my-server createUser --json '{"name": "Alice", "age": 30}'
|
|
272
|
+
|
|
273
|
+
# 文件
|
|
274
|
+
mcps call my-server createUser --json params.json
|
|
275
|
+
```
|
|
276
|
+
|
|
241
277
|
## 配置文件
|
|
242
278
|
|
|
243
279
|
默认情况下,配置文件存储在:
|
|
@@ -290,8 +326,9 @@ mcps call my-server config debug=true timeout=5000 options='{"retries": 3}'
|
|
|
290
326
|
- `mcps restart [server]` - 重启守护进程或特定服务
|
|
291
327
|
|
|
292
328
|
### 工具交互
|
|
293
|
-
- `mcps tools <server> [-s] [-t <name>...]` - 查看可用工具
|
|
329
|
+
- `mcps tools <server> [-s] [-j] [-t <name>...]` - 查看可用工具
|
|
294
330
|
- `-s, --simple`: 只显示工具名称
|
|
331
|
+
- `-j, --json`: 输出原始 JSON(用于调试)
|
|
295
332
|
- `-t, --tool`: 按名称筛选工具(可重复使用)
|
|
296
333
|
- `mcps call <server> <tool> [args...]` - 调用工具
|
|
297
334
|
|
package/dist/commands/tools.js
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { configManager } from '../core/config.js';
|
|
3
3
|
import { DaemonClient } from '../core/daemon-client.js';
|
|
4
|
+
function printProperty(key, value, required, indent) {
|
|
5
|
+
const indentStr = ' '.repeat(indent);
|
|
6
|
+
const requiredMark = required ? chalk.red('*') : '';
|
|
7
|
+
const desc = value.description ? ` (${value.description})` : '';
|
|
8
|
+
if (value.type === 'object' && value.properties) {
|
|
9
|
+
console.log(`${indentStr}${key}${requiredMark}: object${desc}`);
|
|
10
|
+
const nestedRequired = value.required || [];
|
|
11
|
+
Object.entries(value.properties).forEach(([nestedKey, nestedValue]) => {
|
|
12
|
+
printProperty(nestedKey, nestedValue, nestedRequired.includes(nestedKey), indent + 1);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
let typeInfo = value.type || 'any';
|
|
17
|
+
if (value.type === 'array' && value.items) {
|
|
18
|
+
const itemType = value.items.type || 'any';
|
|
19
|
+
typeInfo = `array of ${itemType}`;
|
|
20
|
+
}
|
|
21
|
+
if (value.enum) {
|
|
22
|
+
const enumValues = value.enum.map((v) => typeof v === 'string' ? `"${v}"` : String(v)).join(', ');
|
|
23
|
+
typeInfo += ` [${enumValues}]`;
|
|
24
|
+
}
|
|
25
|
+
console.log(`${indentStr}${key}${requiredMark}: ${typeInfo}${desc}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
4
28
|
function printTools(serverName, tools) {
|
|
5
29
|
console.log(chalk.bold(`\nAvailable Tools for ${serverName}:`));
|
|
6
30
|
if (!tools || tools.length === 0) {
|
|
@@ -15,9 +39,9 @@ function printTools(serverName, tools) {
|
|
|
15
39
|
console.log(chalk.gray(' Arguments:'));
|
|
16
40
|
const schema = tool.inputSchema;
|
|
17
41
|
if (schema.properties) {
|
|
42
|
+
const required = schema.required || [];
|
|
18
43
|
Object.entries(schema.properties).forEach(([key, value]) => {
|
|
19
|
-
|
|
20
|
-
console.log(` ${key}${required}: ${value.type || 'any'} ${value.description ? `(${value.description})` : ''}`);
|
|
44
|
+
printProperty(key, value, required.includes(key), 2);
|
|
21
45
|
});
|
|
22
46
|
}
|
|
23
47
|
else {
|
|
@@ -30,6 +54,7 @@ export const registerToolsCommand = (program) => {
|
|
|
30
54
|
program.command('tools <server>')
|
|
31
55
|
.description('List available tools on a server')
|
|
32
56
|
.option('-s, --simple', 'Show only tool names')
|
|
57
|
+
.option('-j, --json', 'Output raw JSON')
|
|
33
58
|
.option('-t, --tool <name...>', 'Filter tools by name(s)')
|
|
34
59
|
.action(async (serverName, options) => {
|
|
35
60
|
// Check if server exists in config first
|
|
@@ -52,6 +77,11 @@ export const registerToolsCommand = (program) => {
|
|
|
52
77
|
console.log(chalk.yellow('No tools found.'));
|
|
53
78
|
return;
|
|
54
79
|
}
|
|
80
|
+
if (options.json) {
|
|
81
|
+
// Raw JSON output
|
|
82
|
+
console.log(JSON.stringify(tools, null, 2));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
55
85
|
if (options.simple) {
|
|
56
86
|
// Simple mode: only show tool names
|
|
57
87
|
tools.forEach((tool) => console.log(tool.name));
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
describe('tools command', () => {
|
|
3
|
+
describe('tool schema structure validation', () => {
|
|
4
|
+
// 由于 printProperty 是内部函数,我们通过实际输出来测试其行为
|
|
5
|
+
// 这些测试确保嵌套对象、数组和枚举值能正确显示
|
|
6
|
+
it('should display nested object properties', () => {
|
|
7
|
+
// 这里需要模拟完整的 tools 命令调用
|
|
8
|
+
// 由于 printProperty 是内部函数,我们测试最终输出
|
|
9
|
+
const mockTool = {
|
|
10
|
+
name: 'test_tool',
|
|
11
|
+
description: 'Test tool with nested objects',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
params: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
description: 'Nested parameters',
|
|
18
|
+
properties: {
|
|
19
|
+
lang: {
|
|
20
|
+
type: 'number',
|
|
21
|
+
description: 'Language code'
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
required: ['lang']
|
|
25
|
+
},
|
|
26
|
+
simple: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'Simple parameter'
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
required: ['params']
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
// 验证 schema 结构正确
|
|
35
|
+
expect(mockTool.inputSchema.properties.params).toBeDefined();
|
|
36
|
+
expect(mockTool.inputSchema.properties.params.type).toBe('object');
|
|
37
|
+
expect(mockTool.inputSchema.properties.params.properties).toBeDefined();
|
|
38
|
+
expect(mockTool.inputSchema.properties.params.properties.lang).toBeDefined();
|
|
39
|
+
});
|
|
40
|
+
it('should handle array types with items', () => {
|
|
41
|
+
const mockSchema = {
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
items: {
|
|
45
|
+
type: 'array',
|
|
46
|
+
items: {
|
|
47
|
+
type: 'string'
|
|
48
|
+
},
|
|
49
|
+
description: 'List of items'
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
expect(mockSchema.properties.items.type).toBe('array');
|
|
54
|
+
expect(mockSchema.properties.items.items).toBeDefined();
|
|
55
|
+
expect(mockSchema.properties.items.items.type).toBe('string');
|
|
56
|
+
});
|
|
57
|
+
it('should handle enum values', () => {
|
|
58
|
+
const mockSchema = {
|
|
59
|
+
type: 'object',
|
|
60
|
+
properties: {
|
|
61
|
+
format: {
|
|
62
|
+
type: 'string',
|
|
63
|
+
enum: ['jpeg', 'png', 'webp'],
|
|
64
|
+
description: 'Image format'
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
expect(mockSchema.properties.format.enum).toBeDefined();
|
|
69
|
+
expect(mockSchema.properties.format.enum).toEqual(['jpeg', 'png', 'webp']);
|
|
70
|
+
});
|
|
71
|
+
it('should handle required fields marking', () => {
|
|
72
|
+
const mockSchema = {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: {
|
|
75
|
+
required_field: {
|
|
76
|
+
type: 'string'
|
|
77
|
+
},
|
|
78
|
+
optional_field: {
|
|
79
|
+
type: 'number'
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
required: ['required_field']
|
|
83
|
+
};
|
|
84
|
+
expect(mockSchema.required).toContain('required_field');
|
|
85
|
+
expect(mockSchema.required).not.toContain('optional_field');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('complex nested structures', () => {
|
|
89
|
+
it('should handle deeply nested objects', () => {
|
|
90
|
+
const mockSchema = {
|
|
91
|
+
type: 'object',
|
|
92
|
+
properties: {
|
|
93
|
+
level1: {
|
|
94
|
+
type: 'object',
|
|
95
|
+
properties: {
|
|
96
|
+
level2: {
|
|
97
|
+
type: 'object',
|
|
98
|
+
properties: {
|
|
99
|
+
value: {
|
|
100
|
+
type: 'string',
|
|
101
|
+
description: 'Deep value'
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
expect(mockSchema.properties.level1.properties.level2.properties.value).toBeDefined();
|
|
110
|
+
expect(mockSchema.properties.level1.properties.level2.properties.value.type).toBe('string');
|
|
111
|
+
});
|
|
112
|
+
it('should handle arrays with complex item types', () => {
|
|
113
|
+
const mockSchema = {
|
|
114
|
+
type: 'object',
|
|
115
|
+
properties: {
|
|
116
|
+
complexArray: {
|
|
117
|
+
type: 'array',
|
|
118
|
+
items: {
|
|
119
|
+
type: 'object',
|
|
120
|
+
properties: {
|
|
121
|
+
name: { type: 'string' },
|
|
122
|
+
count: { type: 'number' }
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
expect(mockSchema.properties.complexArray.items).toBeDefined();
|
|
129
|
+
expect(mockSchema.properties.complexArray.items.type).toBe('object');
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe('edge cases', () => {
|
|
133
|
+
it('should handle properties without type', () => {
|
|
134
|
+
const mockSchema = {
|
|
135
|
+
type: 'object',
|
|
136
|
+
properties: {
|
|
137
|
+
untyped: {
|
|
138
|
+
description: 'Field without explicit type'
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
expect(mockSchema.properties.untyped).toBeDefined();
|
|
143
|
+
expect(mockSchema.properties.untyped.type).toBeUndefined();
|
|
144
|
+
});
|
|
145
|
+
it('should handle empty objects', () => {
|
|
146
|
+
const mockSchema = {
|
|
147
|
+
type: 'object',
|
|
148
|
+
properties: {
|
|
149
|
+
empty: {
|
|
150
|
+
type: 'object',
|
|
151
|
+
properties: {}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
expect(mockSchema.properties.empty.properties).toEqual({});
|
|
156
|
+
});
|
|
157
|
+
it('should handle arrays without items specification', () => {
|
|
158
|
+
const mockSchema = {
|
|
159
|
+
type: 'object',
|
|
160
|
+
properties: {
|
|
161
|
+
arrayWithoutItems: {
|
|
162
|
+
type: 'array'
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
expect(mockSchema.properties.arrayWithoutItems.type).toBe('array');
|
|
167
|
+
expect(mockSchema.properties.arrayWithoutItems.items).toBeUndefined();
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maplezzk/mcps",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A CLI to manage and use MCP servers",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"prepublishOnly": "npm run build && npm run test",
|
|
31
31
|
"start": "node dist/index.js",
|
|
32
32
|
"dev": "ts-node src/index.ts",
|
|
33
|
+
"check": "npm run build && npm test",
|
|
33
34
|
"test": "vitest run",
|
|
34
35
|
"test:watch": "vitest",
|
|
35
36
|
"test:ui": "vitest --ui",
|