freeform-modeling-mcp 1.0.29 → 1.0.30
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/.cursor/mcp.json +26 -0
- package/package.json +1 -1
- package/src/commands/start.ts +1 -1
- package/src/lib/wsbridge/bridge.ts +33 -6
- package/src/lib/wsbridge/lock.ts +2 -2
package/.cursor/mcp.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"freeform-modeling-mcp": {
|
|
4
|
+
"command": "npx",
|
|
5
|
+
"args": [
|
|
6
|
+
"tsx",
|
|
7
|
+
"src/cli.ts",
|
|
8
|
+
"start",
|
|
9
|
+
"--stdio"
|
|
10
|
+
],
|
|
11
|
+
"cwd": "D:\\wain\\mcp-server"
|
|
12
|
+
},
|
|
13
|
+
"aholo-sdk-mcp": {
|
|
14
|
+
"type": "stdio",
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": [
|
|
17
|
+
"-y",
|
|
18
|
+
"@manycore/aholo-sdk-mcp"
|
|
19
|
+
],
|
|
20
|
+
"env": {
|
|
21
|
+
"AHOLO_API_KEY": "urSuPSeAcEnNEEn",
|
|
22
|
+
"AHOLO_REGION": "cn"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
package/package.json
CHANGED
package/src/commands/start.ts
CHANGED
|
@@ -18,7 +18,7 @@ export async function startMCPServer(options: { dev?: boolean, stdio?: boolean }
|
|
|
18
18
|
const wsBridge = new WebSocketBridge();
|
|
19
19
|
await wsBridge.initialize();
|
|
20
20
|
const wsPort = wsBridge.getPort();
|
|
21
|
-
const wsUrl = `ws://
|
|
21
|
+
const wsUrl = `ws://127.0.0.1:${wsPort}`;
|
|
22
22
|
|
|
23
23
|
await llmClient.connect(wsUrl);
|
|
24
24
|
|
|
@@ -6,6 +6,25 @@ import * as http from 'http';
|
|
|
6
6
|
import { BridgeLockManager, getActiveBridges } from './lock';
|
|
7
7
|
import logger from '../logger';
|
|
8
8
|
|
|
9
|
+
function isAllowedOrigin(origin: string): boolean {
|
|
10
|
+
try {
|
|
11
|
+
const { hostname } = new URL(origin);
|
|
12
|
+
return hostname === 'localhost' || hostname === '127.0.0.1'
|
|
13
|
+
|| hostname === 'kujiale.com' || hostname.endsWith('.kujiale.com')
|
|
14
|
+
|| hostname === 'coohom.com' || hostname.endsWith('.coohom.com');
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function setCors(req: http.IncomingMessage, res: http.ServerResponse): void {
|
|
21
|
+
const origin = req.headers.origin;
|
|
22
|
+
if (origin && isAllowedOrigin(origin)) {
|
|
23
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
24
|
+
res.setHeader('Vary', 'Origin');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
9
28
|
// 客户端类型
|
|
10
29
|
export enum ClientType {
|
|
11
30
|
MCP = 'mcp',
|
|
@@ -101,14 +120,21 @@ export class WebSocketBridge extends EventEmitter {
|
|
|
101
120
|
// 使用锁管理器获取可用端口
|
|
102
121
|
this.port = await this.lockManager.initialize();
|
|
103
122
|
|
|
104
|
-
// 创建 HTTP
|
|
123
|
+
// 创建 HTTP 服务器(与 WebSocket 共用端口;/bridge-status 供浏览器发现)
|
|
105
124
|
this.httpServer = http.createServer((req, res) => {
|
|
106
|
-
|
|
125
|
+
if (req.method === 'OPTIONS') {
|
|
126
|
+
setCors(req, res);
|
|
127
|
+
res.writeHead(204);
|
|
128
|
+
res.end();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
107
131
|
if (req.url === '/bridge-status') {
|
|
132
|
+
setCors(req, res);
|
|
108
133
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
109
134
|
res.end(JSON.stringify({
|
|
110
135
|
service: 'WebSocketBridge',
|
|
111
136
|
version: '1.0.0',
|
|
137
|
+
port: this.port,
|
|
112
138
|
status: this._status,
|
|
113
139
|
clients: {
|
|
114
140
|
total: this.clients.size,
|
|
@@ -122,8 +148,10 @@ export class WebSocketBridge extends EventEmitter {
|
|
|
122
148
|
}
|
|
123
149
|
});
|
|
124
150
|
|
|
125
|
-
|
|
126
|
-
|
|
151
|
+
this.server = new WebSocketServer({
|
|
152
|
+
server: this.httpServer,
|
|
153
|
+
verifyClient: ({ origin }) => !origin || isAllowedOrigin(origin),
|
|
154
|
+
});
|
|
127
155
|
|
|
128
156
|
// 设置事件处理程序
|
|
129
157
|
this.setupEventHandlers();
|
|
@@ -184,8 +212,7 @@ export class WebSocketBridge extends EventEmitter {
|
|
|
184
212
|
}
|
|
185
213
|
});
|
|
186
214
|
|
|
187
|
-
|
|
188
|
-
this.httpServer!.listen(this.port);
|
|
215
|
+
this.httpServer!.listen(this.port, '127.0.0.1');
|
|
189
216
|
} catch (error) {
|
|
190
217
|
logger.error('Failed to start WebSocketBridge:', error);
|
|
191
218
|
reject(error);
|
package/src/lib/wsbridge/lock.ts
CHANGED
|
@@ -75,7 +75,7 @@ function isProcessRunning(pid: number): boolean {
|
|
|
75
75
|
// 检查特定端口是否有WebSocketBridge服务响应
|
|
76
76
|
async function checkBridgeAtPort(port: number): Promise<boolean> {
|
|
77
77
|
return new Promise((resolve) => {
|
|
78
|
-
const req = http.get(`http://
|
|
78
|
+
const req = http.get(`http://127.0.0.1:${port}/bridge-status`, (res) => {
|
|
79
79
|
// 收到响应,检查是否是我们的服务
|
|
80
80
|
let data = '';
|
|
81
81
|
res.on('data', (chunk) => {
|
|
@@ -186,7 +186,7 @@ export class BridgeLockManager extends EventEmitter {
|
|
|
186
186
|
if (!portAvailable) {
|
|
187
187
|
logger.info(`Port ${this.port} is not available, searching for another port...`);
|
|
188
188
|
try {
|
|
189
|
-
this.port = await findAvailablePort(this.port + 1);
|
|
189
|
+
this.port = await findAvailablePort(this.port + 1, 10);
|
|
190
190
|
logger.info(`Found available port: ${this.port}`);
|
|
191
191
|
} catch (e) {
|
|
192
192
|
logger.error(`Cannot find available port:`, e.message);
|