@atlisp/mcp 1.3.8 → 1.4.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/dist/atlisp-mcp.js +210 -80
- package/package.json +1 -1
package/dist/atlisp-mcp.js
CHANGED
|
@@ -34,7 +34,8 @@ var SessionTransport = class {
|
|
|
34
34
|
this._started = true;
|
|
35
35
|
}
|
|
36
36
|
async send(message) {
|
|
37
|
-
if (this._closed)
|
|
37
|
+
if (this._closed)
|
|
38
|
+
return;
|
|
38
39
|
if (this._pendingRequest) {
|
|
39
40
|
const { resolve, reject, timeout } = this._pendingRequest;
|
|
40
41
|
clearTimeout(timeout);
|
|
@@ -43,7 +44,8 @@ var SessionTransport = class {
|
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
async close() {
|
|
46
|
-
if (this._closed)
|
|
47
|
+
if (this._closed)
|
|
48
|
+
return;
|
|
47
49
|
this._closed = true;
|
|
48
50
|
if (this._pendingRequest) {
|
|
49
51
|
const { reject, timeout } = this._pendingRequest;
|
|
@@ -117,7 +119,7 @@ var FILE_EXTENSIONS = {
|
|
|
117
119
|
"BricsCAD": [".des"]
|
|
118
120
|
};
|
|
119
121
|
var SERVER_NAME = "atlisp-mcp-server";
|
|
120
|
-
var SERVER_VERSION = "1.
|
|
122
|
+
var SERVER_VERSION = "1.4.0";
|
|
121
123
|
var MOCK_PACKAGES = [
|
|
122
124
|
{ name: "base", description: "\u57FA\u7840\u51FD\u6570\u5E93", version: "1.0.0" },
|
|
123
125
|
{ name: "at-pm", description: "\u5DE5\u7A0B\u9879\u76EE\u7BA1\u7406", version: "2.1.0" },
|
|
@@ -210,7 +212,8 @@ function setupStdoutHandler(w) {
|
|
|
210
212
|
const lines = buffer.split("\n");
|
|
211
213
|
buffer = lines.pop() || "";
|
|
212
214
|
for (const line of lines) {
|
|
213
|
-
if (!line.trim())
|
|
215
|
+
if (!line.trim())
|
|
216
|
+
continue;
|
|
214
217
|
try {
|
|
215
218
|
const result = JSON.parse(line);
|
|
216
219
|
const rid = result.requestId;
|
|
@@ -235,7 +238,8 @@ function setupStdoutHandler(w) {
|
|
|
235
238
|
}
|
|
236
239
|
function getWorker() {
|
|
237
240
|
if (!worker || !worker.connected) {
|
|
238
|
-
if (worker)
|
|
241
|
+
if (worker)
|
|
242
|
+
worker.kill();
|
|
239
243
|
worker = spawn("node", [workerPath], {
|
|
240
244
|
stdio: ["pipe", "pipe", "pipe"]
|
|
241
245
|
});
|
|
@@ -244,7 +248,8 @@ function getWorker() {
|
|
|
244
248
|
const w = worker;
|
|
245
249
|
w.on("exit", (code) => {
|
|
246
250
|
console.error("worker exited:", code);
|
|
247
|
-
if (w !== worker)
|
|
251
|
+
if (w !== worker)
|
|
252
|
+
return;
|
|
248
253
|
w.connected = false;
|
|
249
254
|
for (const [id, { reject, timeout }] of pendingRequests) {
|
|
250
255
|
clearTimeout(timeout);
|
|
@@ -263,7 +268,8 @@ function getWorker() {
|
|
|
263
268
|
return worker;
|
|
264
269
|
}
|
|
265
270
|
function startHeartbeat() {
|
|
266
|
-
if (heartbeatTimer)
|
|
271
|
+
if (heartbeatTimer)
|
|
272
|
+
clearInterval(heartbeatTimer);
|
|
267
273
|
heartbeatTimer = setInterval(async () => {
|
|
268
274
|
try {
|
|
269
275
|
const result = await sendMessage({ type: "ping" });
|
|
@@ -308,7 +314,8 @@ var CadConnection = class {
|
|
|
308
314
|
return process.platform === "win32";
|
|
309
315
|
}
|
|
310
316
|
async connect() {
|
|
311
|
-
if (!this.isAvailable())
|
|
317
|
+
if (!this.isAvailable())
|
|
318
|
+
return false;
|
|
312
319
|
try {
|
|
313
320
|
const result = await sendMessage({ type: "connect" });
|
|
314
321
|
if (result && result.success) {
|
|
@@ -324,13 +331,16 @@ var CadConnection = class {
|
|
|
324
331
|
return false;
|
|
325
332
|
}
|
|
326
333
|
async sendCommand(code) {
|
|
327
|
-
if (!this.connected)
|
|
334
|
+
if (!this.connected)
|
|
335
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
328
336
|
const result = await sendMessage({ type: "send", code, platform: _platform });
|
|
329
|
-
if (result.success)
|
|
337
|
+
if (result.success)
|
|
338
|
+
return true;
|
|
330
339
|
throw new Error(result.error || "\u53D1\u9001\u5931\u8D25");
|
|
331
340
|
}
|
|
332
341
|
async sendCommandWithResult(code, encoding = null) {
|
|
333
|
-
if (!this.connected)
|
|
342
|
+
if (!this.connected)
|
|
343
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
334
344
|
const result = await sendMessage({ type: "sendResult", code, platform: _platform, encoding: encoding || "" });
|
|
335
345
|
if (result.success) {
|
|
336
346
|
return result.result || "";
|
|
@@ -344,7 +354,8 @@ var CadConnection = class {
|
|
|
344
354
|
return this.product;
|
|
345
355
|
}
|
|
346
356
|
async isBusy() {
|
|
347
|
-
if (!this.connected)
|
|
357
|
+
if (!this.connected)
|
|
358
|
+
return false;
|
|
348
359
|
try {
|
|
349
360
|
const result = await sendMessage({ type: "isBusy", platform: _platform });
|
|
350
361
|
return result && result.isBusy;
|
|
@@ -353,7 +364,8 @@ var CadConnection = class {
|
|
|
353
364
|
}
|
|
354
365
|
}
|
|
355
366
|
async hasDoc() {
|
|
356
|
-
if (!this.connected)
|
|
367
|
+
if (!this.connected)
|
|
368
|
+
return { hasDoc: false, docCount: 0 };
|
|
357
369
|
try {
|
|
358
370
|
const result = await sendMessage({ type: "hasdoc", platform: _platform });
|
|
359
371
|
return result || { hasDoc: false, docCount: 0 };
|
|
@@ -362,7 +374,8 @@ var CadConnection = class {
|
|
|
362
374
|
}
|
|
363
375
|
}
|
|
364
376
|
async newDoc() {
|
|
365
|
-
if (!this.connected)
|
|
377
|
+
if (!this.connected)
|
|
378
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
366
379
|
try {
|
|
367
380
|
const result = await sendMessage({ type: "newdoc", platform: _platform });
|
|
368
381
|
return result && result.success;
|
|
@@ -371,7 +384,8 @@ var CadConnection = class {
|
|
|
371
384
|
}
|
|
372
385
|
}
|
|
373
386
|
async bringToFront() {
|
|
374
|
-
if (!this.connected)
|
|
387
|
+
if (!this.connected)
|
|
388
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
375
389
|
try {
|
|
376
390
|
const result = await sendMessage({ type: "bringToFront", platform: _platform });
|
|
377
391
|
return result && result.success;
|
|
@@ -380,7 +394,8 @@ var CadConnection = class {
|
|
|
380
394
|
}
|
|
381
395
|
}
|
|
382
396
|
async getInfo() {
|
|
383
|
-
if (!this.connected)
|
|
397
|
+
if (!this.connected)
|
|
398
|
+
return "CAD \u672A\u8FDE\u63A5";
|
|
384
399
|
return `Platform: ${this.product}, Version: ${this.version}, Status: Connected`;
|
|
385
400
|
}
|
|
386
401
|
async disconnect() {
|
|
@@ -455,7 +470,8 @@ async function evalLisp(code, withResult = false, encoding = null) {
|
|
|
455
470
|
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
456
471
|
}
|
|
457
472
|
const trimmed = (code || "").trim();
|
|
458
|
-
if (!trimmed)
|
|
473
|
+
if (!trimmed)
|
|
474
|
+
return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
|
|
459
475
|
try {
|
|
460
476
|
if (withResult) {
|
|
461
477
|
const result = await cad.sendCommandWithResult(trimmed, encoding);
|
|
@@ -475,14 +491,17 @@ async function getCadInfo() {
|
|
|
475
491
|
if (!cad.connected) {
|
|
476
492
|
await cad.connect();
|
|
477
493
|
}
|
|
478
|
-
if (!cad.connected)
|
|
494
|
+
if (!cad.connected)
|
|
495
|
+
return { content: [{ type: "text", text: "CAD \u672A\u8FDE\u63A5" }] };
|
|
479
496
|
const info = await cad.getInfo();
|
|
480
497
|
return { content: [{ type: "text", text: info }] };
|
|
481
498
|
}
|
|
482
499
|
async function atCommand(command) {
|
|
483
|
-
if (!cad.connected)
|
|
500
|
+
if (!cad.connected)
|
|
501
|
+
return { content: [{ type: "text", text: "\u8BF7\u5148\u8FDE\u63A5 CAD" }], isError: true };
|
|
484
502
|
const trimmed = (command || "").trim();
|
|
485
|
-
if (!trimmed)
|
|
503
|
+
if (!trimmed)
|
|
504
|
+
return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
|
|
486
505
|
await cad.sendCommand(trimmed + "\n");
|
|
487
506
|
return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001\u547D\u4EE4" }] };
|
|
488
507
|
}
|
|
@@ -490,7 +509,8 @@ async function newDocument() {
|
|
|
490
509
|
if (!cad.connected) {
|
|
491
510
|
await cad.connect();
|
|
492
511
|
}
|
|
493
|
-
if (!cad.connected)
|
|
512
|
+
if (!cad.connected)
|
|
513
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
494
514
|
const result = await cad.newDoc();
|
|
495
515
|
if (result) {
|
|
496
516
|
return { content: [{ type: "text", text: "\u5DF2\u5728 CAD \u4E2D\u65B0\u5EFA\u7A7A\u767D\u6587\u6863" }] };
|
|
@@ -501,7 +521,8 @@ async function bringToFront() {
|
|
|
501
521
|
if (!cad.connected) {
|
|
502
522
|
await cad.connect();
|
|
503
523
|
}
|
|
504
|
-
if (!cad.connected)
|
|
524
|
+
if (!cad.connected)
|
|
525
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
505
526
|
const result = await cad.bringToFront();
|
|
506
527
|
if (result) {
|
|
507
528
|
return { content: [{ type: "text", text: "\u5DF2\u5C06 CAD \u7A97\u53E3\u5207\u6362\u5230\u524D\u53F0" }] };
|
|
@@ -512,7 +533,8 @@ async function installAtlisp() {
|
|
|
512
533
|
if (!cad.connected) {
|
|
513
534
|
await cad.connect();
|
|
514
535
|
}
|
|
515
|
-
if (!cad.connected)
|
|
536
|
+
if (!cad.connected)
|
|
537
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
516
538
|
const installCode = `(progn(vl-load-com)(setq s strcat h "http" o(vlax-create-object (s"win"h".win"h"request.5.1"))v vlax-invoke e eval r read)(v o'open "get" (s h"://atlisp.""cn/@"):vlax-true)(v o'send)(v o'WaitforResponse 1000)(e(r(vlax-get-property o'ResponseText))))`;
|
|
517
539
|
await cad.sendCommand(installCode + "\n");
|
|
518
540
|
return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001 @lisp \u5B89\u88C5\u4EE3\u7801\u5230 CAD" }] };
|
|
@@ -521,20 +543,68 @@ async function listFunctionsInCad() {
|
|
|
521
543
|
if (!cad.connected) {
|
|
522
544
|
await cad.connect();
|
|
523
545
|
}
|
|
524
|
-
if (!cad.connected)
|
|
546
|
+
if (!cad.connected)
|
|
547
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
525
548
|
try {
|
|
526
549
|
const result = await cad.sendCommandWithResult("(atoms-family 0)", null);
|
|
527
|
-
if (result)
|
|
550
|
+
if (result)
|
|
551
|
+
return { content: [{ type: "text", text: result }] };
|
|
528
552
|
return { content: [{ type: "text", text: "CAD \u51FD\u6570\u5217\u8868\u4E3A\u7A7A" }] };
|
|
529
553
|
} catch (e) {
|
|
530
554
|
return { content: [{ type: "text", text: `\u9519\u8BEF: ${e.message}` }], isError: true };
|
|
531
555
|
}
|
|
532
556
|
}
|
|
557
|
+
async function getSystemStatus() {
|
|
558
|
+
const status = {
|
|
559
|
+
mcp: { version: process.env.npm_package_version || "unknown" },
|
|
560
|
+
worker: { alive: false },
|
|
561
|
+
cad: { connected: false, platform: null, version: null, busy: false, hasDoc: false },
|
|
562
|
+
lisp: { available: false, testResult: null, error: null },
|
|
563
|
+
packages: null
|
|
564
|
+
};
|
|
565
|
+
try {
|
|
566
|
+
status.worker.alive = await cad.ping();
|
|
567
|
+
} catch {
|
|
568
|
+
status.worker.alive = false;
|
|
569
|
+
}
|
|
570
|
+
status.cad.connected = cad.connected;
|
|
571
|
+
if (cad.connected) {
|
|
572
|
+
status.cad.platform = cad.getPlatform();
|
|
573
|
+
status.cad.version = cad.getVersion();
|
|
574
|
+
try {
|
|
575
|
+
status.cad.busy = await cad.isBusy();
|
|
576
|
+
} catch {
|
|
577
|
+
}
|
|
578
|
+
try {
|
|
579
|
+
const doc = await cad.hasDoc();
|
|
580
|
+
status.cad.hasDoc = doc.hasDoc;
|
|
581
|
+
} catch {
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
const r = await cad.sendCommandWithResult("(+ 1 2)");
|
|
585
|
+
if (r !== null && r !== void 0) {
|
|
586
|
+
status.lisp.available = true;
|
|
587
|
+
status.lisp.testResult = String(r).trim();
|
|
588
|
+
}
|
|
589
|
+
} catch (e) {
|
|
590
|
+
status.lisp.error = e.message;
|
|
591
|
+
}
|
|
592
|
+
try {
|
|
593
|
+
const pkgResult = await cad.sendCommandWithResult("(@::package-list-in-local)");
|
|
594
|
+
if (pkgResult && pkgResult !== "nil") {
|
|
595
|
+
status.packages = pkgResult;
|
|
596
|
+
}
|
|
597
|
+
} catch {
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return { content: [{ type: "text", text: JSON.stringify(status, null, 2) }] };
|
|
601
|
+
}
|
|
533
602
|
async function initAtlisp() {
|
|
534
603
|
if (!cad.connected) {
|
|
535
604
|
await cad.connect();
|
|
536
605
|
}
|
|
537
|
-
if (!cad.connected)
|
|
606
|
+
if (!cad.connected)
|
|
607
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
538
608
|
const code = `(if (null @::load-module)
|
|
539
609
|
(progn
|
|
540
610
|
(vl-load-com)
|
|
@@ -574,10 +644,13 @@ async function fetchPackages() {
|
|
|
574
644
|
return null;
|
|
575
645
|
}
|
|
576
646
|
async function listPackages() {
|
|
577
|
-
if (!cad.connected)
|
|
578
|
-
|
|
647
|
+
if (!cad.connected)
|
|
648
|
+
await cad.connect();
|
|
649
|
+
if (!cad.connected)
|
|
650
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
579
651
|
const result = await cad.sendCommandWithResult("(@::package-list-in-local)");
|
|
580
|
-
if (result && result !== "nil")
|
|
652
|
+
if (result && result !== "nil")
|
|
653
|
+
return { content: [{ type: "text", text: result }] };
|
|
581
654
|
const packages = MOCK_PACKAGES.map((p) => `${p.name} v${p.version} - ${p.description}`);
|
|
582
655
|
return { content: [{ type: "text", text: `\u5DF2\u5B89\u88C5\u7684 @lisp \u5305:
|
|
583
656
|
${packages.join("\n")}` }] };
|
|
@@ -594,10 +667,12 @@ async function searchPackages(query) {
|
|
|
594
667
|
for (const p of items) {
|
|
595
668
|
const name = (p.name || "").toLowerCase();
|
|
596
669
|
const desc = (p.description || "").toLowerCase();
|
|
597
|
-
if (name.includes(q) || desc.includes(q))
|
|
670
|
+
if (name.includes(q) || desc.includes(q))
|
|
671
|
+
results.push(p);
|
|
598
672
|
}
|
|
599
673
|
} else {
|
|
600
|
-
for (const p of items)
|
|
674
|
+
for (const p of items)
|
|
675
|
+
results.push(p);
|
|
601
676
|
}
|
|
602
677
|
if (results.length === 0) {
|
|
603
678
|
return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5305\u542B "${query}" \u7684\u5305` }] };
|
|
@@ -639,7 +714,8 @@ async function getFunctionUsage(funcName, packageName) {
|
|
|
639
714
|
const data = await response.json();
|
|
640
715
|
const funcs = Object.values(data.all_functions || {});
|
|
641
716
|
const func = funcs.find((f2) => f2.name === funcName || f2.name === `${packageName}:${funcName}`);
|
|
642
|
-
if (func)
|
|
717
|
+
if (func)
|
|
718
|
+
results.push(func);
|
|
643
719
|
}
|
|
644
720
|
} catch (e) {
|
|
645
721
|
log(`function-handlers fetch error: ${e.message}`);
|
|
@@ -650,7 +726,8 @@ async function getFunctionUsage(funcName, packageName) {
|
|
|
650
726
|
const raw = await fs2.readFile(path3.join(FUNCTIONS_DIR, file), "utf-8");
|
|
651
727
|
const data = JSON.parse(raw);
|
|
652
728
|
const func = data.functions?.find((f2) => f2.name === funcName);
|
|
653
|
-
if (func)
|
|
729
|
+
if (func)
|
|
730
|
+
results.push(func);
|
|
654
731
|
}
|
|
655
732
|
}
|
|
656
733
|
if (results.length === 0) {
|
|
@@ -742,11 +819,14 @@ function clearCache(uri) {
|
|
|
742
819
|
}
|
|
743
820
|
}
|
|
744
821
|
function parseLispList(str) {
|
|
745
|
-
if (!str || typeof str !== "string")
|
|
822
|
+
if (!str || typeof str !== "string")
|
|
823
|
+
return null;
|
|
746
824
|
const trimmed = str.trim();
|
|
747
|
-
if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
|
|
825
|
+
if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
|
|
826
|
+
return null;
|
|
748
827
|
const content = trimmed.slice(1, -1).trim();
|
|
749
|
-
if (!content)
|
|
828
|
+
if (!content)
|
|
829
|
+
return [];
|
|
750
830
|
const result = [];
|
|
751
831
|
let depth = 0;
|
|
752
832
|
let current = "";
|
|
@@ -788,15 +868,21 @@ function parseLispList(str) {
|
|
|
788
868
|
}
|
|
789
869
|
current += ch;
|
|
790
870
|
}
|
|
791
|
-
if (current.trim())
|
|
871
|
+
if (current.trim())
|
|
872
|
+
result.push(current.trim());
|
|
792
873
|
return result.map((item) => {
|
|
793
874
|
const t = item.trim();
|
|
794
|
-
if (t === "nil")
|
|
795
|
-
|
|
796
|
-
if (t === "
|
|
875
|
+
if (t === "nil")
|
|
876
|
+
return null;
|
|
877
|
+
if (t === "t")
|
|
878
|
+
return true;
|
|
879
|
+
if (t === "T")
|
|
880
|
+
return true;
|
|
797
881
|
const num = Number(t);
|
|
798
|
-
if (!isNaN(num) && t !== "")
|
|
799
|
-
|
|
882
|
+
if (!isNaN(num) && t !== "")
|
|
883
|
+
return num;
|
|
884
|
+
if (t.startsWith('"') && t.endsWith('"'))
|
|
885
|
+
return t.slice(1, -1);
|
|
800
886
|
return t;
|
|
801
887
|
});
|
|
802
888
|
}
|
|
@@ -811,14 +897,16 @@ var RESOURCES = [
|
|
|
811
897
|
];
|
|
812
898
|
function parseQuery(uri) {
|
|
813
899
|
const qIdx = uri.indexOf("?");
|
|
814
|
-
if (qIdx === -1)
|
|
900
|
+
if (qIdx === -1)
|
|
901
|
+
return { base: uri, params: {} };
|
|
815
902
|
const base = uri.substring(0, qIdx);
|
|
816
903
|
const params = {};
|
|
817
904
|
uri.substring(qIdx + 1).split("&").forEach((p) => {
|
|
818
905
|
const eqIdx = p.indexOf("=");
|
|
819
906
|
const k = eqIdx === -1 ? p : p.substring(0, eqIdx);
|
|
820
907
|
const v = eqIdx === -1 ? "" : p.substring(eqIdx + 1);
|
|
821
|
-
if (k)
|
|
908
|
+
if (k)
|
|
909
|
+
params[k] = decodeURIComponent(v);
|
|
822
910
|
});
|
|
823
911
|
return { base, params };
|
|
824
912
|
}
|
|
@@ -854,7 +942,8 @@ async function readResource(uri) {
|
|
|
854
942
|
}
|
|
855
943
|
async function getCadInfo2() {
|
|
856
944
|
const cached = getCached("cad:info");
|
|
857
|
-
if (cached)
|
|
945
|
+
if (cached)
|
|
946
|
+
return cached;
|
|
858
947
|
if (!cad.connected) {
|
|
859
948
|
await cad.connect();
|
|
860
949
|
}
|
|
@@ -881,9 +970,12 @@ async function getCadInfo2() {
|
|
|
881
970
|
async function getLayers(filterName = null) {
|
|
882
971
|
const cacheKey = filterName ? `layers:${filterName}` : "layers:all";
|
|
883
972
|
const cached = getCached(cacheKey);
|
|
884
|
-
if (cached)
|
|
885
|
-
|
|
886
|
-
if (!cad.connected)
|
|
973
|
+
if (cached)
|
|
974
|
+
return cached;
|
|
975
|
+
if (!cad.connected)
|
|
976
|
+
await cad.connect();
|
|
977
|
+
if (!cad.connected)
|
|
978
|
+
return [];
|
|
887
979
|
try {
|
|
888
980
|
const code = filterName ? `(tblnext "LAYER" T)` : `(progn (setq res nil)(while (setq e (tblnext "LAYER" (null res)))(setq res (cons (list (cdr (assoc 2 e)) (cdr (assoc 62 e)) (cdr (assoc 70 e))) res))) (reverse res))`;
|
|
889
981
|
const result = await cad.sendCommandWithResult(code);
|
|
@@ -930,8 +1022,10 @@ async function getLayers(filterName = null) {
|
|
|
930
1022
|
async function getEntities(filterType = null) {
|
|
931
1023
|
const cacheKey = filterType ? `entities:${filterType}` : "entities:all";
|
|
932
1024
|
const cached = getCached(cacheKey);
|
|
933
|
-
if (cached)
|
|
934
|
-
|
|
1025
|
+
if (cached)
|
|
1026
|
+
return cached;
|
|
1027
|
+
if (!cad.connected)
|
|
1028
|
+
await cad.connect();
|
|
935
1029
|
if (!cad.connected) {
|
|
936
1030
|
const result = { total: 0, byType: {} };
|
|
937
1031
|
setCache(cacheKey, result);
|
|
@@ -985,8 +1079,10 @@ async function getEntities(filterType = null) {
|
|
|
985
1079
|
}
|
|
986
1080
|
}
|
|
987
1081
|
async function getDwgName() {
|
|
988
|
-
if (!cad.connected)
|
|
989
|
-
|
|
1082
|
+
if (!cad.connected)
|
|
1083
|
+
await cad.connect();
|
|
1084
|
+
if (!cad.connected)
|
|
1085
|
+
return { name: null };
|
|
990
1086
|
try {
|
|
991
1087
|
const code = `(vl-princ-to-string (getvar "dwgname"))`;
|
|
992
1088
|
const name = await cad.sendCommandWithResult(code);
|
|
@@ -996,8 +1092,10 @@ async function getDwgName() {
|
|
|
996
1092
|
}
|
|
997
1093
|
}
|
|
998
1094
|
async function getDwgPath() {
|
|
999
|
-
if (!cad.connected)
|
|
1000
|
-
|
|
1095
|
+
if (!cad.connected)
|
|
1096
|
+
await cad.connect();
|
|
1097
|
+
if (!cad.connected)
|
|
1098
|
+
return { path: null, name: null };
|
|
1001
1099
|
try {
|
|
1002
1100
|
const code = `(progn
|
|
1003
1101
|
(setq prefix (vl-princ-to-string (getvar "dwgprefix")))
|
|
@@ -1015,7 +1113,8 @@ async function getDwgPath() {
|
|
|
1015
1113
|
}
|
|
1016
1114
|
if (!parsed) {
|
|
1017
1115
|
const listResult = parseLispList(result);
|
|
1018
|
-
if (listResult && listResult.length >= 2)
|
|
1116
|
+
if (listResult && listResult.length >= 2)
|
|
1117
|
+
parsed = listResult;
|
|
1019
1118
|
}
|
|
1020
1119
|
if (parsed && Array.isArray(parsed) && parsed.length >= 2) {
|
|
1021
1120
|
return { path: String(parsed[0]), name: String(parsed[1]) };
|
|
@@ -1028,9 +1127,12 @@ async function getDwgPath() {
|
|
|
1028
1127
|
async function getPackages(filterName = null) {
|
|
1029
1128
|
const cacheKey = filterName ? `packages:${filterName}` : "packages:all";
|
|
1030
1129
|
const cached = getCached(cacheKey);
|
|
1031
|
-
if (cached)
|
|
1032
|
-
|
|
1033
|
-
if (!cad.connected)
|
|
1130
|
+
if (cached)
|
|
1131
|
+
return cached;
|
|
1132
|
+
if (!cad.connected)
|
|
1133
|
+
await cad.connect();
|
|
1134
|
+
if (!cad.connected)
|
|
1135
|
+
return [];
|
|
1034
1136
|
try {
|
|
1035
1137
|
const code = `(mapcar 'cdr @::*local-pkgs*)`;
|
|
1036
1138
|
const result = await cad.sendCommandWithResult(code);
|
|
@@ -1044,7 +1146,8 @@ async function getPackages(filterName = null) {
|
|
|
1044
1146
|
} catch {
|
|
1045
1147
|
raw = parseLispList(result) || [];
|
|
1046
1148
|
}
|
|
1047
|
-
if (!Array.isArray(raw))
|
|
1149
|
+
if (!Array.isArray(raw))
|
|
1150
|
+
raw = [];
|
|
1048
1151
|
const packages = raw.map((item) => {
|
|
1049
1152
|
if (Array.isArray(item)) {
|
|
1050
1153
|
const pkg = { name: "", version: "0.0.0", description: "", loaded: true };
|
|
@@ -1053,13 +1156,20 @@ async function getPackages(filterName = null) {
|
|
|
1053
1156
|
const [[key, val]] = Object.entries(entry);
|
|
1054
1157
|
const k = String(key);
|
|
1055
1158
|
const v = String(val);
|
|
1056
|
-
if (k === ":NAME")
|
|
1057
|
-
|
|
1058
|
-
else if (k === ":
|
|
1059
|
-
|
|
1060
|
-
else if (k === ":
|
|
1061
|
-
|
|
1062
|
-
else if (k === ":
|
|
1159
|
+
if (k === ":NAME")
|
|
1160
|
+
pkg.name = v;
|
|
1161
|
+
else if (k === ":VERSION")
|
|
1162
|
+
pkg.version = v;
|
|
1163
|
+
else if (k === ":DESCRIPTION")
|
|
1164
|
+
pkg.description = v;
|
|
1165
|
+
else if (k === ":FULL-NAME")
|
|
1166
|
+
pkg.fullName = v;
|
|
1167
|
+
else if (k === ":AUTHOR")
|
|
1168
|
+
pkg.author = v;
|
|
1169
|
+
else if (k === ":CATEGORY")
|
|
1170
|
+
pkg.category = v;
|
|
1171
|
+
else if (k === ":URL")
|
|
1172
|
+
pkg.url = v;
|
|
1063
1173
|
}
|
|
1064
1174
|
}
|
|
1065
1175
|
return pkg;
|
|
@@ -1368,10 +1478,14 @@ ${generateSuggestions(entities, layers)}`
|
|
|
1368
1478
|
}
|
|
1369
1479
|
function generateSuggestions(entities, layers) {
|
|
1370
1480
|
const suggestions = [];
|
|
1371
|
-
if (entities.total > 1e3)
|
|
1372
|
-
|
|
1373
|
-
if (
|
|
1374
|
-
|
|
1481
|
+
if (entities.total > 1e3)
|
|
1482
|
+
suggestions.push("- \u56FE\u7EB8\u5B9E\u4F53\u8F83\u591A\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u56FE\u5C42\u5206\u7C7B\u7BA1\u7406");
|
|
1483
|
+
if (layers.length > 20)
|
|
1484
|
+
suggestions.push("- \u56FE\u5C42\u8F83\u591A\uFF0C\u5EFA\u8BAE\u6E05\u7406\u672A\u4F7F\u7528\u7684\u56FE\u5C42");
|
|
1485
|
+
if (entities.byType.LINE && entities.byType.LINE > 500)
|
|
1486
|
+
suggestions.push("- \u7EBF\u6761\u8F83\u591A\uFF0C\u53EF\u8003\u8651\u4F7F\u7528 BLOCK \u51CF\u5C11\u5B9E\u4F53\u6570\u91CF");
|
|
1487
|
+
if (!entities.byType.DIMENSION)
|
|
1488
|
+
suggestions.push("- \u672A\u53D1\u73B0\u5C3A\u5BF8\u6807\u6CE8\uFF0C\u5EFA\u8BAE\u6DFB\u52A0\u6807\u6CE8");
|
|
1375
1489
|
return suggestions.length ? suggestions.join("\n") : "- \u56FE\u7EB8\u7ED3\u6784\u826F\u597D";
|
|
1376
1490
|
}
|
|
1377
1491
|
async function generateBatchLinesPrompt(args) {
|
|
@@ -2099,9 +2213,11 @@ var SseSession = class {
|
|
|
2099
2213
|
return lines.join("\n") + "\n\n";
|
|
2100
2214
|
}
|
|
2101
2215
|
_setupDrain() {
|
|
2102
|
-
if (typeof this.#res.on !== "function")
|
|
2216
|
+
if (typeof this.#res.on !== "function")
|
|
2217
|
+
return;
|
|
2103
2218
|
this.#drainHandler = () => {
|
|
2104
|
-
if (!this.#active)
|
|
2219
|
+
if (!this.#active)
|
|
2220
|
+
return;
|
|
2105
2221
|
if (this.#backpressureBuffer.length > 0) {
|
|
2106
2222
|
this._drainBuffer();
|
|
2107
2223
|
}
|
|
@@ -2123,7 +2239,8 @@ var SseSession = class {
|
|
|
2123
2239
|
}
|
|
2124
2240
|
}
|
|
2125
2241
|
_write(content) {
|
|
2126
|
-
if (!this.#active)
|
|
2242
|
+
if (!this.#active)
|
|
2243
|
+
return false;
|
|
2127
2244
|
try {
|
|
2128
2245
|
if (this.#backpressureBuffer.length > 0) {
|
|
2129
2246
|
this.#backpressureBuffer.push(content);
|
|
@@ -2393,7 +2510,8 @@ var SERVER_CAPABILITIES = {
|
|
|
2393
2510
|
prompts: {}
|
|
2394
2511
|
};
|
|
2395
2512
|
var { port, host, transport, apiKey, rateLimitWindow, rateLimitMax } = config_default;
|
|
2396
|
-
if (apiKey)
|
|
2513
|
+
if (apiKey)
|
|
2514
|
+
log("API Key authentication enabled");
|
|
2397
2515
|
var mcpLimiter = rateLimit({
|
|
2398
2516
|
windowMs: rateLimitWindow,
|
|
2399
2517
|
max: rateLimitMax,
|
|
@@ -2441,9 +2559,11 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
2441
2559
|
init_atlisp: () => initAtlisp(),
|
|
2442
2560
|
get_function_usage: (a) => getFunctionUsage(a.name, a.package),
|
|
2443
2561
|
list_symbols: (a) => listSymbols(a.package),
|
|
2562
|
+
get_system_status: () => getSystemStatus(),
|
|
2444
2563
|
import_funlib: async (a) => {
|
|
2445
2564
|
const data = await loadAtlibFunctionLib();
|
|
2446
|
-
if (!data)
|
|
2565
|
+
if (!data)
|
|
2566
|
+
return { content: [{ type: "text", text: "\u52A0\u8F7D\u51FD\u6570\u5E93\u5931\u8D25" }], isError: true };
|
|
2447
2567
|
if (a.format === "list") {
|
|
2448
2568
|
const items = Object.values(data.all_functions || {}).map((f) => `${f.name}: ${f.description || ""}`);
|
|
2449
2569
|
return { content: [{ type: "text", text: items.join("\n") }] };
|
|
@@ -2601,11 +2721,17 @@ var tools = [
|
|
|
2601
2721
|
format: { type: "string", enum: ["json", "list"], description: "\u8FD4\u56DE\u683C\u5F0F\uFF1Ajson\uFF08\u5B8C\u6574JSON\uFF09\u6216 list\uFF08\u51FD\u6570\u540D:\u63CF\u8FF0 \u5217\u8868\uFF09\uFF0C\u9ED8\u8BA4 json" }
|
|
2602
2722
|
}
|
|
2603
2723
|
}
|
|
2724
|
+
},
|
|
2725
|
+
{
|
|
2726
|
+
name: "get_system_status",
|
|
2727
|
+
description: "\u83B7\u53D6\u5B8C\u6574\u7CFB\u7EDF\u8BCA\u65AD\u4FE1\u606F\uFF1AMCP \u72B6\u6001\u3001CAD \u8FDE\u63A5\u3001Lisp \u6267\u884C\u3001\u5305\u5217\u8868",
|
|
2728
|
+
inputSchema: { type: "object", properties: {} }
|
|
2604
2729
|
}
|
|
2605
2730
|
];
|
|
2606
2731
|
async function handleToolCall(name, args) {
|
|
2607
2732
|
const handler = TOOL_HANDLERS[name];
|
|
2608
|
-
if (!handler)
|
|
2733
|
+
if (!handler)
|
|
2734
|
+
return { content: [{ type: "text", text: `\u672A\u77E5\u5DE5\u5177: ${name}` }], isError: true };
|
|
2609
2735
|
try {
|
|
2610
2736
|
const result = await handler(args || {});
|
|
2611
2737
|
notifyResourceChanges(name);
|
|
@@ -2728,7 +2854,8 @@ async function startServer() {
|
|
|
2728
2854
|
const JSON_CONTENT_TYPES = ["application/json", "application/json-rpc", "application/vnd.api+json"];
|
|
2729
2855
|
app.use(async (req, res, next) => {
|
|
2730
2856
|
const ct = (req.headers["content-type"] || "").toLowerCase();
|
|
2731
|
-
if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t)))
|
|
2857
|
+
if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t)))
|
|
2858
|
+
return next();
|
|
2732
2859
|
try {
|
|
2733
2860
|
const buf = await rawBody(req, { limit: "10mb" });
|
|
2734
2861
|
const m = ct.match(/charset\s*=\s*([^\s;]+)/i);
|
|
@@ -2749,9 +2876,11 @@ async function startServer() {
|
|
|
2749
2876
|
const PUBLIC_PATHS = ["/health"];
|
|
2750
2877
|
if (apiKey) {
|
|
2751
2878
|
app.use((req, res, next) => {
|
|
2752
|
-
if (PUBLIC_PATHS.includes(req.path))
|
|
2879
|
+
if (PUBLIC_PATHS.includes(req.path))
|
|
2880
|
+
return next();
|
|
2753
2881
|
const auth = req.get("Authorization");
|
|
2754
|
-
if (auth === `Bearer ${apiKey}`)
|
|
2882
|
+
if (auth === `Bearer ${apiKey}`)
|
|
2883
|
+
return next();
|
|
2755
2884
|
res.status(401).json({ error: "Unauthorized" });
|
|
2756
2885
|
});
|
|
2757
2886
|
}
|
|
@@ -2766,7 +2895,8 @@ async function startServer() {
|
|
|
2766
2895
|
res.setHeader("Access-Control-Expose-Headers", "mcp-session-id, content-type, x-accel-buffering");
|
|
2767
2896
|
res.setHeader("Access-Control-Max-Age", "86400");
|
|
2768
2897
|
res.setHeader("Vary", "Accept");
|
|
2769
|
-
if (req.method === "OPTIONS")
|
|
2898
|
+
if (req.method === "OPTIONS")
|
|
2899
|
+
return res.status(204).end();
|
|
2770
2900
|
next();
|
|
2771
2901
|
});
|
|
2772
2902
|
}
|