@atlisp/mcp 1.4.3 → 1.5.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 +67 -95
  2. package/package.json +1 -1
@@ -119,7 +119,7 @@ var FILE_EXTENSIONS = {
119
119
  "BricsCAD": [".des"]
120
120
  };
121
121
  var SERVER_NAME = "atlisp-mcp-server";
122
- var SERVER_VERSION = "1.4.1";
122
+ var SERVER_VERSION = "1.5.0";
123
123
  var MOCK_PACKAGES = [
124
124
  { name: "base", description: "\u57FA\u7840\u51FD\u6570\u5E93", version: "1.0.0" },
125
125
  { name: "at-pm", description: "\u5DE5\u7A0B\u9879\u76EE\u7BA1\u7406", version: "2.1.0" },
@@ -1036,33 +1036,33 @@ function lispPairsToObject(pairs) {
1036
1036
  }
1037
1037
  return obj;
1038
1038
  }
1039
- var ENTITY_SCHEMAS = {
1040
- LINE: { fields: ["x1", "y1", "z1", "x2", "y2", "z2", "length"], strings: [] },
1041
- CIRCLE: { fields: ["cx", "cy", "cz", "radius"], strings: [] },
1042
- ARC: { fields: ["cx", "cy", "cz", "radius", "startAngle", "endAngle"], strings: [] },
1043
- LWPOLYLINE: { fields: ["vertices", "closed"], strings: [] },
1044
- TEXT: { fields: ["x", "y", "z", "text", "height", "rotation"], strings: ["text"] },
1045
- MTEXT: { fields: ["x", "y", "z", "text", "height", "rotation"], strings: ["text"] },
1046
- ATTRIB: { fields: ["x", "y", "z", "text", "height", "rotation"], strings: ["text"] },
1047
- TCH_TEXT: { fields: ["x", "y", "z", "text", "height", "rotation"], strings: ["text"] },
1048
- INSERT: { fields: ["x", "y", "z", "blockName", "rotation", "scaleX", "scaleY"], strings: ["blockName"] },
1049
- POINT: { fields: ["x", "y", "z"], strings: [] }
1050
- };
1051
1039
  function parseEntity(arr) {
1052
1040
  if (!Array.isArray(arr) || arr.length < 5) return null;
1053
1041
  const [type, handle, layer, color, linetype, ...rest] = arr;
1054
- const schema = ENTITY_SCHEMAS[String(type)] || { fields: [], strings: [] };
1055
- const props = {};
1056
- schema.fields.forEach((name, i) => {
1057
- if (i < rest.length) {
1058
- let val = rest[i];
1059
- if (schema.strings.includes(name) && val !== null && val !== void 0) val = String(val);
1060
- props[name] = val;
1061
- }
1062
- });
1063
- return { type: String(type), handle: String(handle), layer: String(layer), color, linetype: String(linetype), ...props };
1042
+ const entity = {
1043
+ type: String(type).toUpperCase().replace(/^"|"$/g, ""),
1044
+ handle: String(handle),
1045
+ layer: String(layer),
1046
+ color,
1047
+ linetype: String(linetype)
1048
+ };
1049
+ const entType = typeof entity.type === "string" ? entity.type.toUpperCase() : entity.type;
1050
+ if (/^(TEXT|MTEXT|ATTRIB|TCH_TEXT)$/.test(entType) && rest[0] != null) {
1051
+ entity.text = String(rest[0]);
1052
+ }
1053
+ if (/^(LINE|LWPOLYLINE|POLYLINE|ARC|CIRCLE|SPLINE|ELLIPSE|XLINE|RAY)$/.test(entType) && Array.isArray(rest[0])) {
1054
+ entity.points = rest[0].map((pt) => {
1055
+ if (Array.isArray(pt) && pt.length >= 2)
1056
+ return { x: Number(pt[0]), y: Number(pt[1]), z: Number(pt[2] || 0) };
1057
+ return null;
1058
+ }).filter(Boolean);
1059
+ }
1060
+ if (entType === "INSERT" && rest[0] != null) {
1061
+ entity.blockName = String(rest[0]);
1062
+ }
1063
+ return entity;
1064
1064
  }
