mcp-adder-simple 1.0.5 → 1.0.7
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/mcp-adder.js +162 -100
- package/package.json +1 -1
package/mcp-adder.js
CHANGED
|
@@ -1,129 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Adder Server
|
|
3
|
+
* 一个简单的 MCP (Model Context Protocol) 服务器,提供数字相加功能
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
const readline = require('readline');
|
|
2
7
|
|
|
3
|
-
//
|
|
8
|
+
// ========== 配置和初始化 ==========
|
|
9
|
+
|
|
10
|
+
// 创建 readline 接口用于处理 stdin/stdout 通信
|
|
4
11
|
const rl = readline.createInterface({
|
|
5
12
|
input: process.stdin,
|
|
6
13
|
output: process.stdout,
|
|
7
|
-
terminal: false
|
|
14
|
+
terminal: false // 非终端模式,避免额外的输出格式化
|
|
8
15
|
});
|
|
9
16
|
|
|
10
|
-
//
|
|
17
|
+
// 设置 stdin 编码为 UTF-8
|
|
11
18
|
process.stdin.setEncoding('utf8');
|
|
12
|
-
process.stdin.resume(); // 关键!防止 Node.js 缓冲输入
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
// 立即恢复 stdin 流,防止缓冲输入延迟
|
|
21
|
+
process.stdin.resume();
|
|
22
|
+
|
|
23
|
+
// ========== 主逻辑 ==========
|
|
15
24
|
|
|
25
|
+
// 监听输入行事件,处理 MCP 请求
|
|
16
26
|
rl.on('line', (line) => {
|
|
17
|
-
console.error('[MCP] 📥 收到数据:', line);
|
|
18
27
|
try {
|
|
28
|
+
// 跳过空行
|
|
19
29
|
const trimmed = line.trim();
|
|
20
|
-
if (!trimmed) return;
|
|
30
|
+
if (!trimmed) return;
|
|
31
|
+
|
|
32
|
+
// 解析 JSON-RPC 请求
|
|
21
33
|
const msg = JSON.parse(trimmed);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
34
|
+
|
|
35
|
+
// 打印完整的请求消息(用于调试)
|
|
36
|
+
console.error('[MCP] 收到请求:', JSON.stringify(msg, null, 2));
|
|
37
|
+
|
|
38
|
+
// 检查请求是否包含 id(id 可以为 0,不能只检查 !msg.id)
|
|
39
|
+
if (msg.id === undefined || msg.id === null) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 处理请求
|
|
44
|
+
handleRequest(msg);
|
|
45
|
+
|
|
46
|
+
} catch (e) {
|
|
47
|
+
// JSON 解析失败,记录错误但不中断服务
|
|
48
|
+
console.error(`[MCP] JSON 解析失败: ${line}`);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 处理 MCP 请求
|
|
54
|
+
* @param {Object} msg - JSON-RPC 请求对象
|
|
55
|
+
*/
|
|
56
|
+
function handleRequest(msg) {
|
|
57
|
+
let result = null;
|
|
58
|
+
let error = null;
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
// 根据方法名分发处理
|
|
62
|
+
switch (msg.method) {
|
|
63
|
+
case 'initialize':
|
|
64
|
+
result = handleInitialize();
|
|
65
|
+
break;
|
|
66
|
+
|
|
67
|
+
case 'tools/list':
|
|
68
|
+
result = handleToolsList();
|
|
69
|
+
break;
|
|
70
|
+
|
|
71
|
+
case 'tools/call':
|
|
72
|
+
result = handleToolCall(msg.params);
|
|
73
|
+
break;
|
|
74
|
+
|
|
75
|
+
default:
|
|
76
|
+
throw new Error(`不支持的方法: ${msg.method}`);
|
|
77
|
+
}
|
|
78
|
+
} catch (err) {
|
|
79
|
+
// 处理过程中的错误
|
|
80
|
+
error = {
|
|
81
|
+
code: -32602,
|
|
82
|
+
message: err.message
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 构建并发送响应
|
|
87
|
+
const response = {
|
|
88
|
+
jsonrpc: '2.0',
|
|
89
|
+
id: msg.id
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
if (error) {
|
|
93
|
+
response.error = error;
|
|
94
|
+
} else {
|
|
95
|
+
response.result = result;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 输出响应到 stdout(MCP 客户端读取)
|
|
99
|
+
console.log(JSON.stringify(response));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 处理 initialize 请求
|
|
104
|
+
* @returns {Object} 初始化响应
|
|
105
|
+
*/
|
|
106
|
+
function handleInitialize() {
|
|
107
|
+
return {
|
|
108
|
+
protocolVersion: '2024-10-07',
|
|
109
|
+
serverInfo: {
|
|
110
|
+
name: 'mcp-adder-server',
|
|
111
|
+
version: '1.0.0'
|
|
112
|
+
},
|
|
113
|
+
capabilities: {
|
|
114
|
+
tools: {} // 声明支持 tools 功能
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 处理工具列表请求
|
|
121
|
+
* @returns {Object} 工具列表响应
|
|
122
|
+
*/
|
|
123
|
+
function handleToolsList() {
|
|
124
|
+
return {
|
|
125
|
+
tools: [
|
|
126
|
+
{
|
|
127
|
+
name: 'add_numbers',
|
|
128
|
+
description: '将两个数字相加',
|
|
129
|
+
inputSchema: {
|
|
130
|
+
type: 'object',
|
|
131
|
+
properties: {
|
|
132
|
+
a: {
|
|
133
|
+
type: 'number',
|
|
134
|
+
description: '第一个数'
|
|
57
135
|
},
|
|
58
|
-
|
|
59
|
-
|
|
136
|
+
b: {
|
|
137
|
+
type: 'number',
|
|
138
|
+
description: '第二个数'
|
|
60
139
|
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
case 'list_tools':
|
|
66
|
-
result = {
|
|
67
|
-
tools: [
|
|
68
|
-
{
|
|
69
|
-
name: 'add_numbers',
|
|
70
|
-
description: '将两个数字相加',
|
|
71
|
-
inputSchema: {
|
|
72
|
-
type: 'object',
|
|
73
|
-
properties: {
|
|
74
|
-
a: { type: 'number', description: '第一个数' },
|
|
75
|
-
b: { type: 'number', description: '第二个数' }
|
|
76
|
-
},
|
|
77
|
-
required: ['a', 'b']
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
]
|
|
81
|
-
};
|
|
82
|
-
console.error('[MCP] ← list_tools 成功响应');
|
|
83
|
-
break;
|
|
84
|
-
|
|
85
|
-
case 'call_tool':
|
|
86
|
-
const { name, arguments: args } = msg.params;
|
|
87
|
-
if (name === 'add_numbers') {
|
|
88
|
-
const { a, b } = args;
|
|
89
|
-
if (typeof a !== 'number' || typeof b !== 'number') {
|
|
90
|
-
throw new Error('参数必须是数字');
|
|
91
|
-
}
|
|
92
|
-
result = {
|
|
93
|
-
content: [{ type: 'text', text: `${a} + ${b} = ${a + b}` }]
|
|
94
|
-
};
|
|
95
|
-
} else {
|
|
96
|
-
throw new Error(`未知工具: ${name}`);
|
|
97
|
-
}
|
|
98
|
-
break;
|
|
99
|
-
|
|
100
|
-
default:
|
|
101
|
-
throw new Error(`不支持的方法: ${msg.method}`);
|
|
140
|
+
},
|
|
141
|
+
required: ['a', 'b']
|
|
142
|
+
}
|
|
102
143
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
144
|
+
]
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 处理工具调用请求
|
|
150
|
+
* @param {Object} params - 请求参数
|
|
151
|
+
* @param {string} params.name - 工具名称
|
|
152
|
+
* @param {Object} params.arguments - 工具参数
|
|
153
|
+
* @returns {Object} 工具执行结果
|
|
154
|
+
*/
|
|
155
|
+
function handleToolCall(params) {
|
|
156
|
+
const { name, arguments: args } = params;
|
|
157
|
+
|
|
158
|
+
if (name === 'add_numbers') {
|
|
159
|
+
const { a, b } = args;
|
|
107
160
|
|
|
108
|
-
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
} else {
|
|
112
|
-
response.result = result;
|
|
161
|
+
// 参数类型验证
|
|
162
|
+
if (typeof a !== 'number' || typeof b !== 'number') {
|
|
163
|
+
throw new Error('参数必须是数字');
|
|
113
164
|
}
|
|
114
165
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
166
|
+
// 计算并返回结果
|
|
167
|
+
return {
|
|
168
|
+
content: [
|
|
169
|
+
{
|
|
170
|
+
type: 'text',
|
|
171
|
+
text: `${a} + ${b} = ${a + b}`
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
} else {
|
|
177
|
+
throw new Error(`未知工具: ${name}`);
|
|
118
178
|
}
|
|
119
|
-
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ========== 清理和退出 ==========
|
|
120
182
|
|
|
183
|
+
// 当连接关闭时退出进程
|
|
121
184
|
rl.on('close', () => {
|
|
122
|
-
console.error('[MCP] 连接关闭,退出服务');
|
|
123
185
|
process.exit(0);
|
|
124
186
|
});
|
|
125
187
|
|
|
126
|
-
//
|
|
188
|
+
// 当 stdin 结束时退出进程(防止 Node.js 阻塞)
|
|
127
189
|
process.stdin.on('end', () => {
|
|
128
190
|
process.exit(0);
|
|
129
191
|
});
|