@usex/mikrotik-mcp 4.17.0 → 4.18.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 CHANGED
@@ -81,6 +81,7 @@ import {
81
81
  moduleCatalog,
82
82
  normalizeExport,
83
83
  openSnapshotStore,
84
+ parseDisks,
84
85
  parseKeyValues,
85
86
  parseLeadingNumber,
86
87
  parseRecords,
@@ -122,7 +123,7 @@ import {
122
123
  updateAaaEntity,
123
124
  updateSummaryLine,
124
125
  writeBackup
125
- } from "./shared/cli-v75jtv6p.js";
126
+ } from "./shared/cli-dv2kmsh2.js";
126
127
 
127
128
  // src/cli.ts
128
129
  import { existsSync as existsSync2 } from "fs";
@@ -764,6 +765,9 @@ async function probeDevice(name, dc) {
764
765
  try {
765
766
  neighbors.set(name, parseNeighbors(await client.run("/ip neighbor print detail")));
766
767
  } catch {}
768
+ try {
769
+ status.disks = parseDisks(await client.run("/disk print detail"));
770
+ } catch {}
767
771
  }
768
772
  } catch (e) {
769
773
  status = {
package/dist/index.js CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  selectToolModules,
30
30
  setConfig,
31
31
  updateSummaryLine
32
- } from "./shared/library-qma8metz.js";
32
+ } from "./shared/library-7m2c1g1y.js";
33
33
  // src/server.ts
