@atlisp/mcp 1.8.30 → 1.8.31
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/README.md +28 -1
- package/dist/atlisp-mcp.js +277 -32
- package/dist/cad-rothelper.dll +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -189,6 +189,30 @@ atlisp-mcp --ws
|
|
|
189
189
|
atlisp-mcp --port 9000 --host 127.0.0.1
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
+
> **端口防冲突**:每个端口只允许一个实例运行。启动时自动检测端口是否已被其他 `atlisp-mcp` 进程占用(通过 `~/.atlisp/locks/atlisp-mcp-{port}.lock` PID 锁文件),占用则报错退出。不同端口可同时运行多个实例互不干扰。
|
|
193
|
+
|
|
194
|
+
### 设置开机自启
|
|
195
|
+
|
|
196
|
+
注册到用户登录后自动启动 HTTP 服务:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
atlisp-mcp --install-autostart
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
移除自启:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
atlisp-mcp --uninstall-autostart
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
查看自启状态:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
atlisp-mcp --autostart-status
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
支持三种平台:Windows(Registry Run 键)、macOS(LaunchAgent)、Linux(XDG Autostart)。
|
|
215
|
+
|
|
192
216
|
### 健康检查
|
|
193
217
|
|
|
194
218
|
```bash
|
|
@@ -824,6 +848,9 @@ curl http://localhost:8110/metrics
|
|
|
824
848
|
| `--config <path>` | 配置文件路径 |
|
|
825
849
|
| `--ssl-key <path>` | SSL 私钥文件 |
|
|
826
850
|
| `--ssl-cert <path>` | SSL 证书文件 |
|
|
851
|
+
| `--install-autostart` | 注册用户登录后自动启动 HTTP 服务 |
|
|
852
|
+
| `--uninstall-autostart` | 移除自动启动注册 |
|
|
853
|
+
| `--autostart-status` | 查询自动启动是否已安装 |
|
|
827
854
|
|
|
828
855
|
---
|
|
829
856
|
|
|
@@ -880,7 +907,7 @@ curl http://localhost:8110/metrics
|
|
|
880
907
|
| 中文乱码 | 使用 `encoding: gbk` 参数或用 `vl-prin1-to-string` 处理 |
|
|
881
908
|
| 括号错误 | MCP Server 会自动检查并提示 |
|
|
882
909
|
| CAD 未自动启动 | 检查 COM 权限,以管理员身份运行 |
|
|
883
|
-
| 端口被占用 | 使用 `--port`
|
|
910
|
+
| 端口被占用 | 使用 `--port` 指定其他端口;同端口多实例冲突时,结束原进程或换端口 |
|
|
884
911
|
| 全局命令找不到 | 检查 npm 全局安装路径是否在 PATH 中 |
|
|
885
912
|
|
|
886
913
|
---
|
package/dist/atlisp-mcp.js
CHANGED
|
@@ -7,10 +7,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
8
8
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
9
9
|
});
|
|
10
|
-
var __glob = (map) => (
|
|
11
|
-
var fn = map[
|
|
10
|
+
var __glob = (map) => (path23) => {
|
|
11
|
+
var fn = map[path23];
|
|
12
12
|
if (fn) return fn();
|
|
13
|
-
throw new Error("Module not found in bundle: " +
|
|
13
|
+
throw new Error("Module not found in bundle: " + path23);
|
|
14
14
|
};
|
|
15
15
|
var __esm = (fn, res) => function __init() {
|
|
16
16
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -1894,8 +1894,8 @@ __export(renderer_exports, {
|
|
|
1894
1894
|
renderPrompt: () => renderPrompt,
|
|
1895
1895
|
renderTemplate: () => renderTemplate
|
|
1896
1896
|
});
|
|
1897
|
-
function resolvePath(obj,
|
|
1898
|
-
const parts =
|
|
1897
|
+
function resolvePath(obj, path23) {
|
|
1898
|
+
const parts = path23.split(/[.\[\]]/g).filter(Boolean);
|
|
1899
1899
|
let val = obj;
|
|
1900
1900
|
for (const p of parts) {
|
|
1901
1901
|
if (val == null) return void 0;
|
|
@@ -1905,8 +1905,8 @@ function resolvePath(obj, path21) {
|
|
|
1905
1905
|
}
|
|
1906
1906
|
function renderTemplate(template, args) {
|
|
1907
1907
|
return template.replace(PARAM_RE, (match, rawExpr, expr) => {
|
|
1908
|
-
const
|
|
1909
|
-
const val = resolvePath(args,
|
|
1908
|
+
const path23 = rawExpr || expr;
|
|
1909
|
+
const val = resolvePath(args, path23);
|
|
1910
1910
|
if (val == null) return "";
|
|
1911
1911
|
const strVal = String(val);
|
|
1912
1912
|
if (rawExpr) return strVal;
|
|
@@ -2338,8 +2338,8 @@ var init_sse_session = __esm({
|
|
|
2338
2338
|
sendMessage(data) {
|
|
2339
2339
|
return this.sendEvent(SSE_EVENTS.MESSAGE, data);
|
|
2340
2340
|
}
|
|
2341
|
-
sendEndpoint(
|
|
2342
|
-
return this.sendEvent(SSE_EVENTS.ENDPOINT,
|
|
2341
|
+
sendEndpoint(path23) {
|
|
2342
|
+
return this.sendEvent(SSE_EVENTS.ENDPOINT, path23);
|
|
2343
2343
|
}
|
|
2344
2344
|
sendError(code, message, id = null) {
|
|
2345
2345
|
return this.sendEvent(SSE_EVENTS.ERROR, { code, message }, id);
|
|
@@ -14376,8 +14376,8 @@ async function exportXdataToFile(handle, filePath) {
|
|
|
14376
14376
|
await ensureCadConnected();
|
|
14377
14377
|
const xdataResult = await getAllEntityXdata(handle);
|
|
14378
14378
|
const parsed = JSON.parse(xdataResult.content[0].text);
|
|
14379
|
-
const
|
|
14380
|
-
|
|
14379
|
+
const fs19 = await import("fs");
|
|
14380
|
+
fs19.writeFileSync(filePath, JSON.stringify(parsed.xdata, null, 2));
|
|
14381
14381
|
return mcpSuccess(JSON.stringify({ handle, filePath }));
|
|
14382
14382
|
} catch (e) {
|
|
14383
14383
|
return mcpError(`\u9519\u8BEF: ${e.message}`);
|
|
@@ -14386,8 +14386,8 @@ async function exportXdataToFile(handle, filePath) {
|
|
|
14386
14386
|
async function importXdataFromFile(handle, filePath, appName) {
|
|
14387
14387
|
try {
|
|
14388
14388
|
await ensureCadConnected();
|
|
14389
|
-
const
|
|
14390
|
-
const data =
|
|
14389
|
+
const fs19 = await import("fs");
|
|
14390
|
+
const data = fs19.readFileSync(filePath, "utf8");
|
|
14391
14391
|
const xdata = JSON.parse(data);
|
|
14392
14392
|
if (appName && xdata[appName]) {
|
|
14393
14393
|
return await setXdata(handle, appName, xdata[appName]);
|
|
@@ -14436,13 +14436,13 @@ function lispPoint(pt) {
|
|
|
14436
14436
|
}
|
|
14437
14437
|
async function attachXref(args) {
|
|
14438
14438
|
try {
|
|
14439
|
-
const
|
|
14439
|
+
const path23 = esc3(args.path);
|
|
14440
14440
|
const point = lispPoint(args.point);
|
|
14441
14441
|
const scale = args.scale || 1;
|
|
14442
14442
|
const rotation = args.rotation || 0;
|
|
14443
14443
|
const overlay = args.overlay ? "_O" : "_A";
|
|
14444
14444
|
const result = await cad.sendCommandWithResult(
|
|
14445
|
-
`(command "_.XATTACH" "${
|
|
14445
|
+
`(command "_.XATTACH" "${path23}" "${overlay}" "${point}" "${scale}" "${rotation}") (princ)`
|
|
14446
14446
|
);
|
|
14447
14447
|
return mcpSuccess(`\u5916\u90E8\u53C2\u7167\u5DF2\u9644\u7740: ${args.path}`);
|
|
14448
14448
|
} catch (e) {
|
|
@@ -15586,8 +15586,8 @@ async function evaluateWatch(watch) {
|
|
|
15586
15586
|
);
|
|
15587
15587
|
const arr = parseLispList2(result) || [];
|
|
15588
15588
|
const matched = Number(arr[0]) !== 0;
|
|
15589
|
-
const
|
|
15590
|
-
return { matched, data: { matched: Boolean(matched), path:
|
|
15589
|
+
const path23 = String(arr[1] || "");
|
|
15590
|
+
return { matched, data: { matched: Boolean(matched), path: path23 } };
|
|
15591
15591
|
}
|
|
15592
15592
|
case "entity_selected": {
|
|
15593
15593
|
result = await cad.sendCommandWithResult(
|
|
@@ -16203,9 +16203,9 @@ var init_agent_context = __esm({
|
|
|
16203
16203
|
function validationError(msg) {
|
|
16204
16204
|
return new MCPError(ERROR_CODES.INVALID_ARGS, msg);
|
|
16205
16205
|
}
|
|
16206
|
-
function validateProps(args, props, required,
|
|
16206
|
+
function validateProps(args, props, required, path23 = "") {
|
|
16207
16207
|
for (const [key, prop] of Object.entries(props)) {
|
|
16208
|
-
const fullKey =
|
|
16208
|
+
const fullKey = path23 ? `${path23}.${key}` : key;
|
|
16209
16209
|
const isOptional = !required.includes(key);
|
|
16210
16210
|
const val = args[key];
|
|
16211
16211
|
if (val === void 0 || val === null) {
|
|
@@ -18796,8 +18796,8 @@ init_subscription_manager();
|
|
|
18796
18796
|
init_subscription_manager();
|
|
18797
18797
|
init_sse_session();
|
|
18798
18798
|
init_config();
|
|
18799
|
-
import
|
|
18800
|
-
import
|
|
18799
|
+
import path22 from "path";
|
|
18800
|
+
import fs18 from "fs";
|
|
18801
18801
|
import http from "http";
|
|
18802
18802
|
import https from "https";
|
|
18803
18803
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
@@ -19489,10 +19489,10 @@ function sendWelcome(ws, clientId) {
|
|
|
19489
19489
|
}
|
|
19490
19490
|
}
|
|
19491
19491
|
function startPingPong(ws, clientId) {
|
|
19492
|
-
let
|
|
19492
|
+
let isAlive2 = true;
|
|
19493
19493
|
ws._isAlive = true;
|
|
19494
19494
|
ws.on("pong", () => {
|
|
19495
|
-
|
|
19495
|
+
isAlive2 = true;
|
|
19496
19496
|
ws._isAlive = true;
|
|
19497
19497
|
});
|
|
19498
19498
|
const interval = setInterval(() => {
|
|
@@ -19500,13 +19500,13 @@ function startPingPong(ws, clientId) {
|
|
|
19500
19500
|
clearInterval(interval);
|
|
19501
19501
|
return;
|
|
19502
19502
|
}
|
|
19503
|
-
if (!
|
|
19503
|
+
if (!isAlive2) {
|
|
19504
19504
|
clearInterval(interval);
|
|
19505
19505
|
log(`WebSocket ping timeout, terminating [${clientId}]`);
|
|
19506
19506
|
ws.terminate();
|
|
19507
19507
|
return;
|
|
19508
19508
|
}
|
|
19509
|
-
|
|
19509
|
+
isAlive2 = false;
|
|
19510
19510
|
ws._isAlive = false;
|
|
19511
19511
|
try {
|
|
19512
19512
|
ws.ping();
|
|
@@ -19989,13 +19989,228 @@ function setupStreamableHttpRoutes(app) {
|
|
|
19989
19989
|
});
|
|
19990
19990
|
}
|
|
19991
19991
|
|
|
19992
|
+
// src/lockfile.js
|
|
19993
|
+
import fs16 from "fs";
|
|
19994
|
+
import path20 from "path";
|
|
19995
|
+
import os13 from "os";
|
|
19996
|
+
var LOCK_DIR = path20.join(os13.homedir(), ".atlisp", "locks");
|
|
19997
|
+
function ensureDir2() {
|
|
19998
|
+
if (!fs16.existsSync(LOCK_DIR)) {
|
|
19999
|
+
fs16.mkdirSync(LOCK_DIR, { recursive: true });
|
|
20000
|
+
}
|
|
20001
|
+
}
|
|
20002
|
+
function lockPath(port) {
|
|
20003
|
+
return path20.join(LOCK_DIR, `atlisp-mcp-${port}.lock`);
|
|
20004
|
+
}
|
|
20005
|
+
function isAlive(pid) {
|
|
20006
|
+
try {
|
|
20007
|
+
process.kill(pid, 0);
|
|
20008
|
+
return true;
|
|
20009
|
+
} catch (e) {
|
|
20010
|
+
return e.code === "EPERM";
|
|
20011
|
+
}
|
|
20012
|
+
}
|
|
20013
|
+
function acquirePortLock(port, host) {
|
|
20014
|
+
ensureDir2();
|
|
20015
|
+
const lp = lockPath(port);
|
|
20016
|
+
const payload = JSON.stringify({ pid: process.pid, port, host, started: (/* @__PURE__ */ new Date()).toISOString() });
|
|
20017
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
20018
|
+
try {
|
|
20019
|
+
const fd = fs16.openSync(lp, "wx");
|
|
20020
|
+
fs16.writeSync(fd, payload, 0, "utf-8");
|
|
20021
|
+
fs16.closeSync(fd);
|
|
20022
|
+
return { ok: true };
|
|
20023
|
+
} catch (err) {
|
|
20024
|
+
if (err.code !== "EEXIST") throw err;
|
|
20025
|
+
try {
|
|
20026
|
+
const existing = JSON.parse(fs16.readFileSync(lp, "utf-8"));
|
|
20027
|
+
if (existing.pid && isAlive(existing.pid)) {
|
|
20028
|
+
return { ok: false, pid: existing.pid, started: existing.started };
|
|
20029
|
+
}
|
|
20030
|
+
} catch {
|
|
20031
|
+
}
|
|
20032
|
+
try {
|
|
20033
|
+
fs16.unlinkSync(lp);
|
|
20034
|
+
} catch {
|
|
20035
|
+
}
|
|
20036
|
+
}
|
|
20037
|
+
}
|
|
20038
|
+
return { ok: false, pid: null, started: null };
|
|
20039
|
+
}
|
|
20040
|
+
function releasePortLock(port) {
|
|
20041
|
+
try {
|
|
20042
|
+
const lp = lockPath(port);
|
|
20043
|
+
try {
|
|
20044
|
+
const existing = JSON.parse(fs16.readFileSync(lp, "utf-8"));
|
|
20045
|
+
if (existing.pid !== process.pid) return;
|
|
20046
|
+
} catch {
|
|
20047
|
+
}
|
|
20048
|
+
fs16.unlinkSync(lp);
|
|
20049
|
+
} catch {
|
|
20050
|
+
}
|
|
20051
|
+
}
|
|
20052
|
+
|
|
20053
|
+
// src/autostart.js
|
|
20054
|
+
import { execSync } from "child_process";
|
|
20055
|
+
import path21 from "path";
|
|
20056
|
+
import fs17 from "fs";
|
|
20057
|
+
import os14 from "os";
|
|
20058
|
+
var AUTOSTART_NAME = "atlisp-mcp";
|
|
20059
|
+
function getStartupCommand() {
|
|
20060
|
+
const nodePath = process.execPath;
|
|
20061
|
+
const scriptPath = process.argv[1];
|
|
20062
|
+
return `"${nodePath}" "${scriptPath}" --transport http`;
|
|
20063
|
+
}
|
|
20064
|
+
function xdgAutostartDir() {
|
|
20065
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
20066
|
+
return path21.join(xdg || path21.join(os14.homedir(), ".config"), "autostart");
|
|
20067
|
+
}
|
|
20068
|
+
function installAutostart() {
|
|
20069
|
+
const platform = process.platform;
|
|
20070
|
+
if (platform === "win32") {
|
|
20071
|
+
const cmd = getStartupCommand().replace(/"/g, '\\"');
|
|
20072
|
+
try {
|
|
20073
|
+
execSync(
|
|
20074
|
+
`reg add "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "${AUTOSTART_NAME}" /t REG_SZ /d "${cmd}" /f`,
|
|
20075
|
+
{ stdio: "pipe", timeout: 5e3 }
|
|
20076
|
+
);
|
|
20077
|
+
console.error(`\u81EA\u52A8\u542F\u52A8\u5DF2\u5B89\u88C5 (HKCU\\...\\Run)`);
|
|
20078
|
+
return true;
|
|
20079
|
+
} catch (e) {
|
|
20080
|
+
console.error(`\u5B89\u88C5\u81EA\u52A8\u542F\u52A8\u5931\u8D25: ${e.message}`);
|
|
20081
|
+
return false;
|
|
20082
|
+
}
|
|
20083
|
+
}
|
|
20084
|
+
if (platform === "darwin") {
|
|
20085
|
+
const plistDir = path21.join(os14.homedir(), "Library", "LaunchAgents");
|
|
20086
|
+
const plistPath = path21.join(plistDir, `com.atlisp.mcp.plist`);
|
|
20087
|
+
const cmd = getStartupCommand().replace(/"/g, """);
|
|
20088
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
20089
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
20090
|
+
<plist version="1.0">
|
|
20091
|
+
<dict>
|
|
20092
|
+
<key>Label</key>
|
|
20093
|
+
<string>com.atlisp.mcp</string>
|
|
20094
|
+
<key>ProgramArguments</key>
|
|
20095
|
+
<array>
|
|
20096
|
+
<string>${process.execPath}</string>
|
|
20097
|
+
<string>${process.argv[1]}</string>
|
|
20098
|
+
<string>--transport</string>
|
|
20099
|
+
<string>http</string>
|
|
20100
|
+
</array>
|
|
20101
|
+
<key>RunAtLoad</key>
|
|
20102
|
+
<true/>
|
|
20103
|
+
<key>KeepAlive</key>
|
|
20104
|
+
<false/>
|
|
20105
|
+
</dict>
|
|
20106
|
+
</plist>`;
|
|
20107
|
+
try {
|
|
20108
|
+
if (!fs17.existsSync(plistDir)) fs17.mkdirSync(plistDir, { recursive: true });
|
|
20109
|
+
fs17.writeFileSync(plistPath, plist, "utf-8");
|
|
20110
|
+
execSync(`launchctl load "${plistPath}"`, { stdio: "pipe", timeout: 5e3 });
|
|
20111
|
+
console.error(`\u81EA\u52A8\u542F\u52A8\u5DF2\u5B89\u88C5 (LaunchAgent)`);
|
|
20112
|
+
return true;
|
|
20113
|
+
} catch (e) {
|
|
20114
|
+
console.error(`\u5B89\u88C5\u81EA\u52A8\u542F\u52A8\u5931\u8D25: ${e.message}`);
|
|
20115
|
+
return false;
|
|
20116
|
+
}
|
|
20117
|
+
}
|
|
20118
|
+
if (platform === "linux") {
|
|
20119
|
+
const dir = xdgAutostartDir();
|
|
20120
|
+
const desktopPath = path21.join(dir, "atlisp-mcp.desktop");
|
|
20121
|
+
const cmd = getStartupCommand();
|
|
20122
|
+
const desktop = `[Desktop Entry]
|
|
20123
|
+
Type=Application
|
|
20124
|
+
Name=@lisp MCP Server
|
|
20125
|
+
Exec=${cmd}
|
|
20126
|
+
Terminal=false
|
|
20127
|
+
X-GNOME-Autostart-enabled=true
|
|
20128
|
+
`;
|
|
20129
|
+
try {
|
|
20130
|
+
if (!fs17.existsSync(dir)) fs17.mkdirSync(dir, { recursive: true });
|
|
20131
|
+
fs17.writeFileSync(desktopPath, desktop, "utf-8");
|
|
20132
|
+
console.error(`\u81EA\u52A8\u542F\u52A8\u5DF2\u5B89\u88C5 (XDG Autostart)`);
|
|
20133
|
+
return true;
|
|
20134
|
+
} catch (e) {
|
|
20135
|
+
console.error(`\u5B89\u88C5\u81EA\u52A8\u542F\u52A8\u5931\u8D25: ${e.message}`);
|
|
20136
|
+
return false;
|
|
20137
|
+
}
|
|
20138
|
+
}
|
|
20139
|
+
console.error(`\u5F53\u524D\u5E73\u53F0 ${platform} \u4E0D\u652F\u6301\u81EA\u52A8\u542F\u52A8`);
|
|
20140
|
+
return false;
|
|
20141
|
+
}
|
|
20142
|
+
function uninstallAutostart() {
|
|
20143
|
+
const platform = process.platform;
|
|
20144
|
+
if (platform === "win32") {
|
|
20145
|
+
try {
|
|
20146
|
+
execSync(
|
|
20147
|
+
`reg delete "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "${AUTOSTART_NAME}" /f`,
|
|
20148
|
+
{ stdio: "pipe", timeout: 5e3 }
|
|
20149
|
+
);
|
|
20150
|
+
console.error("\u81EA\u52A8\u542F\u52A8\u5DF2\u5378\u8F7D");
|
|
20151
|
+
return true;
|
|
20152
|
+
} catch (e) {
|
|
20153
|
+
console.error(`\u5378\u8F7D\u81EA\u52A8\u542F\u52A8\u5931\u8D25: ${e.message}`);
|
|
20154
|
+
return false;
|
|
20155
|
+
}
|
|
20156
|
+
}
|
|
20157
|
+
if (platform === "darwin") {
|
|
20158
|
+
const plistPath = path21.join(os14.homedir(), "Library", "LaunchAgents", "com.atlisp.mcp.plist");
|
|
20159
|
+
try {
|
|
20160
|
+
execSync(`launchctl unload "${plistPath}"`, { stdio: "pipe", timeout: 5e3 });
|
|
20161
|
+
fs17.unlinkSync(plistPath);
|
|
20162
|
+
console.error("\u81EA\u52A8\u542F\u52A8\u5DF2\u5378\u8F7D");
|
|
20163
|
+
return true;
|
|
20164
|
+
} catch (e) {
|
|
20165
|
+
console.error(`\u5378\u8F7D\u81EA\u52A8\u542F\u52A8\u5931\u8D25: ${e.message}`);
|
|
20166
|
+
return false;
|
|
20167
|
+
}
|
|
20168
|
+
}
|
|
20169
|
+
if (platform === "linux") {
|
|
20170
|
+
const desktopPath = path21.join(xdgAutostartDir(), "atlisp-mcp.desktop");
|
|
20171
|
+
try {
|
|
20172
|
+
if (fs17.existsSync(desktopPath)) fs17.unlinkSync(desktopPath);
|
|
20173
|
+
console.error("\u81EA\u52A8\u542F\u52A8\u5DF2\u5378\u8F7D");
|
|
20174
|
+
return true;
|
|
20175
|
+
} catch (e) {
|
|
20176
|
+
console.error(`\u5378\u8F7D\u81EA\u52A8\u542F\u52A8\u5931\u8D25: ${e.message}`);
|
|
20177
|
+
return false;
|
|
20178
|
+
}
|
|
20179
|
+
}
|
|
20180
|
+
return false;
|
|
20181
|
+
}
|
|
20182
|
+
function autostartStatus() {
|
|
20183
|
+
const platform = process.platform;
|
|
20184
|
+
if (platform === "win32") {
|
|
20185
|
+
try {
|
|
20186
|
+
const out = execSync(
|
|
20187
|
+
`reg query "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "${AUTOSTART_NAME}"`,
|
|
20188
|
+
{ stdio: "pipe", timeout: 5e3, encoding: "utf-8" }
|
|
20189
|
+
);
|
|
20190
|
+
const match = out.match(/(\S+\.js)/);
|
|
20191
|
+
return { installed: true, command: match ? match[1] : out.trim() };
|
|
20192
|
+
} catch {
|
|
20193
|
+
return { installed: false };
|
|
20194
|
+
}
|
|
20195
|
+
}
|
|
20196
|
+
if (platform === "darwin") {
|
|
20197
|
+
const plistPath = path21.join(os14.homedir(), "Library", "LaunchAgents", "com.atlisp.mcp.plist");
|
|
20198
|
+
return { installed: fs17.existsSync(plistPath) };
|
|
20199
|
+
}
|
|
20200
|
+
if (platform === "linux") {
|
|
20201
|
+
const desktopPath = path21.join(xdgAutostartDir(), "atlisp-mcp.desktop");
|
|
20202
|
+
return { installed: fs17.existsSync(desktopPath) };
|
|
20203
|
+
}
|
|
20204
|
+
return { installed: false, error: `${platform} \u4E0D\u652F\u6301\u81EA\u52A8\u542F\u52A8` };
|
|
20205
|
+
}
|
|
20206
|
+
|
|
19992
20207
|
// src/atlisp-mcp.js
|
|
19993
20208
|
init_mcp_tools();
|
|
19994
20209
|
init_function_handlers();
|
|
19995
20210
|
init_constants();
|
|
19996
|
-
var __dirname7 =
|
|
20211
|
+
var __dirname7 = path22.dirname(fileURLToPath8(import.meta.url));
|
|
19997
20212
|
var require3 = createRequire2(import.meta.url);
|
|
19998
|
-
var { version: version2 } = require3(
|
|
20213
|
+
var { version: version2 } = require3(path22.join(__dirname7, "..", "package.json"));
|
|
19999
20214
|
var isMcpScript = process.argv[1]?.includes("atlisp-mcp");
|
|
20000
20215
|
if (isMcpScript) {
|
|
20001
20216
|
const cliArgs2 = process.argv.slice(2);
|
|
@@ -20031,6 +20246,9 @@ Options:
|
|
|
20031
20246
|
--api-key <key> API key for authentication
|
|
20032
20247
|
--client-id <id> Client identifier for remote health report
|
|
20033
20248
|
--security-level <type> Security level: strict, standard, relaxed (default: strict)
|
|
20249
|
+
--install-autostart Register server to auto-start after user login
|
|
20250
|
+
--uninstall-autostart Remove auto-start registration
|
|
20251
|
+
--autostart-status Check if auto-start is installed
|
|
20034
20252
|
|
|
20035
20253
|
Environment Variables:
|
|
20036
20254
|
TRANSPORT Transport mode (http/stdio/ws)
|
|
@@ -20111,6 +20329,21 @@ For more info: https://atlisp.cn
|
|
|
20111
20329
|
process.env.CLIENT_ID = cliArgs2[++i];
|
|
20112
20330
|
} else if (arg === "--metrics-enabled" && cliArgs2[i + 1]) {
|
|
20113
20331
|
process.env.METRICS_ENABLED = cliArgs2[++i];
|
|
20332
|
+
} else if (arg === "--install-autostart") {
|
|
20333
|
+
installAutostart();
|
|
20334
|
+
process.exit(0);
|
|
20335
|
+
} else if (arg === "--uninstall-autostart") {
|
|
20336
|
+
uninstallAutostart();
|
|
20337
|
+
process.exit(0);
|
|
20338
|
+
} else if (arg === "--autostart-status") {
|
|
20339
|
+
const s = autostartStatus();
|
|
20340
|
+
if (s.installed) {
|
|
20341
|
+
console.error(`\u81EA\u52A8\u542F\u52A8: \u5DF2\u5B89\u88C5`);
|
|
20342
|
+
if (s.command) console.error(` \u547D\u4EE4: ${s.command}`);
|
|
20343
|
+
} else {
|
|
20344
|
+
console.error(`\u81EA\u52A8\u542F\u52A8: \u672A\u5B89\u88C5`);
|
|
20345
|
+
}
|
|
20346
|
+
process.exit(0);
|
|
20114
20347
|
}
|
|
20115
20348
|
}
|
|
20116
20349
|
}
|
|
@@ -20141,9 +20374,9 @@ async function startServer() {
|
|
|
20141
20374
|
startPluginWatcher();
|
|
20142
20375
|
let promptsWatcher = null;
|
|
20143
20376
|
try {
|
|
20144
|
-
const promptsDir =
|
|
20145
|
-
if (
|
|
20146
|
-
promptsWatcher =
|
|
20377
|
+
const promptsDir = path22.join(__dirname7, "..", "prompts");
|
|
20378
|
+
if (fs18.existsSync(promptsDir)) {
|
|
20379
|
+
promptsWatcher = fs18.watch(promptsDir, (eventType, filename) => {
|
|
20147
20380
|
if (filename && filename.endsWith(".json")) {
|
|
20148
20381
|
log(`Prompt changed: ${filename}`);
|
|
20149
20382
|
broadcastPromptsListChanged();
|
|
@@ -20191,13 +20424,23 @@ async function startServer() {
|
|
|
20191
20424
|
let httpsServer;
|
|
20192
20425
|
if (useSsl) {
|
|
20193
20426
|
const sslOptions = {
|
|
20194
|
-
key:
|
|
20195
|
-
cert:
|
|
20427
|
+
key: fs18.readFileSync(config_default.sslKey, "utf-8"),
|
|
20428
|
+
cert: fs18.readFileSync(config_default.sslCert, "utf-8")
|
|
20196
20429
|
};
|
|
20197
20430
|
httpsServer = https.createServer(sslOptions, app);
|
|
20198
20431
|
}
|
|
20199
20432
|
const rawServer = httpsServer || http.createServer(app);
|
|
20200
20433
|
createWebSocketServer(rawServer);
|
|
20434
|
+
const lock = acquirePortLock(config_default.port, config_default.host);
|
|
20435
|
+
if (!lock.ok) {
|
|
20436
|
+
console.error(`
|
|
20437
|
+
\u9519\u8BEF: \u7AEF\u53E3 ${config_default.port} \u5DF2\u88AB\u53E6\u4E00\u4E2A atlisp-mcp \u5B9E\u4F8B\u5360\u7528`);
|
|
20438
|
+
console.error(` PID: ${lock.pid}`);
|
|
20439
|
+
if (lock.started) console.error(` \u542F\u52A8\u65F6\u95F4: ${lock.started}`);
|
|
20440
|
+
console.error(`\u8BF7\u9009\u62E9\u5176\u4ED6\u7AEF\u53E3 (--port) \u6216\u7ED3\u675F\u5360\u7528\u8FDB\u7A0B\u540E\u91CD\u8BD5\u3002
|
|
20441
|
+
`);
|
|
20442
|
+
process.exit(1);
|
|
20443
|
+
}
|
|
20201
20444
|
const httpServer = rawServer.listen(config_default.port, config_default.host, async () => {
|
|
20202
20445
|
await initCadConnection();
|
|
20203
20446
|
const proto = useSsl ? "https" : "http";
|
|
@@ -20219,6 +20462,7 @@ async function startServer() {
|
|
|
20219
20462
|
removeSessionServer(sid);
|
|
20220
20463
|
}
|
|
20221
20464
|
await closeStreamableHttpServer();
|
|
20465
|
+
releasePortLock(config_default.port);
|
|
20222
20466
|
await cad.disconnect();
|
|
20223
20467
|
closeLog();
|
|
20224
20468
|
httpServer.close(() => {
|
|
@@ -20229,6 +20473,7 @@ async function startServer() {
|
|
|
20229
20473
|
}
|
|
20230
20474
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
20231
20475
|
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
20476
|
+
process.on("exit", () => releasePortLock(config_default.port));
|
|
20232
20477
|
}
|
|
20233
20478
|
}
|
|
20234
20479
|
onDocumentChanged((info) => {
|
package/dist/cad-rothelper.dll
CHANGED
|
Binary file
|