tom-echo-mcp 1.0.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 +118 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +94 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.js +11 -0
- package/mcp-config-example.json +13 -0
- package/package.json +30 -0
- package/src/index.ts +114 -0
- package/src/worker.ts +13 -0
- package/tsconfig.json +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Tom Echo MCP 服务器
|
|
2
|
+
|
|
3
|
+
一个支持多线程的 MCP (Model Context Protocol) Echo 服务器,用于演示基本的 MCP 工具功能和多线程处理。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 提供一个 `echo` 工具,返回接收到的任何消息
|
|
8
|
+
- 支持多线程处理,使用 worker pool 提高并发性能
|
|
9
|
+
- 可配置工作线程数量
|
|
10
|
+
- 基于 TypeScript 开发
|
|
11
|
+
|
|
12
|
+
## 安装
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 构建
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm run build
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 使用方法
|
|
25
|
+
|
|
26
|
+
### 直接运行
|
|
27
|
+
|
|
28
|
+
使用默认配置(4个工作线程):
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm start
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 配置线程数量
|
|
35
|
+
|
|
36
|
+
通过环境变量 `WORKER_THREADS` 配置工作线程数量:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
WORKER_THREADS=8 npm start
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 在 MCP 客户端中配置
|
|
43
|
+
|
|
44
|
+
在你的 MCP 客户端配置文件中添加:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"tom-echo": {
|
|
50
|
+
"command": "node",
|
|
51
|
+
"args": ["/Users/tom/Desktop/tom_echo/dist/index.js"],
|
|
52
|
+
"env": {
|
|
53
|
+
"WORKER_THREADS": "8"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
或者使用 npm 运行:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"mcpServers": {
|
|
65
|
+
"tom-echo": {
|
|
66
|
+
"command": "npm",
|
|
67
|
+
"args": ["start"],
|
|
68
|
+
"cwd": "/Users/tom/Desktop/tom_echo",
|
|
69
|
+
"env": {
|
|
70
|
+
"WORKER_THREADS": "8"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## API
|
|
78
|
+
|
|
79
|
+
### echo 工具
|
|
80
|
+
|
|
81
|
+
回显输入的消息内容。
|
|
82
|
+
|
|
83
|
+
**参数:**
|
|
84
|
+
- `message` (string, 必需): 要回显的消息内容
|
|
85
|
+
|
|
86
|
+
**返回:**
|
|
87
|
+
- 返回与输入相同的消息内容
|
|
88
|
+
|
|
89
|
+
**示例:**
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"name": "echo",
|
|
93
|
+
"arguments": {
|
|
94
|
+
"message": "Hello, World!"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
返回:`Hello, World!`
|
|
100
|
+
|
|
101
|
+
## 技术栈
|
|
102
|
+
|
|
103
|
+
- **@modelcontextprotocol/sdk**: MCP 协议实现
|
|
104
|
+
- **workerpool**: Node.js 工作线程池管理
|
|
105
|
+
- **TypeScript**: 类型安全的开发体验
|
|
106
|
+
|
|
107
|
+
## 架构说明
|
|
108
|
+
|
|
109
|
+
本项目使用 `workerpool` 库实现多线程支持:
|
|
110
|
+
|
|
111
|
+
1. 主线程运行 MCP 服务器,处理请求和响应
|
|
112
|
+
2. Worker 线程池处理实际的 echo 操作
|
|
113
|
+
3. 请求会自动分配到空闲的 worker 线程
|
|
114
|
+
4. 支持动态配置线程数量,适应不同的负载需求
|
|
115
|
+
|
|
116
|
+
## 许可证
|
|
117
|
+
|
|
118
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import * as workerpool from 'workerpool';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
// 从环境变量读取线程数配置,默认为 4
|
|
11
|
+
const WORKER_THREADS = parseInt(process.env.WORKER_THREADS || '4', 10);
|
|
12
|
+
// 创建 worker pool
|
|
13
|
+
const pool = workerpool.pool(join(__dirname, 'worker.js'), {
|
|
14
|
+
maxWorkers: WORKER_THREADS,
|
|
15
|
+
minWorkers: Math.min(2, WORKER_THREADS)
|
|
16
|
+
});
|
|
17
|
+
console.error(`Echo MCP 服务器启动,使用 ${WORKER_THREADS} 个工作线程`);
|
|
18
|
+
const server = new Server({
|
|
19
|
+
name: "tom-echo-mcp",
|
|
20
|
+
version: "1.0.0",
|
|
21
|
+
}, {
|
|
22
|
+
capabilities: {
|
|
23
|
+
tools: {},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
// 列出可用的工具
|
|
27
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
28
|
+
return {
|
|
29
|
+
tools: [
|
|
30
|
+
{
|
|
31
|
+
name: "echo",
|
|
32
|
+
description: "回显输入的消息。支持多线程处理,传入什么消息就返回什么消息。",
|
|
33
|
+
inputSchema: {
|
|
34
|
+
type: "object",
|
|
35
|
+
properties: {
|
|
36
|
+
message: {
|
|
37
|
+
type: "string",
|
|
38
|
+
description: "要回显的消息内容",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
required: ["message"],
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
// 处理工具调用
|
|
48
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
49
|
+
if (request.params.name === "echo") {
|
|
50
|
+
const message = request.params.arguments?.message;
|
|
51
|
+
if (typeof message !== "string") {
|
|
52
|
+
throw new Error("参数 'message' 必须是字符串类型");
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
// 使用 worker pool 执行 echo 操作
|
|
56
|
+
const result = await pool.exec('echo', [message]);
|
|
57
|
+
return {
|
|
58
|
+
content: [
|
|
59
|
+
{
|
|
60
|
+
type: "text",
|
|
61
|
+
text: result,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw new Error(`Echo 执行失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
throw new Error(`未知的工具: ${request.params.name}`);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
// 启动服务器
|
|
75
|
+
async function main() {
|
|
76
|
+
const transport = new StdioServerTransport();
|
|
77
|
+
await server.connect(transport);
|
|
78
|
+
console.error("Echo MCP 服务器已连接并运行中...");
|
|
79
|
+
}
|
|
80
|
+
// 优雅关闭
|
|
81
|
+
process.on('SIGINT', async () => {
|
|
82
|
+
console.error('\n正在关闭 worker pool...');
|
|
83
|
+
await pool.terminate();
|
|
84
|
+
process.exit(0);
|
|
85
|
+
});
|
|
86
|
+
process.on('SIGTERM', async () => {
|
|
87
|
+
console.error('\n正在关闭 worker pool...');
|
|
88
|
+
await pool.terminate();
|
|
89
|
+
process.exit(0);
|
|
90
|
+
});
|
|
91
|
+
main().catch((error) => {
|
|
92
|
+
console.error("服务器启动失败:", error);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
});
|
package/dist/worker.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/worker.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tom-echo-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "一个支持多线程的 MCP Echo 服务器",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"tom-echo-mcp": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"prepare": "npm run build",
|
|
13
|
+
"start": "node dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"echo",
|
|
18
|
+
"worker-threads"
|
|
19
|
+
],
|
|
20
|
+
"author": "",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
24
|
+
"workerpool": "^9.2.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^22.10.5",
|
|
28
|
+
"typescript": "^5.7.3"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import {
|
|
6
|
+
CallToolRequestSchema,
|
|
7
|
+
ListToolsRequestSchema,
|
|
8
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
import * as workerpool from 'workerpool';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { dirname, join } from 'path';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = dirname(__filename);
|
|
15
|
+
|
|
16
|
+
// 从环境变量读取线程数配置,默认为 4
|
|
17
|
+
const WORKER_THREADS = parseInt(process.env.WORKER_THREADS || '4', 10);
|
|
18
|
+
|
|
19
|
+
// 创建 worker pool
|
|
20
|
+
const pool = workerpool.pool(join(__dirname, 'worker.js'), {
|
|
21
|
+
maxWorkers: WORKER_THREADS,
|
|
22
|
+
minWorkers: Math.min(2, WORKER_THREADS)
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
console.error(`Echo MCP 服务器启动,使用 ${WORKER_THREADS} 个工作线程`);
|
|
26
|
+
|
|
27
|
+
const server = new Server(
|
|
28
|
+
{
|
|
29
|
+
name: "tom-echo-mcp",
|
|
30
|
+
version: "1.0.0",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
capabilities: {
|
|
34
|
+
tools: {},
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// 列出可用的工具
|
|
40
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
41
|
+
return {
|
|
42
|
+
tools: [
|
|
43
|
+
{
|
|
44
|
+
name: "echo",
|
|
45
|
+
description: "回显输入的消息。支持多线程处理,传入什么消息就返回什么消息。",
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
message: {
|
|
50
|
+
type: "string",
|
|
51
|
+
description: "要回显的消息内容",
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
required: ["message"],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// 处理工具调用
|
|
62
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
63
|
+
if (request.params.name === "echo") {
|
|
64
|
+
const message = request.params.arguments?.message;
|
|
65
|
+
|
|
66
|
+
if (typeof message !== "string") {
|
|
67
|
+
throw new Error("参数 'message' 必须是字符串类型");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
// 使用 worker pool 执行 echo 操作
|
|
72
|
+
const result = await pool.exec('echo', [message]) as string;
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
content: [
|
|
76
|
+
{
|
|
77
|
+
type: "text",
|
|
78
|
+
text: result,
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
} catch (error) {
|
|
83
|
+
throw new Error(`Echo 执行失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
throw new Error(`未知的工具: ${request.params.name}`);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// 启动服务器
|
|
91
|
+
async function main() {
|
|
92
|
+
const transport = new StdioServerTransport();
|
|
93
|
+
await server.connect(transport);
|
|
94
|
+
|
|
95
|
+
console.error("Echo MCP 服务器已连接并运行中...");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 优雅关闭
|
|
99
|
+
process.on('SIGINT', async () => {
|
|
100
|
+
console.error('\n正在关闭 worker pool...');
|
|
101
|
+
await pool.terminate();
|
|
102
|
+
process.exit(0);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
process.on('SIGTERM', async () => {
|
|
106
|
+
console.error('\n正在关闭 worker pool...');
|
|
107
|
+
await pool.terminate();
|
|
108
|
+
process.exit(0);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
main().catch((error) => {
|
|
112
|
+
console.error("服务器启动失败:", error);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
});
|
package/src/worker.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ES2022",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"rootDir": "./src",
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"declaration": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*"],
|
|
17
|
+
"exclude": ["node_modules", "dist"]
|
|
18
|
+
}
|