@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.
Files changed (2) hide show
  1. package/dist/atlisp-mcp.js +210 -80
  2. package/package.json +1 -1
@@ -34,7 +34,8 @@ var SessionTransport = class {
34
34
  this._started = true;
35
35
  }
36
36
  async send(message) {
37
- if (this._closed) return;
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) return;
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.1.2";
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()) continue;
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) worker.kill();
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) return;
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) clearInterval(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()) return false;
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) throw new Error("\u672A\u8FDE\u63A5 CAD");
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) return true;
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) throw new Error("\u672A\u8FDE\u63A5 CAD");
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) return false;
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) return { hasDoc: false, docCount: 0 };
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) throw new Error("\u672A\u8FDE\u63A5 CAD");
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) throw new Error("\u672A\u8FDE\u63A5 CAD");
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) return "CAD \u672A\u8FDE\u63A5";
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) return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
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) return { content: [{ type: "text", text: "CAD \u672A\u8FDE\u63A5" }] };
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) return { content: [{ type: "text", text: "\u8BF7\u5148\u8FDE\u63A5 CAD" }], isError: true };
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) return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
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) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
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) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
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) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
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) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
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) return { content: [{ type: "text", text: 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) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
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) await cad.connect();
578
- if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
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") return { content: [{ type: "text", text: result }] };
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)) results.push(p);
670
+ if (name.includes(q) || desc.includes(q))
671
+ results.push(p);
598
672
  }
599
673
  } else {
600
- for (const p of items) results.push(p);
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) results.push(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) results.push(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") return null;
822
+ if (!str || typeof str !== "string")
823
+ return null;
746
824
  const trimmed = str.trim();
747
- if (!trimmed.startsWith("(") || !trimmed.endsWith(")")) return null;
825
+ if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
826
+ return null;
748
827
  const content = trimmed.slice(1, -1).trim();
749
- if (!content) return [];
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()) result.push(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") return null;
795
- if (t === "t") return true;
796
- if (t === "T") return true;
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 !== "") return num;
799
- if (t.startsWith('"') && t.endsWith('"')) return t.slice(1, -1);
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) return { base: uri, params: {} };
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) params[k] = decodeURIComponent(v);
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) return 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) return cached;
885
- if (!cad.connected) await cad.connect();
886
- if (!cad.connected) return [];
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) return cached;
934
- if (!cad.connected) await cad.connect();
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) await cad.connect();
989
- if (!cad.connected) return { name: null };
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) await cad.connect();
1000
- if (!cad.connected) return { path: null, name: null };
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) parsed = listResult;
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) return cached;
1032
- if (!cad.connected) await cad.connect();
1033
- if (!cad.connected) return [];
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)) 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") pkg.name = v;
1057
- else if (k === ":VERSION") pkg.version = v;
1058
- else if (k === ":DESCRIPTION") pkg.description = v;
1059
- else if (k === ":FULL-NAME") pkg.fullName = v;
1060
- else if (k === ":AUTHOR") pkg.author = v;
1061
- else if (k === ":CATEGORY") pkg.category = v;
1062
- else if (k === ":URL") pkg.url = v;
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) suggestions.push("- \u56FE\u7EB8\u5B9E\u4F53\u8F83\u591A\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u56FE\u5C42\u5206\u7C7B\u7BA1\u7406");
1372
- if (layers.length > 20) suggestions.push("- \u56FE\u5C42\u8F83\u591A\uFF0C\u5EFA\u8BAE\u6E05\u7406\u672A\u4F7F\u7528\u7684\u56FE\u5C42");
1373
- if (entities.byType.LINE && entities.byType.LINE > 500) suggestions.push("- \u7EBF\u6761\u8F83\u591A\uFF0C\u53EF\u8003\u8651\u4F7F\u7528 BLOCK \u51CF\u5C11\u5B9E\u4F53\u6570\u91CF");
1374
- if (!entities.byType.DIMENSION) suggestions.push("- \u672A\u53D1\u73B0\u5C3A\u5BF8\u6807\u6CE8\uFF0C\u5EFA\u8BAE\u6DFB\u52A0\u6807\u6CE8");
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") return;
2216
+ if (typeof this.#res.on !== "function")
2217
+ return;
2103
2218
  this.#drainHandler = () => {
2104
- if (!this.#active) return;
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) return false;
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) log("API Key authentication enabled");
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) return { content: [{ type: "text", text: "\u52A0\u8F7D\u51FD\u6570\u5E93\u5931\u8D25" }], isError: true };
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) return { content: [{ type: "text", text: `\u672A\u77E5\u5DE5\u5177: ${name}` }], isError: true };
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))) return next();
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)) return next();
2879
+ if (PUBLIC_PATHS.includes(req.path))
2880
+ return next();
2753
2881
  const auth = req.get("Authorization");
2754
- if (auth === `Bearer ${apiKey}`) return next();
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") return res.status(204).end();
2898
+ if (req.method === "OPTIONS")
2899
+ return res.status(204).end();
2770
2900
  next();
2771
2901
  });
2772
2902
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlisp/mcp",
3
- "version": "1.3.8",
3
+ "version": "1.4.0",
4
4
  "description": "MCP Server for @lisp on CAD",
5
5
  "type": "module",
6
6
  "bin": {