computer_mcp 1.0.1 → 1.0.3

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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/server.js +51 -27
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "computer_mcp",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "MCP Streamable HTTP Server with file and command execution tools",
5
5
  "main": "server.js",
6
6
  "type": "module",
7
7
  "bin": {
8
- "computer-mcp": "./server.js"
8
+ "computer-mcp": "server.js"
9
9
  },
10
10
  "files": [
11
11
  "server.js",
package/server.js CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
4
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
5
- import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/index.js";
6
5
  import express from "express";
7
6
  import { randomUUID } from 'node:crypto';
8
7
  import { registerBashTool } from './tools/bash.js';
@@ -10,27 +9,25 @@ import { registerFileTools } from './tools/file.js';
10
9
  import { registerInteractiveBashTool } from './tools/interactive.js';
11
10
  import { loadSkills, getSkillDetails } from './tools/skills.js';
12
11
 
13
- // 创建 MCP 服务器
14
- const server = new McpServer(
15
- {
16
- name: 'computer-mcp-server',
17
- version: '1.0.0'
18
- },
19
- {
20
- capabilities: {
21
- logging: {},
22
- tools: {}
12
+ /** 每个 Streamable HTTP 会话需要独立的 McpServer(协议层与 transport 一对一) */
13
+ function createComputerMcpServer() {
14
+ const server = new McpServer(
15
+ {
16
+ name: 'computer-mcp-server',
17
+ version: '1.0.0'
18
+ },
19
+ {
20
+ capabilities: {
21
+ logging: {},
22
+ tools: {}
23
+ }
23
24
  }
24
- }
25
- );
25
+ );
26
+ registerInteractiveBashTool(server);
27
+ registerFileTools(server);
28
+ return server;
29
+ }
26
30
 
27
- // 注册工具
28
- registerInteractiveBashTool(server);
29
- // registerBashTool(server);
30
- registerFileTools(server);
31
-
32
- // // 创建 Express 应用
33
- // const app = createMcpExpressApp();
34
31
  const app = express();
35
32
 
36
33
  // 健康检查端点
@@ -109,26 +106,40 @@ app.get('/skills/:name', async (req, res) => {
109
106
  }
110
107
  });
111
108
 
112
- // 管理传输层的 Map
113
- const transports = new Map();
109
+ // sessionId -> { transport, mcpServer }
110
+ const sessions = new Map();
114
111
 
115
112
  // MCP 端点处理
116
113
  app.all('/mcp', async (req, res) => {
117
114
  try {
118
- // 重用现有传输层或创建新的
119
- const sessionId = req.headers['mcp-session-id'];
120
- let transport = sessionId ? transports.get(sessionId) : undefined;
115
+ const rawSessionId = req.headers['mcp-session-id'];
116
+ const sessionId = Array.isArray(rawSessionId)
117
+ ? rawSessionId[rawSessionId.length - 1]
118
+ : rawSessionId;
119
+
120
+ let entry = sessionId ? sessions.get(sessionId) : undefined;
121
+ let transport = entry?.transport;
122
+ let mcpServer = entry?.mcpServer;
121
123
 
122
124
  if (!transport) {
125
+ mcpServer = createComputerMcpServer();
123
126
  transport = new StreamableHTTPServerTransport({
124
127
  sessionIdGenerator: () => randomUUID(),
125
128
  retryInterval: 2000, // 默认重试间隔用于 priming events
126
129
  onsessioninitialized: id => {
127
130
  console.log(`[${id}] Session initialized`);
128
- transports.set(id, transport);
131
+ sessions.set(id, { transport, mcpServer });
132
+ },
133
+ onsessionclosed: async id => {
134
+ sessions.delete(id);
135
+ try {
136
+ await mcpServer.close();
137
+ } catch (e) {
138
+ console.error('Error closing MCP server:', e);
139
+ }
129
140
  }
130
141
  });
131
- await server.connect(transport);
142
+ await mcpServer.connect(transport);
132
143
  }
133
144
 
134
145
  await transport.handleRequest(req, res, req.body);
@@ -163,6 +174,19 @@ app.listen(PORT, error => {
163
174
  // 处理服务器关闭
164
175
  process.on('SIGINT', async () => {
165
176
  console.log('Shutting down server...');
177
+ for (const [, { transport, mcpServer }] of sessions) {
178
+ try {
179
+ await mcpServer.close();
180
+ } catch (e) {
181
+ console.error(e);
182
+ }
183
+ try {
184
+ await transport.close();
185
+ } catch (e) {
186
+ console.error(e);
187
+ }
188
+ }
189
+ sessions.clear();
166
190
  process.exit(0);
167
191
  });
168
192