@atlisp/mcp 1.3.0 → 1.3.1

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.
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cad-worker.js
4
+ import edge from "edge-js";
5
+ import process from "process";
6
+ import fs from "fs";
7
+ import path from "path";
8
+ var BUSY_RETRIES = parseInt(process.env.BUSY_RETRIES || "10", 10);
9
+ var BUSY_DELAY = parseInt(process.env.BUSY_DELAY || "500", 10);
10
+ var DEBUG_FILE = process.env.DEBUG_FILE || path.join(process.env.TEMP || "/tmp", "cad-worker-debug.log");
11
+ function log(msg) {
12
+ const entry = `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
13
+ `;
14
+ if (process.env.DEBUG) {
15
+ fs.appendFile(DEBUG_FILE, entry, () => {
16
+ });
17
+ }
18
+ }
19
+ var cadConnect = edge.func(function() {
20
+ });
21
+ var cadLaunch = edge.func(function() {
22
+ });
23
+ var cadSend = edge.func(function() {
24
+ });
25
+ var cadSendWithResult = edge.func(function() {
26
+ });
27
+ process.stdin.setEncoding("utf8");
28
+ var stdinBuffer = "";
29
+ process.stdin.on("data", (data) => {
30
+ stdinBuffer += data;
31
+ const lines = stdinBuffer.split("\n");
32
+ stdinBuffer = lines.pop() || "";
33
+ for (const line of lines) {
34
+ if (!line.trim()) continue;
35
+ try {
36
+ const msg = JSON.parse(line);
37
+ const requestId = msg.requestId;
38
+ handleMessage(msg).then((result) => {
39
+ process.stdout.write(JSON.stringify({ ...result, requestId }) + "\n");
40
+ }).catch((err) => {
41
+ process.stdout.write(JSON.stringify({ error: err.message, requestId }) + "\n");
42
+ });
43
+ } catch (e) {
44
+ process.stdout.write(JSON.stringify({ error: "invalid message" }) + "\n");
45
+ }
46
+ }
47
+ });
48
+ var cadIsBusy = edge.func(function() {
49
+ });
50
+ var cadHasDoc = edge.func(function() {
51
+ });
52
+ var cadNewDoc = edge.func(function() {
53
+ });
54
+ var cadBringToFront = edge.func(function() {
55
+ });
56
+ async function waitForIdle(platform) {
57
+ let retries = BUSY_RETRIES;
58
+ while (retries > 0) {
59
+ const checkResult = await new Promise((resolve, reject) => {
60
+ cadIsBusy(platform || "AutoCAD", (e, r) => {
61
+ if (e) reject(e);
62
+ else resolve(r);
63
+ });
64
+ });
65
+ if (!checkResult.isBusy) return true;
66
+ retries--;
67
+ if (retries > 0) await new Promise((resolve) => setTimeout(resolve, BUSY_DELAY));
68
+ }
69
+ return false;
70
+ }
71
+ function checkParens(code) {
72
+ let depth = 0;
73
+ let inString = false;
74
+ for (let i = 0; i < code.length; i++) {
75
+ const ch = code[i];
76
+ if (inString) {
77
+ if (ch === "\\" && i + 1 < code.length) {
78
+ i++;
79
+ continue;
80
+ }
81
+ if (ch === '"') {
82
+ inString = false;
83
+ }
84
+ continue;
85
+ }
86
+ if (ch === '"') {
87
+ inString = true;
88
+ continue;
89
+ }
90
+ if (ch === ";") {
91
+ while (i < code.length && code[i] !== "\n") i++;
92
+ continue;
93
+ }
94
+ if (ch === "(") depth++;
95
+ if (ch === ")") depth--;
96
+ if (depth < 0) return { valid: false, error: "\u591A\u4F59\u53F3\u62EC\u53F7 )", pos: i };
97
+ }
98
+ if (depth > 0) return { valid: false, error: `\u7F3A\u5C11 ${depth} \u4E2A\u53F3\u62EC\u53F7 )`, pos: code.length - 1 };
99
+ if (depth < 0) return { valid: false, error: `\u591A\u4F59 ${-depth} \u4E2A\u5DE6\u62EC\u53F7 (` };
100
+ return { valid: true };
101
+ }
102
+ async function handleMessage(msg) {
103
+ if (msg.type === "ping") {
104
+ return { pong: true };
105
+ }
106
+ if (msg.type === "connect") {
107
+ try {
108
+ const result = await new Promise((resolve, reject) => {
109
+ cadConnect({}, (e, r) => {
110
+ if (e) reject(e);
111
+ else resolve(r);
112
+ });
113
+ });
114
+ if (result && result.success) return result;
115
+ } catch (e) {
116
+ log("cadConnect failed: " + e.message);
117
+ }
118
+ return new Promise((resolve, reject) => {
119
+ cadLaunch({}, (e, r) => {
120
+ if (e) reject(e);
121
+ else resolve(r);
122
+ });
123
+ });
124
+ }
125
+ if (msg.type === "hasdoc") {
126
+ return new Promise((resolve, reject) => {
127
+ cadHasDoc(msg.platform || "AutoCAD", (e, r) => {
128
+ if (e) reject(e);
129
+ else resolve(r);
130
+ });
131
+ });
132
+ }
133
+ if (msg.type === "newdoc") {
134
+ return new Promise((resolve, reject) => {
135
+ cadNewDoc(msg.platform || "AutoCAD", (e, r) => {
136
+ if (e) reject(e);
137
+ else resolve(r);
138
+ });
139
+ });
140
+ }
141
+ if (msg.type === "bringToFront") {
142
+ return new Promise((resolve, reject) => {
143
+ cadBringToFront(msg.platform || "AutoCAD", (e, r) => {
144
+ if (e) reject(e);
145
+ else resolve(r);
146
+ });
147
+ });
148
+ }
149
+ if (msg.type === "send") {
150
+ const docCheck = await new Promise((resolve, reject) => {
151
+ cadHasDoc(msg.platform || "AutoCAD", (e, r) => {
152
+ if (e) reject(e);
153
+ else resolve(r);
154
+ });
155
+ });
156
+ if (!docCheck.hasDoc) {
157
+ return { success: false, error: "No open document" };
158
+ }
159
+ const parenCheck = checkParens(msg.code);
160
+ if (!parenCheck.valid) {
161
+ return { success: false, error: `\u62EC\u53F7\u9519\u8BEF: ${parenCheck.error} (\u4F4D\u7F6E ${parenCheck.pos})` };
162
+ }
163
+ if (!await waitForIdle(msg.platform || "AutoCAD")) {
164
+ return { success: false, error: "CAD is busy, timeout" };
165
+ }
166
+ log(`send: ${msg.code}`);
167
+ return new Promise((resolve, reject) => {
168
+ cadSend({ code: msg.code, platform: msg.platform }, (e, r) => {
169
+ if (e) {
170
+ log(`send error: ${e.message}`);
171
+ reject(e);
172
+ } else {
173
+ log(`send result: ${JSON.stringify(r)}`);
174
+ resolve(r);
175
+ }
176
+ });
177
+ });
178
+ }
179
+ if (msg.type === "sendResult") {
180
+ const docCheck = await new Promise((resolve, reject) => {
181
+ cadHasDoc(msg.platform || "AutoCAD", (e, r) => {
182
+ if (e) reject(e);
183
+ else resolve(r);
184
+ });
185
+ });
186
+ if (!docCheck.hasDoc) {
187
+ return { success: false, error: "No open document" };
188
+ }
189
+ const parenCheck = checkParens(msg.code);
190
+ if (!parenCheck.valid) {
191
+ return { success: false, error: `\u62EC\u53F7\u9519\u8BEF: ${parenCheck.error} (\u4F4D\u7F6E ${parenCheck.pos})` };
192
+ }
193
+ if (!await waitForIdle(msg.platform)) {
194
+ return { success: false, error: "CAD is busy, timeout" };
195
+ }
196
+ log(`sendResult: ${msg.code}`);
197
+ return new Promise((resolve, reject) => {
198
+ cadSendWithResult({ code: msg.code, platform: msg.platform, encoding: msg.encoding || "" }, (e, r) => {
199
+ if (e) {
200
+ log(`sendResult error: ${e.message}`);
201
+ reject(e);
202
+ } else {
203
+ log(`sendResult result: ${JSON.stringify(r)}`);
204
+ resolve(r);
205
+ }
206
+ });
207
+ });
208
+ }
209
+ if (msg.type === "isBusy") {
210
+ return new Promise((resolve, reject) => {
211
+ cadIsBusy(msg.platform || "AutoCAD", (e, r) => {
212
+ if (e) reject(e);
213
+ else resolve(r);
214
+ });
215
+ });
216
+ }
217
+ return { error: "unknown message type" };
218
+ }
219
+ export {
220
+ checkParens
221
+ };
package/package.json CHANGED
@@ -1,21 +1,25 @@
1
1
  {
2
2
  "name": "@atlisp/mcp",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "MCP Server for @lisp on CAD",
5
5
  "type": "module",
6
6
  "bin": {
7
- "atlisp-mcp": "./src/atlisp-mcp.js"
7
+ "atlisp-mcp": "./dist/atlisp-mcp.js"
8
8
  },
9
- "main": "src/atlisp-mcp.js",
9
+ "main": "dist/atlisp-mcp.js",
10
10
  "exports": {
11
- ".": "./src/atlisp-mcp.js",
12
- "./cad": "./src/cad.js"
11
+ ".": "./dist/atlisp-mcp.js",
12
+ "./cad": "./dist/atlisp-mcp.js"
13
13
  },
14
14
  "files": [
15
- "src"
15
+ "dist"
16
16
  ],
17
17
  "scripts": {
18
18
  "start": "node src/atlisp-mcp.js",
19
+ "build": "npm run build:main && npm run build:worker",
20
+ "build:main": "esbuild src/atlisp-mcp.js --bundle --platform=node --target=node18 --format=esm --outdir=dist --external:edge-js --packages=external --banner:js=\"#!/usr/bin/env node\"",
21
+ "build:worker": "esbuild src/cad-worker.js --bundle --platform=node --target=node18 --format=esm --outdir=dist --external:edge-js --packages=external",
22
+ "prepublishOnly": "npm run build",
19
23
  "test": "vitest run",
20
24
  "test:watch": "vitest"
21
25
  },
@@ -48,6 +52,7 @@
48
52
  "node": ">=18.0.0"
49
53
  },
50
54
  "devDependencies": {
55
+ "esbuild": "^0.28.0",
51
56
  "vitest": "^4.1.5"
52
57
  }
53
58
  }