mikromcp 1.0.2 → 1.0.3

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/main.js +42 -35
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  [![CI](https://github.com/AliKarami/MikroMCP/actions/workflows/ci.yml/badge.svg)](https://github.com/AliKarami/MikroMCP/actions/workflows/ci.yml)
14
14
  [![Release](https://github.com/AliKarami/MikroMCP/actions/workflows/release.yml/badge.svg)](https://github.com/AliKarami/MikroMCP/actions/workflows/release.yml)
15
- [![Version](https://img.shields.io/badge/version-v1.0.2-EA580C)](package.json)
15
+ [![Version](https://img.shields.io/badge/version-v1.0.3-EA580C)](package.json)
16
16
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
17
17
  [![Node.js >= 22](https://img.shields.io/badge/node-%3E%3D22-339933)](package.json)
18
18
  [![RouterOS 7.x](https://img.shields.io/badge/RouterOS-7.x-293239)](https://help.mikrotik.com/docs/display/ROS/REST+API)
package/dist/main.js CHANGED
@@ -2,28 +2,33 @@
2
2
 
3
3
  // src/main.ts
4
4
  import { config as loadDotenv } from "dotenv";
5
- import { join as join3 } from "path";
6
- import { homedir as homedir3 } from "os";
5
+ import { join as join5 } from "path";
6
+ import { homedir as homedir5 } from "os";
7
7
 
8
8
  // src/cli/index.ts
9
9
  import { Command } from "commander";
10
10
 
11
11
  // src/config/app-config.ts
12
+ import { join } from "path";
13
+ import { homedir } from "os";
14
+ function mikromcpDir() {
15
+ return join(homedir(), ".mikromcp");
16
+ }
12
17
  function loadAppConfig() {
13
18
  const env = process.env;
14
- const dataDir = env.MIKROMCP_DATA_DIR ?? "data";
19
+ const dataDir = env.MIKROMCP_DATA_DIR ?? join(mikromcpDir(), "data");
15
20
  return {
16
21
  transport: env.MIKROMCP_TRANSPORT === "http" ? "http" : "stdio",
17
22
  port: parseInt(env.MIKROMCP_PORT ?? "3000", 10),
18
23
  bindHost: env.MIKROMCP_BIND_HOST ?? "127.0.0.1",
19
24
  logLevel: env.MIKROMCP_LOG_LEVEL ?? "info",
20
- configPath: env.MIKROMCP_CONFIG_PATH ?? "config/routers.yaml",
25
+ configPath: env.MIKROMCP_CONFIG_PATH ?? join(mikromcpDir(), "routers.yaml"),
21
26
  dataDir,
22
27
  snapshotDir: `${dataDir}/snapshots`,
23
28
  journalPath: `${dataDir}/write-journal.ndjson`,
24
29
  cmdAllow: (env.MIKROMCP_CMD_ALLOW ?? "").split(",").map((s) => s.trim()).filter(Boolean),
25
30
  cmdDeny: (env.MIKROMCP_CMD_DENY ?? "").split(",").map((s) => s.trim()).filter(Boolean),
26
- identitiesPath: env.MIKROMCP_IDENTITIES_PATH ?? "config/identities.yaml",
31
+ identitiesPath: env.MIKROMCP_IDENTITIES_PATH ?? join(mikromcpDir(), "identities.yaml"),
27
32
  stdioIdentity: env.MIKROMCP_STDIO_IDENTITY || void 0,
28
33
  confirmationSecret: env.MIKROMCP_CONFIRMATION_SECRET || void 0,
29
34
  auditLogPath: env.MIKROMCP_AUDIT_LOG_PATH || void 0,
@@ -4900,10 +4905,12 @@ var containerTools = [listContainersTool, manageContainerTool];
4900
4905
  // src/domain/tools/change-management-tools.ts
4901
4906
  import { z as z23 } from "zod";
4902
4907
  import { readFileSync as readFileSync2 } from "fs";
4908
+ import { join as join3 } from "path";
4909
+ import { homedir as homedir2 } from "os";
4903
4910
 
4904
4911
  // src/domain/snapshot/snapshot-engine.ts
4905
4912
  import { mkdirSync, writeFileSync, readFileSync } from "fs";
4906
- import { join } from "path";
4913
+ import { join as join2 } from "path";
4907
4914
  import { nanoid } from "nanoid";
4908
4915
  function pathToSlug(rosPath) {
4909
4916
  return rosPath.replace(/\//g, "-");
@@ -4914,8 +4921,8 @@ function timestampPrefix() {
4914
4921
  async function takeSnapshot(client, routerId, path, snapshotDir) {
4915
4922
  const records = await client.get(path, {});
4916
4923
  const id = `${timestampPrefix()}-${pathToSlug(path)}-${nanoid(6)}`;
4917
- const dir = join(snapshotDir, routerId);
4918
- const filePath = join(dir, `${id}.json`);
4924
+ const dir = join2(snapshotDir, routerId);
4925
+ const filePath = join2(dir, `${id}.json`);
4919
4926
  const ts = (/* @__PURE__ */ new Date()).toISOString();
4920
4927
  mkdirSync(dir, { recursive: true });
4921
4928
  const stored = { id, routerId, path, ts, records };
@@ -5177,7 +5184,7 @@ function createChangeManagementTools(baseTools2) {
5177
5184
  async handler(params, context) {
5178
5185
  const parsed = applyPlanInputSchema.parse(params);
5179
5186
  log24.info({ routerId: context.routerId, stepCount: parsed.steps.length }, "Applying plan");
5180
- const dataDir = process.env.MIKROMCP_DATA_DIR ?? "data";
5187
+ const dataDir = process.env.MIKROMCP_DATA_DIR ?? join3(homedir2(), ".mikromcp", "data");
5181
5188
  const journalPath = `${dataDir}/write-journal.ndjson`;
5182
5189
  const snapshotDir = `${dataDir}/snapshots`;
5183
5190
  const results2 = [];
@@ -5271,7 +5278,7 @@ function createChangeManagementTools(baseTools2) {
5271
5278
  },
5272
5279
  async handler(params, context) {
5273
5280
  const parsed = rollbackChangeInputSchema.parse(params);
5274
- const dataDir = process.env.MIKROMCP_DATA_DIR ?? "data";
5281
+ const dataDir = process.env.MIKROMCP_DATA_DIR ?? join3(homedir2(), ".mikromcp", "data");
5275
5282
  const journalPath = `${dataDir}/write-journal.ndjson`;
5276
5283
  const snapshotDir = `${dataDir}/snapshots`;
5277
5284
  log24.info({ routerId: context.routerId, journalId: parsed.journalId }, "Rolling back change");
@@ -7935,7 +7942,7 @@ function getStdioIdentity(stdioIdentityName, registry) {
7935
7942
  details: { stdioIdentityName },
7936
7943
  recoverability: {
7937
7944
  retryable: false,
7938
- suggestedAction: `Add an identity named "${stdioIdentityName}" to config/identities.yaml or unset MIKROMCP_STDIO_IDENTITY.`
7945
+ suggestedAction: `Add an identity named "${stdioIdentityName}" to ~/.mikromcp/identities.yaml or unset MIKROMCP_STDIO_IDENTITY.`
7939
7946
  }
7940
7947
  });
7941
7948
  }
@@ -8606,7 +8613,7 @@ function createServerFactory(config, identityRegistry) {
8606
8613
  const makeServer = () => {
8607
8614
  const server = new McpServer({
8608
8615
  name: "mikromcp",
8609
- version: "1.0.2"
8616
+ version: "1.0.3"
8610
8617
  });
8611
8618
  registerAllTools(server, registry, pool, circuitBreakers, config, identityRegistry);
8612
8619
  return server;
@@ -8926,10 +8933,10 @@ async function runServe() {
8926
8933
 
8927
8934
  // src/cli/doctor.ts
8928
8935
  import { existsSync as existsSync3, readFileSync as readFileSync6 } from "fs";
8929
- import { homedir } from "os";
8936
+ import { homedir as homedir3 } from "os";
8930
8937
  import * as net from "net";
8931
8938
  import chalk from "chalk";
8932
- var localVersion = "1.0.2";
8939
+ var localVersion = "1.0.3";
8933
8940
  var results = [];
8934
8941
  function ok(msg) {
8935
8942
  console.log(chalk.green("\u2705 ") + msg);
@@ -9085,7 +9092,7 @@ async function checkRouter(router) {
9085
9092
  }
9086
9093
  }
9087
9094
  function checkIdentities(identitiesPath, transport2) {
9088
- if (!process.env.MIKROMCP_IDENTITIES_PATH && identitiesPath === "config/identities.yaml") {
9095
+ if (!process.env.MIKROMCP_IDENTITIES_PATH && identitiesPath.endsWith(".mikromcp/identities.yaml")) {
9089
9096
  if (!existsSync3(identitiesPath)) {
9090
9097
  return;
9091
9098
  }
@@ -9109,8 +9116,8 @@ function checkIdentities(identitiesPath, transport2) {
9109
9116
  }
9110
9117
  function checkClaudeDesktop() {
9111
9118
  const candidatePaths = [
9112
- `${homedir()}/Library/Application Support/Claude/claude_desktop_config.json`,
9113
- `${homedir()}/.config/Claude/claude_desktop_config.json`
9119
+ `${homedir3()}/Library/Application Support/Claude/claude_desktop_config.json`,
9120
+ `${homedir3()}/.config/Claude/claude_desktop_config.json`
9114
9121
  ];
9115
9122
  const configPath = candidatePaths.find((p) => existsSync3(p));
9116
9123
  if (!configPath) {
@@ -9208,16 +9215,16 @@ import {
9208
9215
  mkdirSync as mkdirSync3,
9209
9216
  copyFileSync
9210
9217
  } from "fs";
9211
- import { homedir as homedir2 } from "os";
9212
- import { join as join2 } from "path";
9218
+ import { homedir as homedir4 } from "os";
9219
+ import { join as join4 } from "path";
9213
9220
  import { stringify as yamlStringify, parse as yamlParse } from "yaml";
9214
9221
  import bcrypt2 from "bcryptjs";
9215
9222
  import chalk2 from "chalk";
9216
- function mikromcpDir() {
9217
- return join2(homedir2(), ".mikromcp");
9223
+ function mikromcpDir2() {
9224
+ return join4(homedir4(), ".mikromcp");
9218
9225
  }
9219
9226
  function defaultAuditLogPath() {
9220
- return join2(mikromcpDir(), "audit.ndjson");
9227
+ return join4(mikromcpDir2(), "audit.ndjson");
9221
9228
  }
9222
9229
  function suggestEnvPrefix(routerId) {
9223
9230
  return "ROUTER_" + routerId.toUpperCase().replace(/-/g, "_");
@@ -9231,8 +9238,8 @@ function splitTags(val) {
9231
9238
  }
9232
9239
  function findClaudeDesktopConfig() {
9233
9240
  const candidates = [
9234
- join2(homedir2(), "Library", "Application Support", "Claude", "claude_desktop_config.json"),
9235
- join2(homedir2(), ".config", "Claude", "claude_desktop_config.json")
9241
+ join4(homedir4(), "Library", "Application Support", "Claude", "claude_desktop_config.json"),
9242
+ join4(homedir4(), ".config", "Claude", "claude_desktop_config.json")
9236
9243
  ];
9237
9244
  return candidates.find((p) => existsSync4(p)) ?? null;
9238
9245
  }
@@ -9354,7 +9361,7 @@ async function collectClaudeDesktopPreference() {
9354
9361
  return confirm({ message: "Register with Claude Desktop?", default: true });
9355
9362
  }
9356
9363
  function writeRoutersYaml(data) {
9357
- const filePath = join2(data.configDir, "routers.yaml");
9364
+ const filePath = join4(data.configDir, "routers.yaml");
9358
9365
  const newEntry = {
9359
9366
  host: data.host,
9360
9367
  port: data.port,
@@ -9381,7 +9388,7 @@ function writeRoutersYaml(data) {
9381
9388
  return true;
9382
9389
  }
9383
9390
  function writeIdentitiesYaml(data) {
9384
- const filePath = join2(data.configDir, "identities.yaml");
9391
+ const filePath = join4(data.configDir, "identities.yaml");
9385
9392
  const newEntry = {
9386
9393
  token: data.tokenHash,
9387
9394
  role: data.role,
@@ -9416,8 +9423,8 @@ function writeDotEnv(data) {
9416
9423
  `MIKROMCP_TRANSPORT=${transport2}`,
9417
9424
  "",
9418
9425
  "# \u2500\u2500 Config paths \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
9419
- `MIKROMCP_CONFIG_PATH=${join2(data.configDir, "routers.yaml")}`,
9420
- `MIKROMCP_IDENTITIES_PATH=${join2(data.configDir, "identities.yaml")}`,
9426
+ `MIKROMCP_CONFIG_PATH=${join4(data.configDir, "routers.yaml")}`,
9427
+ `MIKROMCP_IDENTITIES_PATH=${join4(data.configDir, "identities.yaml")}`,
9421
9428
  "",
9422
9429
  "# \u2500\u2500 Logging \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
9423
9430
  "# Levels: trace | debug | info | warn | error",
@@ -9477,11 +9484,11 @@ async function runInit() {
9477
9484
  console.log(chalk2.bold.cyan("\n\u{1F527} MikroMCP \u2014 Interactive Setup Wizard\n"));
9478
9485
  const routerInfo = await collectRouterInfo();
9479
9486
  const identityInfo = await collectIdentityInfo();
9480
- const configDir = mikromcpDir();
9481
- const envPath = join2(configDir, ".env");
9487
+ const configDir = mikromcpDir2();
9488
+ const envPath = join4(configDir, ".env");
9482
9489
  const writeEnv = await collectEnvPreference();
9483
9490
  let writeRouters = true;
9484
- const routersYamlPath = join2(configDir, "routers.yaml");
9491
+ const routersYamlPath = join4(configDir, "routers.yaml");
9485
9492
  if (existsSync4(routersYamlPath)) {
9486
9493
  console.log(chalk2.bold("\n\u2500\u2500 Config files \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
9487
9494
  writeRouters = await confirm({
@@ -9505,12 +9512,12 @@ async function runInit() {
9505
9512
  if (data.writeRoutersYaml) {
9506
9513
  writeRoutersYaml(data);
9507
9514
  summary.push(`routers.yaml written to ${data.configDir}`);
9508
- console.log(chalk2.green(` \u2714 ${join2(data.configDir, "routers.yaml")}`));
9515
+ console.log(chalk2.green(` \u2714 ${join4(data.configDir, "routers.yaml")}`));
9509
9516
  }
9510
9517
  if (data.writeIdentitiesYaml) {
9511
9518
  writeIdentitiesYaml(data);
9512
9519
  summary.push(`identities.yaml written to ${data.configDir}`);
9513
- console.log(chalk2.green(` \u2714 ${join2(data.configDir, "identities.yaml")}`));
9520
+ console.log(chalk2.green(` \u2714 ${join4(data.configDir, "identities.yaml")}`));
9514
9521
  }
9515
9522
  if (data.writeEnv) {
9516
9523
  writeDotEnv(data);
@@ -9543,12 +9550,12 @@ async function runInit() {
9543
9550
  }
9544
9551
 
9545
9552
  // src/cli/index.ts
9546
- var program = new Command().name("mikromcp").description("MikroTik RouterOS MCP server").version("1.0.2");
9553
+ var program = new Command().name("mikromcp").description("MikroTik RouterOS MCP server").version("1.0.3");
9547
9554
  program.command("serve", { isDefault: true }).description("Start the MCP server (default)").action(runServe);
9548
9555
  program.command("doctor").description("Check config, connectivity, and permissions").action(runDoctor);
9549
9556
  program.command("init").description("Interactive setup wizard").action(runInit);
9550
9557
 
9551
9558
  // src/main.ts
9552
- loadDotenv({ path: join3(homedir3(), ".mikromcp", ".env"), override: false });
9559
+ loadDotenv({ path: join5(homedir5(), ".mikromcp", ".env"), override: false });
9553
9560
  program.parse();
9554
9561
  //# sourceMappingURL=main.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mikromcp",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Production-grade MCP server for MikroTik RouterOS",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",