@atlisp/mcp 1.0.22 → 1.0.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlisp/mcp",
3
- "version": "1.0.22",
3
+ "version": "1.0.24",
4
4
  "description": "MCP Server for @lisp on CAD",
5
5
  "type": "module",
6
6
  "bin": {
package/src/atlisp-mcp.js CHANGED
@@ -75,11 +75,16 @@ const TOOL_HANDLERS = {
75
75
  search_packages: (a) => packageHandlers.searchPackages(a.query),
76
76
  install_package: (a) => packageHandlers.installPackage(a.packageName),
77
77
  get_platform_info: () => ({ content: [{ type: 'text', text: `支持的 CAD 平台:\n${CAD_PLATFORMS.join('\n')}\n当前连接: ${cad.connected ? '已连接' : '未连接'}` }] }),
78
+ get_file_extensions: (a) => {
79
+ const exts = FILE_EXTENSIONS[a.platform];
80
+ if (!exts) return { content: [{ type: 'text', text: `错误: 不支持的平台 "${a.platform}"` }], isError: true };
81
+ return { content: [{ type: 'text', text: `${a.platform} 文件扩展名: ${exts.join(', ')}` }] };
82
+ },
83
+ get_install_code: () => ({ content: [{ type: 'text', text: `复制以下代码到 CAD 命令行安装 @lisp:\n\n(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))))` }] }),
78
84
  at_command: (a) => cadHandlers.atCommand(a.command),
79
85
  new_document: () => cadHandlers.newDocument(),
80
86
  bring_to_front: () => cadHandlers.bringToFront(),
81
87
  install_atlisp: () => cadHandlers.installAtlisp(),
82
- init_atlisp: () => cadHandlers.initAtlisp(),
83
88
  get_function_usage: (a) => functionHandlers.getFunctionUsage(a.name, a.package),
84
89
  list_functions: (a) => functionHandlers.listFunctions(a.package),
85
90
  };
@@ -144,6 +149,20 @@ export const tools = [
144
149
  description: '获取 CAD 平台信息',
145
150
  inputSchema: { type: 'object', properties: {} }
146
151
  },
152
+ {
153
+ name: 'get_file_extensions',
154
+ description: '获取指定平台的文件扩展名',
155
+ inputSchema: {
156
+ type: 'object',
157
+ properties: { platform: { type: 'string', enum: CAD_PLATFORMS, description: 'CAD 平台' } },
158
+ required: ['platform']
159
+ }
160
+ },
161
+ {
162
+ name: 'get_install_code',
163
+ description: '获取 @lisp 安装代码',
164
+ inputSchema: { type: 'object', properties: {} }
165
+ },
147
166
  {
148
167
  name: 'at_command',
149
168
  description: '执行 @lisp 命令',
@@ -168,11 +187,6 @@ export const tools = [
168
187
  description: '在 CAD 中安装 @lisp',
169
188
  inputSchema: { type: 'object', properties: {} }
170
189
  },
171
- {
172
- name: 'init_atlisp',
173
- description: '初始化 CAD 中的 @lisp 环境,加载函数库和初始变量',
174
- inputSchema: { type: 'object', properties: {} }
175
- },
176
190
  {
177
191
  name: 'get_function_usage',
178
192
  description: '获取 @lisp 函数用法(从本地 JSON 库)',
@@ -233,7 +247,7 @@ async function initCadConnection() {
233
247
  const connected = await cad.connect();
234
248
  if (connected) {
235
249
  log('Auto-connected to CAD: ' + cad.getPlatform() + ' ' + cad.getVersion());
236
- console.error('已自动连接到 CAD: ' + cad.getPlatform() + ' ' + cad.getVersion());
250
+ console.log('已自动连接到 CAD: ' + cad.getPlatform() + ' ' + cad.getVersion());
237
251
  } else {
238
252
  log('No CAD found on startup');
239
253
  }
@@ -368,12 +382,12 @@ async function handleMcpRequest(session, method, params, id) {
368
382
  }
369
383
 
370
384
  export async function startServer() {
371
- if (transport === 'stdio') {
385
+ if (config.transport === 'stdio') {
372
386
  await initCadConnection();
373
387
  const mcpServer = createMcpServer();
374
- const transport = new StdioServerTransport();
375
- await mcpServer.connect(transport);
376
- console.error(`${SERVER_NAME} 运行在 stdio 模式`);
388
+ const stdioTransport = new StdioServerTransport();
389
+ await mcpServer.connect(stdioTransport);
390
+ console.log(`${SERVER_NAME} 运行在 stdio 模式`);
377
391
  } else {
378
392
  const app = express();
379
393
 
package/src/cad-worker.js CHANGED
@@ -137,7 +137,7 @@ const cadSendWithResult = edge.func(function() {/*
137
137
 
138
138
  // 生成 LISP 代码:执行 code,将结果打印到 tempFile
139
139
  // 使用 princ 输出原始字符串
140
- string lispCode = "(progn(setq f(open \"" + tempFile.Replace("\\", "\\\\") + "\" \"w\"))(princ " + code + " f)(close f)(princ))";
140
+ string lispCode = "(progn(setq f(open \"" + tempFile.Replace("\\", "\\\\") + "\" \"w\"))(princ (progn " + code + ") f)(close f)(princ))";
141
141
 
142
142
  // 使用系统 ANSI 编码以兼容 GstarCAD / ZWCAD
143
143
  System.IO.File.WriteAllText(lispFile, lispCode, System.Text.Encoding.GetEncoding(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ANSICodePage));
@@ -337,22 +337,22 @@ async function waitForIdle(platform) {
337
337
  function checkParens(code) {
338
338
  let depth = 0;
339
339
  let inString = false;
340
- let escapeNext = false;
341
340
  for (let i = 0; i < code.length; i++) {
342
341
  const ch = code[i];
343
- if (escapeNext) {
344
- escapeNext = false;
345
- continue;
346
- }
347
- if (ch === '\\') {
348
- escapeNext = true;
342
+ if (inString) {
343
+ if (ch === '\\' && i + 1 < code.length) {
344
+ i++;
345
+ continue;
346
+ }
347
+ if (ch === '"') {
348
+ inString = false;
349
+ }
349
350
  continue;
350
351
  }
351
352
  if (ch === '"') {
352
- inString = !inString;
353
+ inString = true;
353
354
  continue;
354
355
  }
355
- if (inString) continue;
356
356
  if (ch === ';') {
357
357
  while (i < code.length && code[i] !== '\n') i++;
358
358
  continue;
@@ -427,7 +427,7 @@ async function handleMessage(msg) {
427
427
  if (!parenCheck.valid) {
428
428
  return { success: false, error: `括号错误: ${parenCheck.error} (位置 ${parenCheck.pos})` };
429
429
  }
430
- if (!(await waitForIdle(msg.platform))) {
430
+ if (!(await waitForIdle(msg.platform || 'AutoCAD'))) {
431
431
  return { success: false, error: 'CAD is busy, timeout' };
432
432
  }
433
433
  log(`send: ${msg.code}`);
package/src/constants.js CHANGED
@@ -8,7 +8,7 @@ export const FILE_EXTENSIONS = {
8
8
 
9
9
  export const PROTOCOL_VERSION = '2024-11-05';
10
10
  export const SERVER_NAME = 'atlisp-mcp-server';
11
- export const SERVER_VERSION = '1.0.22';
11
+ export const SERVER_VERSION = '1.0.24';
12
12
 
13
13
  export const MOCK_PACKAGES = [
14
14
  { name: 'base', description: '基础函数库', version: '1.0.0' },
@@ -77,22 +77,3 @@ export async function installAtlisp() {
77
77
  await cad.sendCommand(installCode + '\n');
78
78
  return { content: [{ type: 'text', text: '已发送 @lisp 安装代码到 CAD' }] };
79
79
  }
80
-
81
- export async function initAtlisp() {
82
- if (!cad.connected) { await cad.connect(); }
83
- if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
84
- const code = `(if (null @::load-module)
85
- (progn
86
- (vl-load-com)
87
- (setq s strcat h"http"o(vlax-create-object (s"win"h".win"h"request.5.1"))
88
- v vlax-invoke e eval r read)(v o'open "get" (s h"://""atlisp.""cn/cloud"):vlax-true)
89
- (v o'send)
90
- (v o'WaitforResponse 1000)
91
- (e(r(vlax-get o'ResponseText)))))`;
92
- try {
93
- await cad.sendCommand(code + '\n');
94
- return { content: [{ type: 'text', text: '已发送 @lisp 函数库加载代码到 CAD' }] };
95
- } catch (e) {
96
- return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
97
- }
98
- }
@@ -312,16 +312,29 @@ async function getDwgPath() {
312
312
  if (!cad.connected) return { path: null, name: null };
313
313
 
314
314
  try {
315
- const code = `(strcat (vl-princ-to-string (getvar "dwgprefix")) (vl-princ-to-string (getvar "dwgname")))`;
316
- const fullPath = await cad.sendCommandWithResult(code);
315
+ const code = `(progn
316
+ (setq prefix (vl-princ-to-string (getvar "dwgprefix")))
317
+ (setq name (vl-princ-to-string (getvar "dwgname")))
318
+ (list (strcat prefix name) name)
319
+ )`;
320
+ const result = await cad.sendCommandWithResult(code);
317
321
 
318
- const nameCode = `(vl-princ-to-string (getvar "dwgname"))`;
319
- const name = await cad.sendCommandWithResult(nameCode);
322
+ if (!result || result === "nil" || result === "") {
323
+ return { path: null, name: null };
324
+ }
325
+
326
+ let parsed = null;
327
+ try { parsed = JSON.parse(result); } catch {}
328
+ if (!parsed) {
329
+ const listResult = parseLispList(result);
330
+ if (listResult && listResult.length >= 2) parsed = listResult;
331
+ }
332
+
333
+ if (parsed && Array.isArray(parsed) && parsed.length >= 2) {
334
+ return { path: String(parsed[0]), name: String(parsed[1]) };
335
+ }
320
336
 
321
- return {
322
- path: fullPath || null,
323
- name: name || null
324
- };
337
+ return { path: result, name: result };
325
338
  } catch (e) {
326
339
  return { path: null, name: null };
327
340
  }
@@ -197,7 +197,7 @@ export class SseSession {
197
197
  }
198
198
 
199
199
  sendEndpoint(path) {
200
- return this._write(`: endpoint ${path}\n\n`);
200
+ return this.sendEvent(SSE_EVENTS.ENDPOINT, path);
201
201
  }
202
202
 
203
203
  sendError(code, message, id = null) {
@@ -205,7 +205,7 @@ export class SseSession {
205
205
  }
206
206
 
207
207
  sendPing() {
208
- return this._write(': ping ' + Date.now() + '\n\n');
208
+ return this.sendEvent(SSE_EVENTS.PING, { timestamp: Date.now() });
209
209
  }
210
210
 
211
211
  sendProgress(current, total, message = '') {
@@ -213,7 +213,7 @@ export class SseSession {
213
213
  }
214
214
 
215
215
  sendCapabilities(capabilities) {
216
- return this._write(`: capabilities ${JSON.stringify(capabilities)}\n\n`);
216
+ return this.sendEvent(SSE_EVENTS.CAPABILITIES, capabilities);
217
217
  }
218
218
 
219
219
  sendResponse(jsonrpcResponse, id = null) {