@atlisp/mcp 1.0.6 → 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/README.md +3 -0
- package/package.json +1 -1
- package/src/cad-worker.js +30 -50
- package/src/cad.js +3 -1
- package/src/index.js +2 -3
package/README.md
CHANGED
|
@@ -123,6 +123,9 @@ atlisp-mcp
|
|
|
123
123
|
| `TRANSPORT` | `http` | 传输模式:`http` 或 `stdio` |
|
|
124
124
|
| `PORT` | `8110` | HTTP 模式监听端口 |
|
|
125
125
|
| `HOST` | `0.0.0.0` | HTTP 模式监听地址 |
|
|
126
|
+
| `MESSAGE_TIMEOUT` | `60000` | 消息超时(毫秒) |
|
|
127
|
+
| `BUSY_RETRIES` | `10` | CAD 忙碌时重试次数 |
|
|
128
|
+
| `BUSY_DELAY` | `500` | CAD 忙碌重试间隔(毫秒) |
|
|
126
129
|
|
|
127
130
|
## API
|
|
128
131
|
|
package/package.json
CHANGED
package/src/cad-worker.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import edge from 'edge-js';
|
|
3
3
|
import process from 'process';
|
|
4
4
|
|
|
5
|
+
const BUSY_RETRIES = parseInt(process.env.BUSY_RETRIES || '10', 10);
|
|
6
|
+
const BUSY_DELAY = parseInt(process.env.BUSY_DELAY || '500', 10);
|
|
7
|
+
|
|
5
8
|
const cadConnect = edge.func(function() {/*
|
|
6
9
|
async (input) => {
|
|
7
10
|
// Try existing CAD instances
|
|
@@ -104,16 +107,6 @@ const cadSend = edge.func(function() {/*
|
|
|
104
107
|
dynamic cad = System.Runtime.InteropServices.Marshal.GetActiveObject(progId);
|
|
105
108
|
if (cad != null) {
|
|
106
109
|
dynamic doc = cad.ActiveDocument;
|
|
107
|
-
if (doc == null || doc.Name == "") {
|
|
108
|
-
string templatePath = @"C:\Users\Public\Documents\AutoCAD 2024\Sample\basics.dwg";
|
|
109
|
-
if (System.IO.File.Exists(templatePath)) {
|
|
110
|
-
cad.Documents.Open(templatePath, false);
|
|
111
|
-
} else {
|
|
112
|
-
cad.Documents.Add("");
|
|
113
|
-
}
|
|
114
|
-
System.Threading.Thread.Sleep(2000);
|
|
115
|
-
}
|
|
116
|
-
doc = cad.ActiveDocument;
|
|
117
110
|
if (doc != null) {
|
|
118
111
|
doc.SendCommand(code);
|
|
119
112
|
return new { success = true };
|
|
@@ -122,7 +115,7 @@ const cadSend = edge.func(function() {/*
|
|
|
122
115
|
} catch {}
|
|
123
116
|
return new { success = false };
|
|
124
117
|
}
|
|
125
|
-
*/});
|
|
118
|
+
*/});
|
|
126
119
|
|
|
127
120
|
const cadSendWithResult = edge.func(function() {/*
|
|
128
121
|
async (input) => {
|
|
@@ -134,22 +127,13 @@ const cadSendWithResult = edge.func(function() {/*
|
|
|
134
127
|
string tempDir = System.IO.Path.GetTempPath();
|
|
135
128
|
string tempFile = System.IO.Path.Combine(tempDir, "atlisp_result_" + System.Guid.NewGuid().ToString("N") + ".txt");
|
|
136
129
|
|
|
137
|
-
|
|
130
|
+
// Use print to write result directly to file
|
|
131
|
+
string lispCode = "(progn(setq f(open \"" + tempFile.Replace("\\", "\\\\") + "\" \"w\"))(print " + code + " f)(close f))";
|
|
138
132
|
|
|
139
133
|
try {
|
|
140
134
|
dynamic cad = System.Runtime.InteropServices.Marshal.GetActiveObject(progId);
|
|
141
135
|
if (cad != null) {
|
|
142
136
|
dynamic doc = cad.ActiveDocument;
|
|
143
|
-
if (doc == null || doc.Name == "") {
|
|
144
|
-
string templatePath = @"C:\Users\Public\Documents\AutoCAD 2024\Sample\basics.dwg";
|
|
145
|
-
if (System.IO.File.Exists(templatePath)) {
|
|
146
|
-
cad.Documents.Open(templatePath, false);
|
|
147
|
-
} else {
|
|
148
|
-
cad.Documents.Add("");
|
|
149
|
-
}
|
|
150
|
-
System.Threading.Thread.Sleep(2000);
|
|
151
|
-
}
|
|
152
|
-
doc = cad.ActiveDocument;
|
|
153
137
|
if (doc != null) {
|
|
154
138
|
doc.SendCommand(lispCode + "\n");
|
|
155
139
|
System.Threading.Thread.Sleep(500);
|
|
@@ -157,7 +141,11 @@ const cadSendWithResult = edge.func(function() {/*
|
|
|
157
141
|
if (System.IO.File.Exists(tempFile)) {
|
|
158
142
|
string result = System.IO.File.ReadAllText(tempFile).Trim();
|
|
159
143
|
try { System.IO.File.Delete(tempFile); } catch {}
|
|
160
|
-
|
|
144
|
+
if (!string.IsNullOrEmpty(result)) {
|
|
145
|
+
return new { success = true, result = result };
|
|
146
|
+
}
|
|
147
|
+
// Try evaluate result directly if file is empty
|
|
148
|
+
return new { success = true, result = "" };
|
|
161
149
|
}
|
|
162
150
|
return new { success = true, result = "" };
|
|
163
151
|
}
|
|
@@ -169,7 +157,7 @@ const cadSendWithResult = edge.func(function() {/*
|
|
|
169
157
|
try { if (System.IO.File.Exists(tempFile)) System.IO.File.Delete(tempFile); } catch {}
|
|
170
158
|
return new { success = false };
|
|
171
159
|
}
|
|
172
|
-
*/});
|
|
160
|
+
*/});
|
|
173
161
|
|
|
174
162
|
process.stdin.setEncoding('utf8');
|
|
175
163
|
|
|
@@ -242,6 +230,22 @@ const cadNewDoc = edge.func(function() {/*
|
|
|
242
230
|
}
|
|
243
231
|
*/});
|
|
244
232
|
|
|
233
|
+
async function waitForIdle(platform) {
|
|
234
|
+
let retries = BUSY_RETRIES;
|
|
235
|
+
while (retries > 0) {
|
|
236
|
+
const checkResult = await new Promise((resolve, reject) => {
|
|
237
|
+
cadIsBusy(platform || 'AutoCAD', (e, r) => {
|
|
238
|
+
if (e) reject(e);
|
|
239
|
+
else resolve(r);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
if (!checkResult.isBusy) return true;
|
|
243
|
+
retries--;
|
|
244
|
+
if (retries > 0) await new Promise(resolve => setTimeout(resolve, BUSY_DELAY));
|
|
245
|
+
}
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
|
|
245
249
|
async function handleMessage(msg) {
|
|
246
250
|
if (msg.type === 'connect') {
|
|
247
251
|
return new Promise((resolve, reject) => {
|
|
@@ -277,19 +281,7 @@ async function handleMessage(msg) {
|
|
|
277
281
|
if (!docCheck.hasDoc) {
|
|
278
282
|
return { success: false, error: 'No open document' };
|
|
279
283
|
}
|
|
280
|
-
|
|
281
|
-
while (retries > 0) {
|
|
282
|
-
const checkResult = await new Promise((resolve, reject) => {
|
|
283
|
-
cadIsBusy(msg.platform || 'AutoCAD', (e, r) => {
|
|
284
|
-
if (e) reject(e);
|
|
285
|
-
else resolve(r);
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
if (!checkResult.isBusy) break;
|
|
289
|
-
retries--;
|
|
290
|
-
if (retries > 0) await new Promise(resolve => setTimeout(resolve, 500));
|
|
291
|
-
}
|
|
292
|
-
if (retries === 0) {
|
|
284
|
+
if (!(await waitForIdle(msg.platform))) {
|
|
293
285
|
return { success: false, error: 'CAD is busy, timeout' };
|
|
294
286
|
}
|
|
295
287
|
return new Promise((resolve, reject) => {
|
|
@@ -309,19 +301,7 @@ async function handleMessage(msg) {
|
|
|
309
301
|
if (!docCheck.hasDoc) {
|
|
310
302
|
return { success: false, error: 'No open document' };
|
|
311
303
|
}
|
|
312
|
-
|
|
313
|
-
while (retries > 0) {
|
|
314
|
-
const checkResult = await new Promise((resolve, reject) => {
|
|
315
|
-
cadIsBusy(msg.platform || 'AutoCAD', (e, r) => {
|
|
316
|
-
if (e) reject(e);
|
|
317
|
-
else resolve(r);
|
|
318
|
-
});
|
|
319
|
-
});
|
|
320
|
-
if (!checkResult.isBusy) break;
|
|
321
|
-
retries--;
|
|
322
|
-
if (retries > 0) await new Promise(resolve => setTimeout(resolve, 500));
|
|
323
|
-
}
|
|
324
|
-
if (retries === 0) {
|
|
304
|
+
if (!(await waitForIdle(msg.platform))) {
|
|
325
305
|
return { success: false, error: 'CAD is busy, timeout' };
|
|
326
306
|
}
|
|
327
307
|
return new Promise((resolve, reject) => {
|
package/src/cad.js
CHANGED
|
@@ -11,6 +11,8 @@ const FILE_EXTENSIONS = {
|
|
|
11
11
|
'BricsCAD': ['.des']
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
+
const MESSAGE_TIMEOUT = parseInt(process.env.MESSAGE_TIMEOUT || '60000', 10);
|
|
15
|
+
|
|
14
16
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
17
|
const workerPath = path.join(__dirname, 'cad-worker.js');
|
|
16
18
|
|
|
@@ -44,7 +46,7 @@ function sendMessage(msg) {
|
|
|
44
46
|
responded = true;
|
|
45
47
|
reject(new Error('Timeout waiting for worker'));
|
|
46
48
|
}
|
|
47
|
-
},
|
|
49
|
+
}, MESSAGE_TIMEOUT);
|
|
48
50
|
|
|
49
51
|
const handler = (data) => {
|
|
50
52
|
try {
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
-
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
5
4
|
import {
|
|
6
5
|
ListToolsRequestSchema,
|
|
7
6
|
CallToolRequestSchema,
|
|
@@ -223,7 +222,7 @@ async function handleToolCall(name, args) {
|
|
|
223
222
|
}
|
|
224
223
|
|
|
225
224
|
const mcpServer = new Server(
|
|
226
|
-
{ name: 'atlisp-mcp-server', version: '1.0.
|
|
225
|
+
{ name: 'atlisp-mcp-server', version: '1.0.7' },
|
|
227
226
|
{ capabilities: { tools: {} } }
|
|
228
227
|
);
|
|
229
228
|
|
|
@@ -283,7 +282,7 @@ if (TRANSPORT === 'stdio') {
|
|
|
283
282
|
result: {
|
|
284
283
|
protocolVersion: '2024-11-05',
|
|
285
284
|
capabilities: { tools: {} },
|
|
286
|
-
serverInfo: { name: 'atlisp-mcp-server', version: '1.0.
|
|
285
|
+
serverInfo: { name: 'atlisp-mcp-server', version: '1.0.7' }
|
|
287
286
|
}
|
|
288
287
|
});
|
|
289
288
|
}
|