1065
- function buildEntityCode({ type, layer, bbox, offset, limit }) {
1065
+ function buildEntityCode({ type, layer, bbox }) {
1066
1066
  const items = [];
1067
1067
  if (type) items.push(`(cons 0 "${type.replace(/"/g, '\\"')}")`);
1068
1068
  if (layer) items.push(`(cons 8 "${layer.replace(/"/g, '\\"')}")`);
@@ -1081,51 +1081,29 @@ function buildEntityCode({ type, layer, bbox, offset, limit }) {
1081
1081
  const filterExpr = items.length ? `(list ${items.join(" ")})` : "nil";
1082
1082
  const ssgetExpr = items.length ? `(ssget "_X" ${filterExpr})` : '(ssget "_X")';
1083
1083
  return `(progn
1084
- (defun @e:props (ent / ed typ result item s e c verts closed ins)
1085
- (setq ed (entget ent) typ (cdr (assoc 0 ed)))
1086
- (setq result (list (vl-prin1-to-string (cdr (assoc 5 ed))) (vl-prin1-to-string (cdr (assoc 8 ed)))
1087
- (if (setq item (assoc 62 ed)) (cdr item) "ByLayer")
1088
- (vl-prin1-to-string (if (setq item (assoc 6 ed)) (cdr item) "ByLayer"))))
1089
- (cond
1090
- ((= typ "LINE")
1091
- (setq s (cdr (assoc 10 ed)) e (cdr (assoc 11 ed)))
1092
- (append result (list (car s) (cadr s) (caddr s) (car e) (cadr e) (caddr e) (distance s e))))
1093
- ((= typ "CIRCLE")
1094
- (setq c (cdr (assoc 10 ed)))
1095
- (append result (list (car c) (cadr c) (caddr c) (cdr (assoc 40 ed)))))
1096
- ((= typ "ARC")
1097
- (setq c (cdr (assoc 10 ed)))
1098
- (append result (list (car c) (cadr c) (caddr c) (cdr (assoc 40 ed)) (cdr (assoc 50 ed)) (cdr (assoc 51 ed)))))
1099
- ((= typ "LWPOLYLINE")
1100
- (setq verts nil closed nil)
1101
- (foreach g ed
1102
- (if (= (car g) 10) (setq verts (append verts (list (list (cadr g) (caddr g))))))
1103
- (if (= (car g) 70) (setq closed (= (logand (cdr g) 1) 1))))
1104
- (append result (list verts (if closed "T" nil))))
1105
- ((= typ "TEXT")
1106
- (setq ins (cdr (assoc 10 ed)))
1107
- (append result (list (car ins) (cadr ins) (caddr ins) (vl-prin1-to-string (cdr (assoc 1 ed))) (cdr (assoc 40 ed)) (cdr (assoc 50 ed))))))
1108
- ((= typ "MTEXT")
1109
- (setq ins (cdr (assoc 10 ed)))
1110
- (append result (list (car ins) (cadr ins) (caddr ins) (vl-prin1-to-string (cdr (assoc 1 ed))) (cdr (assoc 40 ed)) (cdr (assoc 50 ed))))))
1111
- ((= typ "INSERT")
1112
- (setq ins (cdr (assoc 10 ed)))
1113
- (append result (list (car ins) (cadr ins) (caddr ins) (vl-prin1-to-string (cdr (assoc 2 ed))) (cdr (assoc 50 ed)) (cdr (assoc 41 ed)) (cdr (assoc 42 ed))))))
1114
- ((= typ "POINT")
1115
- (setq p (cdr (assoc 10 ed)))
1116
- (append result (list (car p) (cadr p) (caddr p))))
1117
- (t result)))
1118
- (defun @e:run nil
1119
- (setq ss ${ssgetExpr})
1120
- (if (null ss)
1121
- (list "total" 0 "offset" ${offset} "limit" ${limit})
1122
- (progn
1123
- (setq total (sslength ss) entities nil i ${offset})
1124
- (while (and (< i total) (< (length entities) ${limit}))
1125
- (setq entities (append entities (list (@e:props (ssname ss i)))) i (1+ i)))
1126
- (list "total" total "offset" ${offset} "limit" ${limit} "entities" entities))))
1127
- (@e:run))
1128
- `;
1084
+ (vl-load-com)
1085
+ (defun @e:safe-fn (f ent / r)
1086
+ (setq r (vl-catch-all-apply f (list ent)))
1087
+ (if (vl-catch-all-error-p r) nil r))
1088
+ (defun @e:dp (ent / ed typ gcl is)
1089
+ (setq ed (entget ent) typ (cdr (assoc 0 ed)) gcl (assoc 62 ed) is (assoc 6 ed))
1090
+ (append
1091
+ (list typ (cdr (assoc 5 ed)) (cdr (assoc 8 ed))
1092
+ (if gcl (cdr gcl) 256)
1093
+ (if is (cdr is) "ByLayer"))
1094
+ (cond
1095
+ ((wcmatch typ "TEXT,MTEXT,ATTRIB,TCH_TEXT")
1096
+ (list (@e:safe-fn '(lambda (e) (text:remove-fmt (text:get-mtext e))) ent)))
1097
+ ((wcmatch typ "LINE,LWPOLYLINE,POLYLINE,ARC,CIRCLE,SPLINE,ELLIPSE,XLINE,RAY")
1098
+ (list (@e:safe-fn 'curve:get-points ent)))
1099
+ ((= typ "INSERT")
1100
+ (list (@e:safe-fn 'block:get-effectivename ent)))
1101
+ (t nil))))
1102
+ (setq @e:total (if (setq @e:ss ${ssgetExpr}) (sslength @e:ss) 0)
1103
+ @e:ents nil @e:i 0)
1104
+ (while (and @e:ss (< @e:i @e:total)(< (length @e:ents) 3000))
1105
+ (setq @e:ents (cons (@e:dp (ssname @e:ss @e:i)) @e:ents) @e:i (1+ @e:i)))
1106
+ (vl-prin1-to-string (list @e:total (reverse @e:ents))))`;
1129
1107
  }
1130
1108
  function buildTextCode({ layer, bbox, offset, limit }) {
1131
1109
  const items = [`'(0 . "TEXT,MTEXT,ATTRIB,TCH_TEXT")`];
@@ -1168,8 +1146,8 @@ function buildTextCode({ layer, bbox, offset, limit }) {
1168
1146
  var RESOURCES = [
1169
1147
  { uri: "atlisp://cad/info", name: "CAD Info", description: "CAD \u8FDE\u63A5\u4FE1\u606F", mimeType: "application/json", subscribable: true },
1170
1148
  { uri: "atlisp://dwg/layers", name: "Layers", description: "\u56FE\u5C42\u5217\u8868", mimeType: "application/json", subscribable: true },
1171
- { uri: "atlisp://dwg/entities", name: "Entities", description: "\u5B9E\u4F53\u5C5E\u6027\u5217\u8868\uFF0C\u652F\u6301 ?type=LINE&layer=0&bbox=0,0,100,100&limit=100&offset=0", mimeType: "application/json", subscribable: true },
1172
- { uri: "atlisp://dwg/texts", name: "Texts", description: "\u6587\u672C\u5B9E\u4F53\u5185\u5BB9\u5217\u8868 (TEXT/MTEXT/ATTRIB/TCH_TEXT)\uFF0C\u652F\u6301 ?layer=0&bbox=0,0,100,100&limit=500&offset=0", mimeType: "application/json", subscribable: true },
1149
+ { uri: "atlisp://dwg/entities", name: "Entities", description: "\u56FE\u5143\u5217\u8868\uFF0C\u8FD4\u56DE\u603B\u6570\u548C\u524D3000\u4E2A\u56FE\u5143\uFF0C\u6587\u672C\u9644\u52A0 text \u5B57\u6BB5\uFF0C\u66F2\u7EBF\u9644\u52A0 points \u6570\u7EC4\uFF0CINSERT \u9644\u52A0 blockName\uFF0C\u652F\u6301 ?type=LINE&layer=0&bbox=0,0,100,100 \u8FC7\u6EE4", mimeType: "application/json", subscribable: true },
1150
+ { uri: "atlisp://dwg/texts", name: "Texts", description: "\u6587\u672C\u5B9E\u4F53\u5185\u5BB9\u5217\u8868 (TEXT/MTEXT/ATTRIB/TCH_TEXT)\uFF0C\u652F\u6301 ?layer=0&bbox=0,0,100,100&limit=5000&offset=0", mimeType: "application/json", subscribable: true },
1173
1151
  { uri: "atlisp://dwg/name", name: "DWG Name", description: "\u5F53\u524D DWG \u6587\u4EF6\u540D", mimeType: "application/json", subscribable: true },
1174
1152
  { uri: "atlisp://dwg/path", name: "DWG Path", description: "\u6587\u4EF6\u5B8C\u6574\u8DEF\u5F84", mimeType: "application/json", subscribable: true },
1175
1153
  { uri: "atlisp://cad/dwgs", name: "DWG List", description: "\u6240\u6709\u6253\u5F00\u7684 DWG \u6587\u4EF6\u5217\u8868", mimeType: "application/json", subscribable: true },
@@ -1262,7 +1240,7 @@ async function getLayers(filterName = null) {
1262
1240
  if (!cad.connected) await cad.connect();
1263
1241
  if (!cad.connected) return [];
1264
1242
  try {
1265
- 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))`;
1243
+ const code = filterName ? `(vl-prin1-to-string (cdr (assoc 2 (tblnext "LAYER" T))))` : `(progn (setq res nil)(while (setq e (tblnext "LAYER" (null res)))(setq res (cons (list (vl-prin1-to-string (cdr (assoc 2 e))) (cdr (assoc 62 e)) (cdr (assoc 70 e))) res))) (reverse res))`;
1266
1244
  const result = await cad.sendCommandWithResult(code);
1267
1245
  if (!result || result === "" || result === "nil") {
1268
1246
  setCache(cacheKey, []);
@@ -1314,39 +1292,33 @@ async function getEntities(params = {}) {
1314
1292
  setCache(cacheKey, result);
1315
1293
  return result;
1316
1294
  }
1317
- const offset = Math.max(0, parseInt(params.offset) || 0);
1318
- const limit = Math.min(Math.max(1, parseInt(params.limit) || 100), 1e3);
1319
1295
  try {
1320
1296
  const code = buildEntityCode({
1321
1297
  type: params.type || null,
1322
1298
  layer: params.layer || null,
1323
- bbox: params.bbox || null,
1324
- offset,
1325
- limit
1299
+ bbox: params.bbox || null
1326
1300
  });
1327
1301
  const resultStr = await cad.sendCommandWithResult(code);
1328
- if (!resultStr || resultStr === "" || resultStr === "nil" || resultStr === "0") {
1329
- const result = { total: 0, offset, limit, entities: [] };
1330
- setCache(cacheKey, result);
1331
- return result;
1302
+ if (!resultStr || resultStr === "" || resultStr === "nil") {
1303
+ const result2 = { total: 0, entities: [] };
1304
+ setCache(cacheKey, result2);
1305
+ return result2;
1332
1306
  }
1307
+ let total = 0;
1308
+ let entities = [];
1333
1309
  const parsed = parseLispRecursive(resultStr);
1334
- if (!parsed || !Array.isArray(parsed)) {
1335
- const result = { total: 0, offset, limit, entities: [] };
1336
- setCache(cacheKey, result);
1337
- return result;
1310
+ if (parsed && Array.isArray(parsed) && parsed.length >= 2) {
1311
+ total = typeof parsed[0] === "number" ? parsed[0] : 0;
1312
+ const rawEntities = Array.isArray(parsed[1]) ? parsed[1] : [];
1313
+ entities = rawEntities.map(parseEntity).filter(Boolean);
1338
1314
  }
1339
- const entitiesIdx = parsed.indexOf("entities");
1340
- const rawEntities = entitiesIdx !== -1 && Array.isArray(parsed[entitiesIdx + 1]) ? parsed[entitiesIdx + 1] : [];
1341
- const data = lispPairsToObject(parsed);
1342
- data.entities = rawEntities.length > 0 ? rawEntities.map(parseEntity).filter(Boolean) : [];
1343
- data.offset = offset;
1344
- data.limit = limit;
1345
- setCache(cacheKey, data);
1346
- return data;
1315
+ const result = { total, entities };
1316
+ log(`getEntities: total=${total}, returned=${entities.length}`);
1317
+ setCache(cacheKey, result);
1318
+ return result;
1347
1319
  } catch (e) {
1348
1320
  log(`getEntities error: ${e.message}`);
1349
- const result = { total: 0, offset, limit, entities: [] };
1321
+ const result = { total: 0, entities: [] };
1350
1322
  setCache(cacheKey, result);
1351
1323
  return result;
1352
1324
  }
@@ -1362,7 +1334,7 @@ async function getTexts(params = {}) {
1362
1334
  return result;
1363
1335
  }
1364
1336
  const offset = Math.max(0, parseInt(params.offset) || 0);
1365
- const limit = Math.min(Math.max(1, parseInt(params.limit) || 500), 5e3);
1337
+ const limit = Math.min(Math.max(1, parseInt(params.limit) || 5e3), 5e3);
1366
1338
  try {
1367
1339
  const code = buildTextCode({
1368
1340
  layer: params.layer || null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlisp/mcp",
3
- "version": "1.4.3",
3
+ "version": "1.5.0",
4
4
  "description": "MCP Server for @lisp on CAD",
5
5
  "type": "module",
6
6
  "bin": {