34
34
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
35
35
  import { ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
@@ -4,7 +4,7 @@ import {
4
4
  allToolModules,
5
5
  moduleCatalog,
6
6
  selectToolModules
7
- } from "./cli-v75jtv6p.js";
7
+ } from "./cli-dv2kmsh2.js";
8
8
  export {
9
9
  selectToolModules,
10
10
  moduleCatalog,
@@ -1802,9 +1802,16 @@ function parseFlagLegend(text) {
1802
1802
  }
1803
1803
  function parseKvTokens(chunk) {
1804
1804
  const out = {};
1805
- const re = /([A-Za-z][\w.-]*)=("(?:[^"\\]|\\.)*"|[^\s]*)/g;
1805
+ const re = /(\.?[A-Za-z][\w.-]*)=("(?:[^"\\]|\\.)*"|[^\s]*)/g;
1806
+ let prefix = "";
1806
1807
  for (const m of chunk.matchAll(re)) {
1807
- const key = m[1];
1808
+ let key = m[1];
1809
+ if (key.startsWith(".")) {
1810
+ key = prefix + key;
1811
+ } else {
1812
+ const dot = key.indexOf(".");
1813
+ prefix = dot > 0 ? key.slice(0, dot) : "";
1814
+ }
1808
1815
  let value = m[2];
1809
1816
  if (value.startsWith('"') && value.endsWith('"')) {
1810
1817
  value = value.slice(1, -1).replace(/\\(.)/g, "$1");
@@ -1984,6 +1991,33 @@ function parseSizeToBytes(value) {
1984
1991
  };
1985
1992
  return n * (factor[unit] ?? 1);
1986
1993
  }
1994
+ function parseDisks(text) {
1995
+ const collapsed = text.replace(/(\d) (?=\d)/g, "$1");
1996
+ const { rows } = parseRecords(collapsed);
1997
+ const disks = [];
1998
+ for (const r of rows) {
1999
+ const slot = r.slot ?? r.name ?? "";
2000
+ if (!slot)
2001
+ continue;
2002
+ if (/E/.test(r.flags ?? ""))
2003
+ continue;
2004
+ const size = parseLeadingNumber(r.size);
2005
+ if (size == null || size <= 0)
2006
+ continue;
2007
+ const free = parseLeadingNumber(r.free);
2008
+ const usePct = parseLeadingNumber(r.use);
2009
+ disks.push({
2010
+ slot,
2011
+ model: r.model,
2012
+ fs: r.fs,
2013
+ size,
2014
+ free: free ?? undefined,
2015
+ mountPoint: r["mount-point"],
2016
+ usedPct: usePct ?? (free != null && size > 0 ? Math.round((size - free) / size * 100) : undefined)
2017
+ });
2018
+ }
2019
+ return disks;
2020
+ }
1987
2021
 
1988
2022
  // src/core/ui-meta.ts
1989
2023
  var UI_META_KEY = "ui";
@@ -8995,7 +9029,7 @@ var cache = null;
8995
9029
  async function gateway() {
8996
9030
  if (cache)
8997
9031
  return cache;
8998
- const { moduleCatalog } = await import("./cli-1ftjz1jx.js");
9032
+ const { moduleCatalog } = await import("./cli-7jxnfmp0.js");
8999
9033
  const forIndex = [];
9000
9034
  const byName = new Map;
9001
9035
  for (const mod of moduleCatalog) {
@@ -31752,12 +31786,12 @@ function num2(v) {
31752
31786
  return Number.isFinite(n) ? n : undefined;
31753
31787
  }
31754
31788
  function bandFromRow(row) {
31755
- const b = (row.band ?? row["configuration.mode"] ?? "").toLowerCase();
31789
+ const b = (row["channel.band"] ?? row.band ?? row.bands ?? row["configuration.band"] ?? "").toLowerCase();
31756
31790
  if (b.includes("2ghz") || b.includes("2.4"))
31757
31791
  return "2ghz";
31758
31792
  if (b.includes("5ghz") || b.includes("5."))
31759
31793
  return "5ghz";
31760
- const ch = num2(row.channel ?? row.frequency ?? row["channel.frequency"]);
31794
+ const ch = num2(row["channel.frequency"] ?? row.channel ?? row.frequency);
31761
31795
  if (ch != null) {
31762
31796
  if (ch >= 5000 || ch >= 36 && ch <= 177)
31763
31797
  return "5ghz";
@@ -31767,7 +31801,7 @@ function bandFromRow(row) {
31767
31801
  return "unknown";
31768
31802
  }
31769
31803
  function channelOf(row) {
31770
- return num2(row.channel ?? row.frequency ?? row["channel.frequency"]);
31804
+ return num2(row["channel.frequency"] ?? row.channel ?? row.frequency);
31771
31805
  }
31772
31806
  function normalizeCapsmanState(raw) {
31773
31807
  if (!raw)
@@ -31778,9 +31812,12 @@ function normalizeCapsmanState(raw) {
31778
31812
  if (rid)
31779
31813
  clientsByRadio.set(rid, (clientsByRadio.get(rid) ?? 0) + 1);
31780
31814
  }
31781
- const radios = raw.radios.map((row) => {
31782
- const cap = row["remote-cap-identity"] ?? row.identity ?? row["cap-name"] ?? row.name ?? "?";
31783
- const radioId = row.interface ?? row.name ?? row["radio-mac"] ?? cap;
31815
+ const interfaceRows = raw.interfaces ?? [];
31816
+ const useInterfaces = interfaceRows.length > 0;
31817
+ const radioRows = useInterfaces ? interfaceRows : raw.radios;
31818
+ const radios = radioRows.map((row) => {
31819
+ const cap = useInterfaces ? row.name ?? row["radio-mac"] ?? "?" : row["remote-cap-identity"] ?? row.identity ?? row["cap-name"] ?? row.name ?? "?";
31820
+ const radioId = useInterfaces ? row.name ?? row["radio-mac"] ?? cap : row.interface ?? row.name ?? row["radio-mac"] ?? cap;
31784
31821
  const tag = parseFloorTag(`${cap} ${row.comment ?? ""}`);
31785
31822
  const res = raw.resources[cap] ?? {};
31786
31823
  return {
@@ -31788,7 +31825,7 @@ function normalizeCapsmanState(raw) {
31788
31825
  radioId,
31789
31826
  band: bandFromRow(row),
31790
31827
  channel: channelOf(row),
31791
- width: row.width ?? row["channel.width"],
31828
+ width: row["channel.width"] ?? row.width,
31792
31829
  txPower: num2(row["tx-power"] ?? row["tx-power-dbm"]),
31793
31830
  clientCount: clientsByRadio.get(radioId) ?? num2(row["registered-clients"]) ?? 0,
31794
31831
  floor: tag.floor,
@@ -31865,10 +31902,11 @@ async function fetchCapsmanState(ctx) {
31865
31902
  if (!path)
31866
31903
  return normalizeCapsmanState(null);
31867
31904
  const isCapsman = path === "/caps-man";
31868
- const [manager, remoteCaps, radios, registrations, securityConfigs, accessList] = await Promise.all([
31905
+ const [manager, remoteCaps, radios, interfaces, registrations, securityConfigs, accessList] = await Promise.all([
31869
31906
  fetchKv(isCapsman ? "/caps-man manager print" : `${path} capsman print`, ctx),
31870
31907
  fetchRows(isCapsman ? "/caps-man remote-cap print detail" : `${path} capsman remote-cap print detail`, ctx),
31871
31908
  fetchRows(isCapsman ? "/caps-man radio print detail" : `${path} radio print detail`, ctx),
31909
+ isCapsman ? Promise.resolve([]) : fetchRows(`${path} print detail`, ctx),
31872
31910
  fetchRows(isCapsman ? "/caps-man registration-table print detail" : `${path} registration-table print detail`, ctx),
31873
31911
  fetchRows(isCapsman ? "/caps-man security print detail" : `${path} security print detail`, ctx),
31874
31912
  fetchRows(isCapsman ? "/caps-man access-list print detail" : `${path} access-list print detail`, ctx)
@@ -31878,6 +31916,7 @@ async function fetchCapsmanState(ctx) {
31878
31916
  manager,
31879
31917
  remoteCaps,
31880
31918
  radios,
31919
+ interfaces,
31881
31920
  registrations,
31882
31921
  securityConfigs,
31883
31922
  accessList,
@@ -33266,4 +33305,4 @@ function selectToolModules(filter = {}, catalog = moduleCatalog) {
33266
33305
  }).map((m) => m.tools);
33267
33306
  }
33268
33307
 
33269
- export { __require, DEFAULT_SNAPSHOT_DB, DEFAULT_CONFIG_HISTORY_DIR, DeviceConfigSchema, ToolFilterSchema, MikrotikConfigSchema, getConfigSource, loadConfig, logger, setConfig, getConfig, listDevices, deviceLabels, resolveDeviceName, deviceDirectory, isMacTelnetDevice, createDeviceClient, describeTransport, isPoolEnabled, closeAll, poolStatus, getMemoryStore, closeMemoryStore, reopenMemoryStore, executeMikrotikCommand, createContext, Cmd, isEmpty, looksLikeError, commandUnsupported, parseKeyValues, parseRouterosDate, parseSize, parseSystemResource, parseRecords, parseLeadingNumber, riskOf, REDACTED, redact, configureRecorder, getEventStore, subscribe, subscriberCount, registerTools, fetchDevices, sampleDeviceTraffic, sampleAllTraffic, setDeviceLimits, blockDevice, allowDevice, makeDeviceStatic, setDeviceIp, setDeviceLabel, removeDeviceLease, devicesView, PROMPTS_DIR, UI_DIST_DIR, registerUiResources, backupDir, listBackups, readBackup, writeBackup, deleteBackup, renameBackup, createLocalBackup, restoreLocalBackup, isS3Configured, getS3Client, presignExpiresIn, s3Target, splitCommands, buildChangePlan, renderPlan, diffLines, normalizeExport, analyzeDrift, attributeChanges, openSnapshotStore, applyWritesSafely, captureSnapshot, DEFAULT_TZSP_PORT, capture2 as capture, AAA_ENTITIES, listAaaEntity, addAaaEntity, updateAaaEntity, removeAaaEntity, toggleAaaEntity, getRadiusIncoming, setRadiusIncoming, resetRadiusCounters, getUmSettings, setUmSettings, VERSION, WEBSITE_URL, LOGO_URL, SERVER_TITLE, SERVER_DESCRIPTION, SERVER_NAME, PKG_META, loadFileCacheSync, fetchLatestRelease, checkForUpdate, updateSummaryLine, fetchAllReleases, buildChannelPlanCommands, reportWeakClients, runCapsmanAudit, steerAlreadyPresent, buildSteerCommands, loadBalancePlan, buildLoadBalanceCommands, buildFtCommands, buildHaCommands, haGuidance, capsmanOverview, fetchCapsmanState, moduleCatalog, allToolModules, ALWAYS_ON_MODULES, selectToolModules };
33308
+ export { __require, DEFAULT_SNAPSHOT_DB, DEFAULT_CONFIG_HISTORY_DIR, DeviceConfigSchema, ToolFilterSchema, MikrotikConfigSchema, getConfigSource, loadConfig, logger, setConfig, getConfig, listDevices, deviceLabels, resolveDeviceName, deviceDirectory, isMacTelnetDevice, createDeviceClient, describeTransport, isPoolEnabled, closeAll, poolStatus, getMemoryStore, closeMemoryStore, reopenMemoryStore, executeMikrotikCommand, createContext, Cmd, isEmpty, looksLikeError, commandUnsupported, parseKeyValues, parseRouterosDate, parseSize, parseSystemResource, parseRecords, parseLeadingNumber, parseDisks, riskOf, REDACTED, redact, configureRecorder, getEventStore, subscribe, subscriberCount, registerTools, fetchDevices, sampleDeviceTraffic, sampleAllTraffic, setDeviceLimits, blockDevice, allowDevice, makeDeviceStatic, setDeviceIp, setDeviceLabel, removeDeviceLease, devicesView, PROMPTS_DIR, UI_DIST_DIR, registerUiResources, backupDir, listBackups, readBackup, writeBackup, deleteBackup, renameBackup, createLocalBackup, restoreLocalBackup, isS3Configured, getS3Client, presignExpiresIn, s3Target, splitCommands, buildChangePlan, renderPlan, diffLines, normalizeExport, analyzeDrift, attributeChanges, openSnapshotStore, applyWritesSafely, captureSnapshot, DEFAULT_TZSP_PORT, capture2 as capture, AAA_ENTITIES, listAaaEntity, addAaaEntity, updateAaaEntity, removeAaaEntity, toggleAaaEntity, getRadiusIncoming, setRadiusIncoming, resetRadiusCounters, getUmSettings, setUmSettings, VERSION, WEBSITE_URL, LOGO_URL, SERVER_TITLE, SERVER_DESCRIPTION, SERVER_NAME, PKG_META, loadFileCacheSync, fetchLatestRelease, checkForUpdate, updateSummaryLine, fetchAllReleases, buildChannelPlanCommands, reportWeakClients, runCapsmanAudit, steerAlreadyPresent, buildSteerCommands, loadBalancePlan, buildLoadBalanceCommands, buildFtCommands, buildHaCommands, haGuidance, capsmanOverview, fetchCapsmanState, moduleCatalog, allToolModules, ALWAYS_ON_MODULES, selectToolModules };
@@ -4,7 +4,7 @@ import {
4
4
  allToolModules,
5
5
  moduleCatalog,
6
6
  selectToolModules
7
- } from "./library-qma8metz.js";
7
+ } from "./library-7m2c1g1y.js";
8
8
  export {
9
9
  selectToolModules,
10
10
  moduleCatalog,
@@ -1783,9 +1783,16 @@ function parseFlagLegend(text) {
1783
1783
  }
1784
1784
  function parseKvTokens(chunk) {
1785
1785
  const out = {};
1786
- const re = /([A-Za-z][\w.-]*)=("(?:[^"\\]|\\.)*"|[^\s]*)/g;
1786
+ const re = /(\.?[A-Za-z][\w.-]*)=("(?:[^"\\]|\\.)*"|[^\s]*)/g;
1787
+ let prefix = "";
1787
1788
  for (const m of chunk.matchAll(re)) {
1788
- const key = m[1];
1789
+ let key = m[1];
1790
+ if (key.startsWith(".")) {
1791
+ key = prefix + key;
1792
+ } else {
1793
+ const dot = key.indexOf(".");
1794
+ prefix = dot > 0 ? key.slice(0, dot) : "";
1795
+ }
1789
1796
  let value = m[2];
1790
1797
  if (value.startsWith('"') && value.endsWith('"')) {
1791
1798
  value = value.slice(1, -1).replace(/\\(.)/g, "$1");
@@ -8804,7 +8811,7 @@ var cache = null;
8804
8811
  async function gateway() {
8805
8812
  if (cache)
8806
8813
  return cache;
8807
- const { moduleCatalog } = await import("./library-ydfn3v4j.js");
8814
+ const { moduleCatalog } = await import("./library-77r1j24d.js");
8808
8815
  const forIndex = [];
8809
8816
  const byName = new Map;
8810
8817
  for (const mod of moduleCatalog) {
@@ -31482,12 +31489,12 @@ function num2(v) {
31482
31489
  return Number.isFinite(n) ? n : undefined;
31483
31490
  }
31484
31491
  function bandFromRow(row) {
31485
- const b = (row.band ?? row["configuration.mode"] ?? "").toLowerCase();
31492
+ const b = (row["channel.band"] ?? row.band ?? row.bands ?? row["configuration.band"] ?? "").toLowerCase();
31486
31493
  if (b.includes("2ghz") || b.includes("2.4"))
31487
31494
  return "2ghz";
31488
31495
  if (b.includes("5ghz") || b.includes("5."))
31489
31496
  return "5ghz";
31490
- const ch = num2(row.channel ?? row.frequency ?? row["channel.frequency"]);
31497
+ const ch = num2(row["channel.frequency"] ?? row.channel ?? row.frequency);
31491
31498
  if (ch != null) {
31492
31499
  if (ch >= 5000 || ch >= 36 && ch <= 177)
31493
31500
  return "5ghz";
@@ -31497,7 +31504,7 @@ function bandFromRow(row) {
31497
31504
  return "unknown";
31498
31505
  }
31499
31506
  function channelOf(row) {
31500
- return num2(row.channel ?? row.frequency ?? row["channel.frequency"]);
31507
+ return num2(row["channel.frequency"] ?? row.channel ?? row.frequency);
31501
31508
  }
31502
31509
  function normalizeCapsmanState(raw) {
31503
31510
  if (!raw)
@@ -31508,9 +31515,12 @@ function normalizeCapsmanState(raw) {
31508
31515
  if (rid)
31509
31516
  clientsByRadio.set(rid, (clientsByRadio.get(rid) ?? 0) + 1);
31510
31517
  }
31511
- const radios = raw.radios.map((row) => {
31512
- const cap = row["remote-cap-identity"] ?? row.identity ?? row["cap-name"] ?? row.name ?? "?";
31513
- const radioId = row.interface ?? row.name ?? row["radio-mac"] ?? cap;
31518
+ const interfaceRows = raw.interfaces ?? [];
31519
+ const useInterfaces = interfaceRows.length > 0;
31520
+ const radioRows = useInterfaces ? interfaceRows : raw.radios;
31521
+ const radios = radioRows.map((row) => {
31522
+ const cap = useInterfaces ? row.name ?? row["radio-mac"] ?? "?" : row["remote-cap-identity"] ?? row.identity ?? row["cap-name"] ?? row.name ?? "?";
31523
+ const radioId = useInterfaces ? row.name ?? row["radio-mac"] ?? cap : row.interface ?? row.name ?? row["radio-mac"] ?? cap;
31514
31524
  const tag = parseFloorTag(`${cap} ${row.comment ?? ""}`);
31515
31525
  const res = raw.resources[cap] ?? {};
31516
31526
  return {
@@ -31518,7 +31528,7 @@ function normalizeCapsmanState(raw) {
31518
31528
  radioId,
31519
31529
  band: bandFromRow(row),
31520
31530
  channel: channelOf(row),
31521
- width: row.width ?? row["channel.width"],
31531
+ width: row["channel.width"] ?? row.width,
31522
31532
  txPower: num2(row["tx-power"] ?? row["tx-power-dbm"]),
31523
31533
  clientCount: clientsByRadio.get(radioId) ?? num2(row["registered-clients"]) ?? 0,
31524
31534
  floor: tag.floor,
@@ -31595,10 +31605,11 @@ async function fetchCapsmanState(ctx) {
31595
31605
  if (!path)
31596
31606
  return normalizeCapsmanState(null);
31597
31607
  const isCapsman = path === "/caps-man";
31598
- const [manager, remoteCaps, radios, registrations, securityConfigs, accessList] = await Promise.all([
31608
+ const [manager, remoteCaps, radios, interfaces, registrations, securityConfigs, accessList] = await Promise.all([
31599
31609
  fetchKv(isCapsman ? "/caps-man manager print" : `${path} capsman print`, ctx),
31600
31610
  fetchRows(isCapsman ? "/caps-man remote-cap print detail" : `${path} capsman remote-cap print detail`, ctx),
31601
31611
  fetchRows(isCapsman ? "/caps-man radio print detail" : `${path} radio print detail`, ctx),
31612
+ isCapsman ? Promise.resolve([]) : fetchRows(`${path} print detail`, ctx),
31602
31613
  fetchRows(isCapsman ? "/caps-man registration-table print detail" : `${path} registration-table print detail`, ctx),
31603
31614
  fetchRows(isCapsman ? "/caps-man security print detail" : `${path} security print detail`, ctx),
31604
31615
  fetchRows(isCapsman ? "/caps-man access-list print detail" : `${path} access-list print detail`, ctx)
@@ -31608,6 +31619,7 @@ async function fetchCapsmanState(ctx) {
31608
31619
  manager,
31609
31620
  remoteCaps,
31610
31621
  radios,
31622
+ interfaces,
31611
31623
  registrations,
31612
31624
  securityConfigs,
31613
31625
  accessList,