@usex/mikrotik-mcp 3.57.0 → 3.59.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.
- package/dist/cli.js +84 -64
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -15
- package/dist/shared/{cli-0ctwspf1.js → cli-2dyvnv9v.js} +1 -1
- package/dist/shared/{cli-thhk9f7n.js → cli-jq168zrj.js} +829 -597
- package/dist/shared/{library-jve65pzw.js → library-0zd2tej9.js} +1 -1
- package/dist/shared/{library-ymtf9zyk.js → library-21t1cncr.js} +828 -597
- package/dist/ui/aaa.html +1 -1
- package/dist/ui/connected-devices.html +1 -1
- package/dist/ui/dashboard.html +1 -1
- package/dist/ui/firewall-audit.html +1 -1
- package/dist/ui/firewall.html +1 -1
- package/dist/ui/interfaces.html +1 -1
- package/dist/ui/observability.html +1 -1
- package/dist/ui/records.html +1 -1
- package/package.json +1 -1
- package/schemas/README.md +5 -5
- package/schemas/config.schema.json +47 -10
- package/schemas/tool-catalog.json +2941 -736
- package/schemas/tools/check_server_pulse.json +12 -0
- package/schemas/tools/config_check_drift.json +5 -1
- package/schemas/tools/config_reconcile.json +3 -1
- package/schemas/tools/config_set_baseline.json +4 -1
- package/schemas/tools/correlate_events.json +4 -1
- package/schemas/tools/diagnose.json +3 -1
- package/schemas/tools/get_filter_rule.json +1 -1
- package/schemas/tools/memory_add_observations.json +7 -2
- package/schemas/tools/memory_create_entities.json +7 -2
- package/schemas/tools/memory_create_relations.json +8 -2
- package/schemas/tools/memory_delete_entities.json +3 -1
- package/schemas/tools/memory_delete_observations.json +7 -2
- package/schemas/tools/memory_delete_relations.json +8 -2
- package/schemas/tools/memory_open_nodes.json +3 -1
- package/schemas/tools/memory_search_nodes.json +3 -1
- package/schemas/tools/suggest_fix.json +3 -1
- package/schemas/tools/trace_path.json +5 -1
package/dist/cli.js
CHANGED
|
@@ -8,12 +8,18 @@ import {
|
|
|
8
8
|
DEFAULT_SNAPSHOT_DB,
|
|
9
9
|
DEFAULT_TZSP_PORT,
|
|
10
10
|
DeviceConfigSchema,
|
|
11
|
+
LOGO_URL,
|
|
11
12
|
MikrotikConfigSchema,
|
|
12
|
-
|
|
13
|
+
PKG_META,
|
|
13
14
|
PROMPTS_DIR,
|
|
14
15
|
REDACTED,
|
|
16
|
+
SERVER_DESCRIPTION,
|
|
17
|
+
SERVER_NAME,
|
|
18
|
+
SERVER_TITLE,
|
|
15
19
|
ToolFilterSchema,
|
|
16
20
|
UI_DIST_DIR,
|
|
21
|
+
VERSION,
|
|
22
|
+
WEBSITE_URL,
|
|
17
23
|
__require,
|
|
18
24
|
addAaaEntity,
|
|
19
25
|
allToolModules,
|
|
@@ -24,6 +30,7 @@ import {
|
|
|
24
30
|
blockDevice,
|
|
25
31
|
buildChangePlan,
|
|
26
32
|
capture,
|
|
33
|
+
checkForUpdate,
|
|
27
34
|
closeAll,
|
|
28
35
|
closeMemoryStore,
|
|
29
36
|
commandUnsupported,
|
|
@@ -39,6 +46,7 @@ import {
|
|
|
39
46
|
diffLines,
|
|
40
47
|
executeMikrotikCommand,
|
|
41
48
|
fetchDevices,
|
|
49
|
+
fetchLatestRelease,
|
|
42
50
|
getConfig,
|
|
43
51
|
getConfigSource,
|
|
44
52
|
getEventStore,
|
|
@@ -54,6 +62,7 @@ import {
|
|
|
54
62
|
listBackups,
|
|
55
63
|
listDevices,
|
|
56
64
|
loadConfig,
|
|
65
|
+
loadFileCacheSync,
|
|
57
66
|
logger,
|
|
58
67
|
looksLikeError,
|
|
59
68
|
makeDeviceStatic,
|
|
@@ -95,16 +104,17 @@ import {
|
|
|
95
104
|
subscriberCount,
|
|
96
105
|
toggleAaaEntity,
|
|
97
106
|
updateAaaEntity,
|
|
107
|
+
updateSummaryLine,
|
|
98
108
|
writeBackup
|
|
99
|
-
} from "./shared/cli-
|
|
109
|
+
} from "./shared/cli-jq168zrj.js";
|
|
100
110
|
|
|
101
111
|
// src/cli.ts
|
|
102
112
|
import { existsSync as existsSync2 } from "fs";
|
|
103
113
|
|
|
104
114
|
// src/observability/dashboard.ts
|
|
105
|
-
import { readFileSync as
|
|
115
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
106
116
|
import { homedir, networkInterfaces } from "os";
|
|
107
|
-
import { dirname as dirname4, join as
|
|
117
|
+
import { dirname as dirname4, join as join2 } from "path";
|
|
108
118
|
var {serve } = globalThis.Bun;
|
|
109
119
|
import { z } from "zod";
|
|
110
120
|
|
|
@@ -1148,18 +1158,6 @@ function computeStats(events, opts) {
|
|
|
1148
1158
|
};
|
|
1149
1159
|
}
|
|
1150
1160
|
|
|
1151
|
-
// src/version.ts
|
|
1152
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
1153
|
-
import { join as join2 } from "path";
|
|
1154
|
-
var pkg = JSON.parse(readFileSync2(join2(PROJECT_ROOT, "package.json"), "utf-8"));
|
|
1155
|
-
var VERSION = pkg.version ?? "0.0.0";
|
|
1156
|
-
var WEBSITE_URL = pkg.homepage ?? "";
|
|
1157
|
-
var LOGO_URL = pkg.logoIcon ?? "";
|
|
1158
|
-
var SERVER_TITLE = "MikroTik MCP";
|
|
1159
|
-
var SERVER_DESCRIPTION = pkg.description ?? "";
|
|
1160
|
-
var SERVER_NAME = "mikrotik-mcp";
|
|
1161
|
-
var PKG_META = pkg;
|
|
1162
|
-
|
|
1163
1161
|
// src/observability/drift-routes.ts
|
|
1164
1162
|
var storePromise = null;
|
|
1165
1163
|
function getStore() {
|
|
@@ -1425,51 +1423,13 @@ async function memoryRoutes(req, url) {
|
|
|
1425
1423
|
|
|
1426
1424
|
// src/observability/dashboard.ts
|
|
1427
1425
|
var SERVER_TAG2 = "mikrotik-mcp";
|
|
1428
|
-
var releaseCache = null;
|
|
1429
|
-
var RELEASE_CACHE_TTL = 15 * 60 * 1000;
|
|
1430
|
-
function compareVersions(a, b) {
|
|
1431
|
-
const pa = a.replace(/^v/, "").split(".").map(Number);
|
|
1432
|
-
const pb = b.replace(/^v/, "").split(".").map(Number);
|
|
1433
|
-
for (let i = 0;i < Math.max(pa.length, pb.length); i++) {
|
|
1434
|
-
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
1435
|
-
if (diff !== 0)
|
|
1436
|
-
return diff;
|
|
1437
|
-
}
|
|
1438
|
-
return 0;
|
|
1439
|
-
}
|
|
1440
|
-
async function fetchLatestRelease() {
|
|
1441
|
-
if (releaseCache && Date.now() - releaseCache.fetchedAt < RELEASE_CACHE_TTL) {
|
|
1442
|
-
return releaseCache.data;
|
|
1443
|
-
}
|
|
1444
|
-
const res = await fetch("https://api.github.com/repos/ali-master/mikrotik-mcp/releases/latest", {
|
|
1445
|
-
headers: {
|
|
1446
|
-
accept: "application/vnd.github+json",
|
|
1447
|
-
"user-agent": "mikrotik-mcp-dashboard"
|
|
1448
|
-
}
|
|
1449
|
-
});
|
|
1450
|
-
if (!res.ok)
|
|
1451
|
-
throw new Error(`GitHub API ${res.status}`);
|
|
1452
|
-
const gh = await res.json();
|
|
1453
|
-
const latestVersion = gh.tag_name.replace(/^v/, "");
|
|
1454
|
-
const data = {
|
|
1455
|
-
version: latestVersion,
|
|
1456
|
-
name: gh.name || `v${latestVersion}`,
|
|
1457
|
-
body: gh.body || "",
|
|
1458
|
-
publishedAt: gh.published_at,
|
|
1459
|
-
url: gh.html_url,
|
|
1460
|
-
isNewer: compareVersions(latestVersion, VERSION) > 0,
|
|
1461
|
-
currentVersion: VERSION
|
|
1462
|
-
};
|
|
1463
|
-
releaseCache = { data, fetchedAt: Date.now() };
|
|
1464
|
-
return data;
|
|
1465
|
-
}
|
|
1466
1426
|
var JSON_HEADERS3 = { "content-type": "application/json; charset=utf-8" };
|
|
1467
1427
|
function json3(body, status = 200) {
|
|
1468
1428
|
return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS3 });
|
|
1469
1429
|
}
|
|
1470
1430
|
function dashboardHtml() {
|
|
1471
1431
|
try {
|
|
1472
|
-
return
|
|
1432
|
+
return readFileSync2(join2(UI_DIST_DIR, "observability.html"), "utf8");
|
|
1473
1433
|
} catch {
|
|
1474
1434
|
return `<!doctype html><meta charset=utf-8><body style="font:14px system-ui;padding:24px;background:#0b0d10;color:#e8eaed">
|
|
1475
1435
|
<h2>MikroTik MCP \u2014 Observability Dashboard</h2>
|
|
@@ -1805,12 +1765,12 @@ async function configRoutes(req, url, admin) {
|
|
|
1805
1765
|
}
|
|
1806
1766
|
async function modulesRoutes(req, url) {
|
|
1807
1767
|
const p = url.pathname;
|
|
1808
|
-
if (p !== "/api/modules" && p !== "/api/modules/toggle")
|
|
1768
|
+
if (p !== "/api/modules" && p !== "/api/modules/toggle" && p !== "/api/modules/app-views")
|
|
1809
1769
|
return null;
|
|
1810
1770
|
if (p === "/api/modules" && req.method === "GET") {
|
|
1811
1771
|
const cfg = getConfig();
|
|
1812
1772
|
const src = getConfigSource();
|
|
1813
|
-
return json3({ ...moduleSurface(cfg.tools), filter: cfg.tools, source: src });
|
|
1773
|
+
return json3({ ...moduleSurface(cfg.tools), filter: cfg.tools, source: src, appViews: cfg.mcp.appViews });
|
|
1814
1774
|
}
|
|
1815
1775
|
if (p === "/api/modules/toggle" && req.method === "POST") {
|
|
1816
1776
|
const b = await readJson(req);
|
|
@@ -1847,6 +1807,34 @@ async function modulesRoutes(req, url) {
|
|
|
1847
1807
|
source: getConfigSource()
|
|
1848
1808
|
});
|
|
1849
1809
|
}
|
|
1810
|
+
if (p === "/api/modules/app-views" && req.method === "POST") {
|
|
1811
|
+
const b = await readJson(req);
|
|
1812
|
+
if (typeof b?.enabled !== "boolean") {
|
|
1813
|
+
return json3({ error: "enabled (boolean) is required" }, 400);
|
|
1814
|
+
}
|
|
1815
|
+
const cfg = getConfig();
|
|
1816
|
+
const next = { ...cfg, mcp: { ...cfg.mcp, appViews: b.enabled } };
|
|
1817
|
+
setConfig(next);
|
|
1818
|
+
let persisted = true;
|
|
1819
|
+
let warning;
|
|
1820
|
+
try {
|
|
1821
|
+
atomicWrite(getConfigSource().path, serializeConfig(next));
|
|
1822
|
+
} catch (e) {
|
|
1823
|
+
persisted = false;
|
|
1824
|
+
warning = `applied live but not saved to disk: ${e instanceof Error ? e.message : String(e)}`;
|
|
1825
|
+
}
|
|
1826
|
+
if (persisted) {
|
|
1827
|
+
recordVersion(getConfig(), "auto", Date.now(), `app views ${b.enabled ? "enabled" : "disabled"}`);
|
|
1828
|
+
}
|
|
1829
|
+
return json3({
|
|
1830
|
+
ok: true,
|
|
1831
|
+
persisted,
|
|
1832
|
+
requiresReconnect: true,
|
|
1833
|
+
warning,
|
|
1834
|
+
appViews: b.enabled,
|
|
1835
|
+
source: getConfigSource()
|
|
1836
|
+
});
|
|
1837
|
+
}
|
|
1850
1838
|
return null;
|
|
1851
1839
|
}
|
|
1852
1840
|
async function captureRoutes(req, url) {
|
|
@@ -2156,7 +2144,7 @@ async function featureRoutes(req, url) {
|
|
|
2156
2144
|
const raw = b?.dir?.trim();
|
|
2157
2145
|
if (!raw)
|
|
2158
2146
|
return json3({ error: "dir required" }, 400);
|
|
2159
|
-
const dir = raw === "~" || raw.startsWith("~/") ?
|
|
2147
|
+
const dir = raw === "~" || raw.startsWith("~/") ? join2(homedir(), raw.slice(1)) : raw;
|
|
2160
2148
|
const next = { ...getConfig(), backupDir: dir };
|
|
2161
2149
|
setConfig(next);
|
|
2162
2150
|
try {
|
|
@@ -2264,7 +2252,7 @@ async function runDashboard(cfg, transportLabel) {
|
|
|
2264
2252
|
});
|
|
2265
2253
|
startHealthChecks(30000);
|
|
2266
2254
|
try {
|
|
2267
|
-
usageStore = await openUsageStore(
|
|
2255
|
+
usageStore = await openUsageStore(join2(dirname4(cfg.dbPath), "usage.db"));
|
|
2268
2256
|
startUsageSampler(usageStore);
|
|
2269
2257
|
} catch (e) {
|
|
2270
2258
|
logger.warn(`[${SERVER_TAG2}] usage history disabled: ${String(e)}`);
|
|
@@ -2281,7 +2269,7 @@ async function runDashboard(cfg, transportLabel) {
|
|
|
2281
2269
|
source: getConfigSource,
|
|
2282
2270
|
readFile: (pth) => {
|
|
2283
2271
|
try {
|
|
2284
|
-
return
|
|
2272
|
+
return readFileSync2(pth, "utf8");
|
|
2285
2273
|
} catch {
|
|
2286
2274
|
return null;
|
|
2287
2275
|
}
|
|
@@ -2564,8 +2552,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
2564
2552
|
import { ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
2565
2553
|
|
|
2566
2554
|
// src/prompts/index.ts
|
|
2567
|
-
import { readFileSync as
|
|
2568
|
-
import { join as
|
|
2555
|
+
import { readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
|
|
2556
|
+
import { join as join3 } from "path";
|
|
2569
2557
|
import { z as z2 } from "zod";
|
|
2570
2558
|
function parseFrontmatter(raw) {
|
|
2571
2559
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
@@ -2648,7 +2636,7 @@ function registerPrompts(server, opts = {}) {
|
|
|
2648
2636
|
for (const file of files) {
|
|
2649
2637
|
let parsed;
|
|
2650
2638
|
try {
|
|
2651
|
-
parsed = parseFrontmatter(
|
|
2639
|
+
parsed = parseFrontmatter(readFileSync3(join3(PROMPTS_DIR, file), "utf8"));
|
|
2652
2640
|
} catch (e) {
|
|
2653
2641
|
logger.warn(`Skipping prompt ${file}: ${String(e)}`);
|
|
2654
2642
|
continue;
|
|
@@ -2734,7 +2722,17 @@ function createServer(opts = {}) {
|
|
|
2734
2722
|
process.title = `Mikrotik MCP Server v${VERSION}`;
|
|
2735
2723
|
const { names, default: defaultDevice } = listDevices();
|
|
2736
2724
|
const readOnly = getConfig().readOnly;
|
|
2737
|
-
|
|
2725
|
+
let instructions = names.length > 1 ? INSTRUCTIONS + MULTI_DEVICE_INSTRUCTIONS.replace("{{names}}", names.join(", ")).replace("{{default}}", defaultDevice) : INSTRUCTIONS;
|
|
2726
|
+
if (!getConfig().disableUpdateCheck) {
|
|
2727
|
+
const cached = loadFileCacheSync();
|
|
2728
|
+
if (cached) {
|
|
2729
|
+
const note = updateSummaryLine(cached);
|
|
2730
|
+
if (note)
|
|
2731
|
+
instructions += `
|
|
2732
|
+
|
|
2733
|
+
${note}`;
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2738
2736
|
const server = new McpServer({
|
|
2739
2737
|
name: SERVER_NAME,
|
|
2740
2738
|
version: VERSION,
|
|
@@ -2886,6 +2884,13 @@ async function runHttp(mcp) {
|
|
|
2886
2884
|
}
|
|
2887
2885
|
});
|
|
2888
2886
|
logger.info(`MCP server ready on http://${mcp.host}:${mcp.port}${mcpPath} \u2014 ${toolCount} tools, ${promptCount} prompts, ${uiViewCount} app views ` + `(${mcp.transport})${readOnly ? " [READ-ONLY]" : ""}`);
|
|
2887
|
+
if (!getConfig().disableUpdateCheck) {
|
|
2888
|
+
checkForUpdate().then((r) => {
|
|
2889
|
+
if (r.release?.isNewer) {
|
|
2890
|
+
logger.info(`[update] MikroTik MCP v${r.release.version} available (running v${VERSION}). ` + `Upgrade: bun i -g @usex/mikrotik-mcp@latest`);
|
|
2891
|
+
}
|
|
2892
|
+
}).catch(() => {});
|
|
2893
|
+
}
|
|
2889
2894
|
}
|
|
2890
2895
|
|
|
2891
2896
|
// src/transport/stdio.ts
|
|
@@ -2895,6 +2900,21 @@ async function runStdio() {
|
|
|
2895
2900
|
const transport = new StdioServerTransport;
|
|
2896
2901
|
await server.connect(transport);
|
|
2897
2902
|
logger.info(`MCP server ready on stdio \u2014 ${toolCount} tools, ${promptCount} prompts, ${uiViewCount} app views${readOnly ? " [READ-ONLY]" : ""}`);
|
|
2903
|
+
if (!getConfig().disableUpdateCheck) {
|
|
2904
|
+
whisperUpdate(server).catch(() => {});
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
async function whisperUpdate(server) {
|
|
2908
|
+
const result = await checkForUpdate();
|
|
2909
|
+
if (!result.release?.isNewer)
|
|
2910
|
+
return;
|
|
2911
|
+
const r = result.release;
|
|
2912
|
+
try {
|
|
2913
|
+
server.server.sendLoggingMessage({
|
|
2914
|
+
level: "info",
|
|
2915
|
+
data: `[MikroTik MCP] Update available: v${r.version} (running v${VERSION}). ` + `${r.name ? `"${r.name}" \u2014 ` : ""}` + `Call check_server_pulse for release notes, or upgrade: bun i -g @usex/mikrotik-mcp@latest`
|
|
2916
|
+
}).catch(() => {});
|
|
2917
|
+
} catch {}
|
|
2898
2918
|
}
|
|
2899
2919
|
|
|
2900
2920
|
// src/cli-logo.ts
|
package/dist/index.d.ts
CHANGED
|
@@ -136,6 +136,11 @@ interface ToolDef<Shape extends ZodRawShape> {
|
|
|
136
136
|
* view (it still returns `text` for non-UI hosts).
|
|
137
137
|
*/
|
|
138
138
|
ui?: UiLink;
|
|
139
|
+
/**
|
|
140
|
+
* When true, skip the multi-device `device` selector injection for this tool.
|
|
141
|
+
* Use for server-introspection tools that never contact a RouterOS device.
|
|
142
|
+
*/
|
|
143
|
+
noDevice?: boolean;
|
|
139
144
|
/** Handler returning the result shown to the model (text, or text + structured data). */
|
|
140
145
|
handler: (args: any, ctx: ToolContext) => Promise<HandlerOutput> | HandlerOutput;
|
|
141
146
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
DeviceConfigSchema,
|
|
4
|
+
LOGO_URL,
|
|
4
5
|
MikroTikSSHClient,
|
|
5
6
|
MikrotikConfigSchema,
|
|
6
|
-
PROJECT_ROOT,
|
|
7
7
|
PROMPTS_DIR,
|
|
8
|
+
SERVER_DESCRIPTION,
|
|
9
|
+
SERVER_NAME,
|
|
10
|
+
SERVER_TITLE,
|
|
8
11
|
SafeModeManager,
|
|
12
|
+
VERSION,
|
|
13
|
+
WEBSITE_URL,
|
|
9
14
|
allToolModules,
|
|
10
15
|
defineTool,
|
|
11
16
|
deviceDirectory,
|
|
@@ -16,13 +21,15 @@ import {
|
|
|
16
21
|
getSafeModeManager,
|
|
17
22
|
listDevices,
|
|
18
23
|
loadConfig,
|
|
24
|
+
loadFileCacheSync,
|
|
19
25
|
logger,
|
|
20
26
|
registerTools,
|
|
21
27
|
registerUiResources,
|
|
22
28
|
resolveDeviceName,
|
|
23
29
|
selectToolModules,
|
|
24
|
-
setConfig
|
|
25
|
-
|
|
30
|
+
setConfig,
|
|
31
|
+
updateSummaryLine
|
|
32
|
+
} from "./shared/library-21t1cncr.js";
|
|
26
33
|
// src/server.ts
|
|
27
34
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
28
35
|
import { ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
@@ -146,17 +153,6 @@ function registerPrompts(server, opts = {}) {
|
|
|
146
153
|
return count;
|
|
147
154
|
}
|
|
148
155
|
|
|
149
|
-
// src/version.ts
|
|
150
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
151
|
-
import { join as join2 } from "path";
|
|
152
|
-
var pkg = JSON.parse(readFileSync2(join2(PROJECT_ROOT, "package.json"), "utf-8"));
|
|
153
|
-
var VERSION = pkg.version ?? "0.0.0";
|
|
154
|
-
var WEBSITE_URL = pkg.homepage ?? "";
|
|
155
|
-
var LOGO_URL = pkg.logoIcon ?? "";
|
|
156
|
-
var SERVER_TITLE = "MikroTik MCP";
|
|
157
|
-
var SERVER_DESCRIPTION = pkg.description ?? "";
|
|
158
|
-
var SERVER_NAME = "mikrotik-mcp";
|
|
159
|
-
|
|
160
156
|
// src/server.ts
|
|
161
157
|
var INSTRUCTIONS = `MikroTik RouterOS management over SSH.
|
|
162
158
|
|
|
@@ -209,7 +205,17 @@ function createServer(opts = {}) {
|
|
|
209
205
|
process.title = `Mikrotik MCP Server v${VERSION}`;
|
|
210
206
|
const { names, default: defaultDevice } = listDevices();
|
|
211
207
|
const readOnly = getConfig().readOnly;
|
|
212
|
-
|
|
208
|
+
let instructions = names.length > 1 ? INSTRUCTIONS + MULTI_DEVICE_INSTRUCTIONS.replace("{{names}}", names.join(", ")).replace("{{default}}", defaultDevice) : INSTRUCTIONS;
|
|
209
|
+
if (!getConfig().disableUpdateCheck) {
|
|
210
|
+
const cached = loadFileCacheSync();
|
|
211
|
+
if (cached) {
|
|
212
|
+
const note = updateSummaryLine(cached);
|
|
213
|
+
if (note)
|
|
214
|
+
instructions += `
|
|
215
|
+
|
|
216
|
+
${note}`;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
213
219
|
const server = new McpServer({
|
|
214
220
|
name: SERVER_NAME,
|
|
215
221
|
version: VERSION,
|