mikromcp 1.0.3 → 1.0.5

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 +136 -132
  2. package/dist/main.js +43 -14
  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.3-EA580C)](package.json)
15
+ [![Version](https://img.shields.io/badge/version-v1.0.5-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)
@@ -37,8 +37,6 @@ MikroMCP exists because raw router CLI access is the wrong abstraction for AI ag
37
37
  | Raw network access for every assistant | RBAC identities, bearer tokens for HTTP mode, tool allowlists, and audit trails |
38
38
  | Fragile troubleshooting workflows | Router-originated ping, traceroute, torch, logs, interfaces, DHCP, firewall, routes, WiFi, WireGuard, and more |
39
39
 
40
- MikroMCP is especially useful when you want AI agents to help with network operations without giving them unchecked terminal access.
41
-
42
40
  ---
43
41
 
44
42
  ## Feature Showcase
@@ -56,8 +54,6 @@ MikroMCP is especially useful when you want AI agents to help with network opera
56
54
  | 🤖 **AI-agent fit** | Human-readable responses plus structured JSON content for reasoning, chaining, and automation |
57
55
  | 🧩 **MCP compatibility** | stdio for desktop clients, Streamable HTTP and legacy SSE for remote or service-style clients |
58
56
 
59
- **Best-in-class strengths:** MikroMCP is not just a thin REST wrapper. It models operational safety around RouterOS: typed tool contracts, safe write patterns, router-aware credentials, destructive-action gates, and rollback-oriented workflows.
60
-
61
57
  ---
62
58
 
63
59
  ## Demo
@@ -78,10 +74,9 @@ MikroMCP is especially useful when you want AI agents to help with network opera
78
74
 
79
75
  ### Prerequisites
80
76
 
81
- - Node.js 22 or newer
77
+ - Node.js 22 or newer (for npm install) — or use a standalone binary below
82
78
  - MikroTik RouterOS 7.x with the REST API enabled
83
- - A RouterOS user with the policies required by the tools you plan to use
84
- - Git and npm
79
+ - A RouterOS user with the policies your tools require
85
80
 
86
81
  Recommended RouterOS policies for full tool coverage:
87
82
 
@@ -89,29 +84,65 @@ Recommended RouterOS policies for full tool coverage:
89
84
  read, write, api, rest-api, test, ssh, sniff, ftp
90
85
  ```
91
86
 
92
- Notes:
87
+ > `ssh` is required for `ping`, `traceroute`, `torch`, and `run_command`. `sniff` is required by `torch`. `ftp` is required only for `upload_file`.
88
+
89
+ ---
90
+
91
+ ### Install
92
+
93
+ **npm (recommended)**
94
+
95
+ ```bash
96
+ npm install -g mikromcp
97
+ ```
98
+
99
+ **Standalone binaries**
93
100
 
94
- - `ssh` is required for `ping`, `traceroute`, `torch`, and `run_command`.
95
- - `sniff` is required by `torch`.
96
- - `ftp` is required only for `upload_file`.
101
+ Download the binary for your platform from the [latest GitHub release](https://github.com/AliKarami/MikroMCP/releases/latest) — no Node.js required.
97
102
 
98
- ### Install Locally
103
+ **Docker**
99
104
 
100
105
  ```bash
101
- git clone https://github.com/AliKarami/MikroMCP.git
102
- cd MikroMCP
103
- npm install
104
- npm run build
105
- cp config/routers.example.yaml config/routers.yaml
106
- cp config/identities.example.yaml config/identities.yaml
106
+ docker pull ghcr.io/alikarami/mikromcp:latest
107
+ ```
108
+
109
+ ---
110
+
111
+ ### Set Up With the Init Wizard
112
+
113
+ Run the interactive setup wizard:
114
+
115
+ ```bash
116
+ mikromcp init
107
117
  ```
108
118
 
109
- Edit `config/routers.yaml`:
119
+ The wizard will ask for your router details and write everything to `~/.mikromcp/`:
120
+
121
+ ```
122
+ ~/.mikromcp/
123
+ ├── routers.yaml # router registry
124
+ ├── identities.yaml # RBAC identities (HTTP mode)
125
+ └── .env # credentials and runtime settings
126
+ ```
127
+
128
+ `~/.mikromcp/.env` is loaded automatically every time MikroMCP starts — no shell exports or Claude Desktop `env` blocks needed. Fill in the credentials it generates:
129
+
130
+ ```bash
131
+ # ~/.mikromcp/.env (generated by mikromcp init)
132
+ ROUTER_CORE01_USER=
133
+ ROUTER_CORE01_PASS=
134
+ ```
135
+
136
+ To edit your router registry directly:
137
+
138
+ ```bash
139
+ nano ~/.mikromcp/routers.yaml
140
+ ```
110
141
 
111
142
  ```yaml
112
143
  routers:
113
144
  core-01:
114
- host: "10.0.0.1"
145
+ host: "192.168.88.1"
115
146
  port: 443
116
147
  tls:
117
148
  enabled: true
@@ -119,59 +150,34 @@ routers:
119
150
  credentials:
120
151
  source: "env"
121
152
  envPrefix: "ROUTER_CORE01"
122
- tags: ["core", "production"]
123
- rosVersion: "7.14"
153
+ tags: ["core"]
154
+ rosVersion: "7"
124
155
  ```
125
156
 
126
- Provide router credentials through environment variables:
127
-
128
- ```bash
129
- export ROUTER_CORE01_USER="mcp-api"
130
- export ROUTER_CORE01_PASS="your-router-password"
131
- npm start
132
- ```
133
-
134
- ### Docker
157
+ ---
135
158
 
136
- #### Pull and run
159
+ ### Verify With Doctor
137
160
 
138
161
  ```bash
139
- docker pull ghcr.io/alikarami/mikromcp:latest
162
+ mikromcp doctor
140
163
  ```
141
164
 
142
- One-liner with environment variables:
165
+ Doctor checks Node version, config files, router reachability, Claude Desktop registration, and whether a newer version is available.
143
166
 
144
- ```bash
145
- docker run --rm \
146
- -e MIKROMCP_TRANSPORT=http \
147
- -e MIKROMCP_PORT=3000 \
148
- -e MIKROMCP_CONFIRMATION_SECRET="$(openssl rand -hex 32)" \
149
- -e ROUTER_CORE01_USER=mcp-api \
150
- -e ROUTER_CORE01_PASS=your-router-password \
151
- -v "$(pwd)/config:/app/config:ro" \
152
- -p 3000:3000 \
153
- ghcr.io/alikarami/mikromcp:latest
154
- ```
167
+ ---
155
168
 
156
- #### Docker Compose
169
+ ### Run
157
170
 
158
- Copy the example file and fill in your `.env`:
171
+ **stdio (for Claude Desktop and other desktop MCP clients)**
159
172
 
160
173
  ```bash
161
- cp docker-compose.example.yml docker-compose.yml
162
- cp config/routers.example.yaml config/routers.yaml
163
- cp config/identities.example.yaml config/identities.yaml
164
- # edit config/routers.yaml and set MIKROMCP_CONFIRMATION_SECRET + router credentials in .env
165
- docker compose up -d
174
+ mikromcp serve
166
175
  ```
167
176
 
168
- See `docker-compose.example.yml` for the full service definition.
169
-
170
- #### Build from source
177
+ **HTTP mode (for service deployments)**
171
178
 
172
179
  ```bash
173
- docker build -t mikromcp .
174
- docker run --rm -e MIKROMCP_TRANSPORT=http -p 3000:3000 mikromcp
180
+ MIKROMCP_TRANSPORT=http mikromcp serve
175
181
  ```
176
182
 
177
183
  ---
@@ -180,25 +186,22 @@ docker run --rm -e MIKROMCP_TRANSPORT=http -p 3000:3000 mikromcp
180
186
 
181
187
  ### Claude Desktop
182
188
 
183
- Add MikroMCP to `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS:
189
+ Run `mikromcp init` and choose **Register with Claude Desktop** — it patches `claude_desktop_config.json` automatically.
190
+
191
+ Or add it manually to `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS:
184
192
 
185
193
  ```json
186
194
  {
187
195
  "mcpServers": {
188
- "mikrotik": {
189
- "command": "node",
190
- "args": ["/absolute/path/to/MikroMCP/dist/main.js"],
191
- "env": {
192
- "MIKROMCP_CONFIG_PATH": "/absolute/path/to/MikroMCP/config/routers.yaml",
193
- "ROUTER_CORE01_USER": "mcp-api",
194
- "ROUTER_CORE01_PASS": "your-router-password"
195
- }
196
+ "mikromcp": {
197
+ "command": "mikromcp",
198
+ "args": ["serve"]
196
199
  }
197
200
  }
198
201
  }
199
202
  ```
200
203
 
201
- Restart Claude Desktop, then ask:
204
+ No `env` block needed — credentials are loaded from `~/.mikromcp/.env` at startup. Restart Claude Desktop, then ask:
202
205
 
203
206
  ```text
204
207
  Use MikroMCP to show CPU, memory, uptime, active interfaces, and warning logs for core-01.
@@ -206,48 +209,72 @@ Use MikroMCP to show CPU, memory, uptime, active interfaces, and warning logs fo
206
209
 
207
210
  ### HTTP / SSE Mode
208
211
 
209
- HTTP mode is useful for service deployments and MCP clients that connect over a local or private network endpoint.
212
+ HTTP mode is useful for service deployments and MCP clients that connect over a network endpoint.
213
+
214
+ Set in `~/.mikromcp/.env`:
215
+
216
+ ```bash
217
+ MIKROMCP_TRANSPORT=http
218
+ MIKROMCP_PORT=3000
219
+ MIKROMCP_CONFIRMATION_SECRET=<openssl rand -hex 32>
220
+ ```
221
+
222
+ Then run:
210
223
 
211
224
  ```bash
212
- export MIKROMCP_TRANSPORT=http
213
- export MIKROMCP_PORT=3000
214
- export MIKROMCP_BIND_HOST=127.0.0.1
215
- export MIKROMCP_CONFIRMATION_SECRET="$(openssl rand -hex 32)"
216
- export ROUTER_CORE01_USER="mcp-api"
217
- export ROUTER_CORE01_PASS="your-router-password"
218
- npm start
225
+ mikromcp serve
219
226
  ```
220
227
 
221
- Every HTTP/SSE request must include:
228
+ Every HTTP request must include:
222
229
 
223
230
  ```text
224
231
  Authorization: Bearer <token>
225
232
  ```
226
233
 
227
- Tokens are configured as bcrypt hashes in `config/identities.yaml`.
234
+ Tokens are configured as bcrypt hashes in `~/.mikromcp/identities.yaml`. Use `mikromcp init` to generate them.
235
+
236
+ ### Docker
237
+
238
+ ```bash
239
+ docker run --rm \
240
+ -e MIKROMCP_TRANSPORT=http \
241
+ -e MIKROMCP_PORT=3000 \
242
+ -e MIKROMCP_CONFIRMATION_SECRET="$(openssl rand -hex 32)" \
243
+ -e ROUTER_CORE01_USER=mcp-api \
244
+ -e ROUTER_CORE01_PASS=your-router-password \
245
+ -e MIKROMCP_CONFIG_PATH=/config/routers.yaml \
246
+ -v "$HOME/.mikromcp:/config:ro" \
247
+ -p 3000:3000 \
248
+ ghcr.io/alikarami/mikromcp:latest
249
+ ```
250
+
251
+ Pass `MIKROMCP_CONFIG_PATH` and `MIKROMCP_IDENTITIES_PATH` explicitly when running in Docker since `~/.mikromcp/` inside the container refers to the container's home directory.
228
252
 
229
253
  ---
230
254
 
231
255
  ## Configuration Reference
232
256
 
233
- | Variable | Default | Purpose |
234
- | --------------------------------- | ------------------------ | ------------------------------------------------------ |
235
- | `MIKROMCP_TRANSPORT` | `stdio` | `stdio` or `http` |
236
- | `MIKROMCP_CONFIG_PATH` | `config/routers.yaml` | Router registry path |
237
- | `MIKROMCP_IDENTITIES_PATH` | `config/identities.yaml` | Identity and bearer-token registry |
238
- | `MIKROMCP_STDIO_IDENTITY` | built-in superadmin | Named identity for stdio mode |
239
- | `MIKROMCP_PORT` | `3000` | HTTP transport port |
240
- | `MIKROMCP_BIND_HOST` | `127.0.0.1` | HTTP bind address |
241
- | `MIKROMCP_CONFIRMATION_SECRET` | unset | HMAC secret for destructive-action confirmation tokens |
242
- | `MIKROMCP_AUDIT_LOG_PATH` | unset | Optional NDJSON audit log file path |
243
- | `MIKROMCP_HTTP_MAX_BODY_BYTES` | `1048576` | HTTP request body cap |
244
- | `MIKROMCP_HTTP_RATE_LIMIT_RPM` | `60` | Requests per minute per IP; `0` disables rate limiting |
245
- | `MIKROMCP_SSH_COMMAND_TIMEOUT_MS` | `30000` | SSH command timeout |
246
- | `MIKROMCP_SSH_MAX_OUTPUT_BYTES` | `524288` | SSH output cap |
247
- | `MIKROMCP_CMD_ALLOW` | unset | Global allowlist patterns for `run_command` |
248
- | `MIKROMCP_CMD_DENY` | unset | Global denylist patterns for `run_command` |
249
- | `ROUTER_<PREFIX>_USER` | unset | Router username from `envPrefix` |
250
- | `ROUTER_<PREFIX>_PASS` | unset | Router password from `envPrefix` |
257
+ All settings can be placed in `~/.mikromcp/.env` or passed as environment variables. Values in `~/.mikromcp/.env` are loaded at startup; explicit environment variables always take precedence.
258
+
259
+ | Variable | Default | Purpose |
260
+ | --------------------------------- | -------------------------------- | ------------------------------------------------------ |
261
+ | `MIKROMCP_TRANSPORT` | `stdio` | `stdio` or `http` |
262
+ | `MIKROMCP_CONFIG_PATH` | `~/.mikromcp/routers.yaml` | Router registry path |
263
+ | `MIKROMCP_IDENTITIES_PATH` | `~/.mikromcp/identities.yaml` | Identity and bearer-token registry |
264
+ | `MIKROMCP_STDIO_IDENTITY` | built-in superadmin | Named identity for stdio mode |
265
+ | `MIKROMCP_PORT` | `3000` | HTTP transport port |
266
+ | `MIKROMCP_BIND_HOST` | `127.0.0.1` | HTTP bind address |
267
+ | `MIKROMCP_CONFIRMATION_SECRET` | unset | HMAC secret for destructive-action confirmation tokens |
268
+ | `MIKROMCP_AUDIT_LOG_PATH` | unset | Optional NDJSON audit log file path |
269
+ | `MIKROMCP_DATA_DIR` | `~/.mikromcp/data` | Snapshots and write-journal directory |
270
+ | `MIKROMCP_HTTP_MAX_BODY_BYTES` | `1048576` | HTTP request body cap |
271
+ | `MIKROMCP_HTTP_RATE_LIMIT_RPM` | `60` | Requests per minute per IP; `0` disables rate limiting |
272
+ | `MIKROMCP_SSH_COMMAND_TIMEOUT_MS` | `30000` | SSH command timeout |
273
+ | `MIKROMCP_SSH_MAX_OUTPUT_BYTES` | `524288` | SSH output cap |
274
+ | `MIKROMCP_CMD_ALLOW` | unset | Global allowlist patterns for `run_command` |
275
+ | `MIKROMCP_CMD_DENY` | unset | Global denylist patterns for `run_command` |
276
+ | `ROUTER_<PREFIX>_USER` | unset | Router username from `envPrefix` |
277
+ | `ROUTER_<PREFIX>_PASS` | unset | Router password from `envPrefix` |
251
278
 
252
279
  ---
253
280
 
@@ -353,14 +380,6 @@ to 1.1.1.1. If packet loss is present, use torch on the WAN interface for a
353
380
  short traffic snapshot.
354
381
  ```
355
382
 
356
- ### Configuration Backup And Audit
357
-
358
- ```text
359
- List files, scripts, scheduled jobs, firewall rules, DNS static records, and
360
- routes on core-01. Produce an audit summary with change-risk notes and suggested
361
- cleanup tasks.
362
- ```
363
-
364
383
  ### Plan / Apply / Rollback Workflow
365
384
 
366
385
  ```text
@@ -383,15 +402,13 @@ AI assistants can use MikroMCP to:
383
402
  - Preview changes before mutation and explain exactly what would happen.
384
403
  - Respect tool-level authorization, router scoping, maintenance windows, and confirmation gates.
385
404
 
386
- This makes MikroMCP a practical bridge between MikroTik networks and the emerging AI infrastructure ecosystem: Claude MCP, LLM tooling, infrastructure automation, DevOps workflows, and network operations copilots.
387
-
388
405
  ---
389
406
 
390
407
  ## Documentation
391
408
 
392
409
  | Resource | Use it for |
393
410
  | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
394
- | [ROADMAP.md](ROADMAP.md) | Shipped milestones and planned v1.0 work |
411
+ | [ROADMAP.md](ROADMAP.md) | Shipped milestones and planned work |
395
412
  | [Architecture](https://github.com/AliKarami/MikroMCP/wiki/Architecture) | System layers and request pipeline |
396
413
  | [Setup Guide](https://github.com/AliKarami/MikroMCP/wiki/Setup-Guide) | RouterOS REST setup and end-to-end onboarding |
397
414
  | [Configuration](https://github.com/AliKarami/MikroMCP/wiki/Configuration) | Router registry, TLS, SSH, credentials, HTTP mode |
@@ -401,7 +418,6 @@ This makes MikroMCP a practical bridge between MikroTik networks and the emergin
401
418
  | [Error Handling](https://github.com/AliKarami/MikroMCP/wiki/Error-Handling) | Typed errors, retry behavior, circuit breaker behavior |
402
419
  | [Development](https://github.com/AliKarami/MikroMCP/wiki/Development) | Project structure, tests, MCP Inspector workflow |
403
420
  | [Contributing](https://github.com/AliKarami/MikroMCP/wiki/Contributing) | Adding tools, coding conventions, PR checklist |
404
- | [Roadmap](https://github.com/AliKarami/MikroMCP/wiki/Roadmap) | Wiki mirror of the milestone roadmap |
405
421
 
406
422
  ---
407
423
 
@@ -411,30 +427,23 @@ This makes MikroMCP a practical bridge between MikroTik networks and the emergin
411
427
  npm run dev # tsx watch hot-reload
412
428
  npm run build # build ESM output to dist/main.js
413
429
  npm start # run built server
414
- npm test # run Vitest once
415
- npm run typecheck # TypeScript type checking
416
- npm run lint # ESLint
430
+ npm test # vitest + tsc + eslint
417
431
  npm run format # Prettier
418
432
  ```
419
433
 
420
- Run this before committing:
421
-
422
- ```bash
423
- npm test
424
- npm run typecheck
425
- ```
426
-
427
434
  Key project paths:
428
435
 
429
436
  | Path | Purpose |
430
437
  | -------------------------------- | ------------------------------------------------------------------------------------------- |
431
- | `src/main.ts` | Loads config and starts stdio or HTTP transport |
438
+ | `src/main.ts` | Loads `~/.mikromcp/.env` and starts stdio or HTTP transport |
432
439
  | `src/mcp/tool-registry.ts` | Registers tools and applies auth, retry, circuit breaker, audit, snapshots, and credentials |
433
440
  | `src/domain/tools/` | Tool definitions and handlers |
434
441
  | `src/domain/snapshot/` | Snapshot, diff, and write-journal support |
435
442
  | `src/adapter/rest-client.ts` | RouterOS REST API client |
436
443
  | `src/adapter/ssh-client.ts` | SSH execution adapter for diagnostics and guarded commands |
437
444
  | `src/config/router-registry.ts` | Router inventory loader |
445
+ | `src/cli/init.ts` | Interactive setup wizard (`mikromcp init`) |
446
+ | `src/cli/doctor.ts` | Health check command (`mikromcp doctor`) |
438
447
  | `config/routers.example.yaml` | Example multi-router registry |
439
448
  | `config/identities.example.yaml` | Example RBAC identity registry |
440
449
 
@@ -448,7 +457,7 @@ Key project paths:
448
457
  | v0.7 | ✅ Shipped | Identity, bearer auth, RBAC, audit log, confirmation gate |
449
458
  | v0.8 | ✅ Shipped | Snapshots, write journal, plan/apply, rollback, maintenance windows |
450
459
  | v0.9 | ✅ Shipped | Fleet operations, IPSec, certificates, users, DHCP servers/pools, queues/QoS, VRRP, SNMP/NTP, Netwatch, discovery, ARP, health checks |
451
- | v1.0 | 🔜 Planned | Docker/npm/systemd distribution, Prometheus metrics, CHR integration tests, doctor CLI, stability policy |
460
+ | v1.0 | ✅ Shipped | npm package, standalone binaries, Docker images, `mikromcp init` wizard, `mikromcp doctor`, `~/.mikromcp/` convention |
452
461
 
453
462
  See [ROADMAP.md](ROADMAP.md) for the complete milestone plan.
454
463
 
@@ -468,12 +477,9 @@ Good first contributions:
468
477
 
469
478
  Development standards:
470
479
 
471
- - TypeScript strict mode
472
- - ESM imports with `.js` extensions
473
- - Zod schemas with `.strict()`
474
- - Idempotency and `dryRun` for write tools
475
- - `MikroMCPError` for domain errors
476
- - Focused Vitest coverage for every tool
480
+ - TypeScript strict mode, ESM imports with `.js` extensions
481
+ - Zod schemas with `.strict()`, idempotency and `dryRun` for write tools
482
+ - `MikroMCPError` for domain errors, focused Vitest coverage for every tool
477
483
 
478
484
  Please open an issue before large changes so maintainers can align on scope.
479
485
 
@@ -481,18 +487,17 @@ Please open an issue before large changes so maintainers can align on scope.
481
487
 
482
488
  ## Security
483
489
 
484
- MikroMCP is designed for sensitive infrastructure, but it still controls real network devices. Treat it like an operations system.
490
+ MikroMCP controls real network devices. Treat it like an operations system.
485
491
 
486
492
  - Use least-privilege RouterOS users.
487
493
  - Prefer TLS verification and certificate fingerprint pinning.
488
- - Pin SSH host-key fingerprints for SSH-enabled tools.
489
- - Keep router credentials in environment variables or a secrets system, not YAML.
494
+ - Keep router credentials in `~/.mikromcp/.env`, not in YAML or shell history.
490
495
  - Use HTTP mode behind a trusted network boundary.
491
496
  - Configure identities with the smallest practical `allowedRouters` and `allowedToolPatterns`.
492
- - Enable audit logging for shared or production use.
497
+ - Enable audit logging (`MIKROMCP_AUDIT_LOG_PATH`) for shared or production use.
493
498
  - Test write tools with `dryRun: true` before applying changes.
494
499
 
495
- For vulnerabilities or unsafe behavior, open a private security advisory if available, or contact the maintainer before publishing exploit details.
500
+ For vulnerabilities or unsafe behavior, open a private security advisory or contact the maintainer before publishing details.
496
501
 
497
502
  ---
498
503
 
@@ -501,7 +506,6 @@ For vulnerabilities or unsafe behavior, open a private security advisory if avai
501
506
  - ⭐ Star the repository if MikroMCP helps your MikroTik or MCP workflow.
502
507
  - 🍴 Fork it to add RouterOS surfaces your network depends on.
503
508
  - 🧵 Open an issue for bugs, feature requests, compatibility notes, or documentation gaps.
504
- - 🛣️ Follow the [roadmap](ROADMAP.md) for upcoming fleet, distribution, and production-readiness work.
505
509
 
506
510
  ---
507
511
 
package/dist/main.js CHANGED
@@ -7,6 +7,7 @@ import { homedir as homedir5 } from "os";
7
7
 
8
8
  // src/cli/index.ts
9
9
  import { Command } from "commander";
10
+ import { spawnSync } from "child_process";
10
11
 
11
12
  // src/config/app-config.ts
12
13
  import { join } from "path";
@@ -8613,7 +8614,7 @@ function createServerFactory(config, identityRegistry) {
8613
8614
  const makeServer = () => {
8614
8615
  const server = new McpServer({
8615
8616
  name: "mikromcp",
8616
- version: "1.0.3"
8617
+ version: "1.0.5"
8617
8618
  });
8618
8619
  registerAllTools(server, registry, pool, circuitBreakers, config, identityRegistry);
8619
8620
  return server;
@@ -8936,7 +8937,7 @@ import { existsSync as existsSync3, readFileSync as readFileSync6 } from "fs";
8936
8937
  import { homedir as homedir3 } from "os";
8937
8938
  import * as net from "net";
8938
8939
  import chalk from "chalk";
8939
- var localVersion = "1.0.3";
8940
+ var localVersion = "1.0.5";
8940
8941
  var results = [];
8941
8942
  function ok(msg) {
8942
8943
  console.log(chalk.green("\u2705 ") + msg);
@@ -9262,8 +9263,7 @@ async function collectRouterInfo() {
9262
9263
  }
9263
9264
  });
9264
9265
  const port = Number(portStr);
9265
- const tlsDefault = port === 443 || port === 8443;
9266
- const tlsEnabled = await confirm({ message: "Enable TLS?", default: tlsDefault });
9266
+ const tlsEnabled = await confirm({ message: "Enable TLS?", default: false });
9267
9267
  let rejectUnauthorized = true;
9268
9268
  if (tlsEnabled) {
9269
9269
  rejectUnauthorized = await confirm({
@@ -9284,6 +9284,14 @@ async function collectRouterInfo() {
9284
9284
  default: suggestedPrefix,
9285
9285
  validate: (v) => v.trim().length > 0 ? true : "Env prefix is required"
9286
9286
  });
9287
+ const routerUser = await input({
9288
+ message: `Router username (${envPrefix}_USER):`,
9289
+ validate: (v) => v.trim().length > 0 ? true : "Username is required"
9290
+ });
9291
+ const routerPass = await input({
9292
+ message: `Router password (${envPrefix}_PASS):`,
9293
+ validate: (v) => v.trim().length > 0 ? true : "Password is required"
9294
+ });
9287
9295
  const tagsRaw = await input({
9288
9296
  message: "Tags (comma-separated, optional):",
9289
9297
  default: ""
@@ -9294,7 +9302,7 @@ async function collectRouterInfo() {
9294
9302
  default: "7",
9295
9303
  validate: (v) => v.trim().length > 0 ? true : "Version is required"
9296
9304
  });
9297
- return { routerId, host, port, tlsEnabled, rejectUnauthorized, envPrefix, tags, rosVersion };
9305
+ return { routerId, host, port, tlsEnabled, rejectUnauthorized, envPrefix, routerUser, routerPass, tags, rosVersion };
9298
9306
  }
9299
9307
  async function collectIdentityInfo() {
9300
9308
  console.log(chalk2.bold("\n\u2500\u2500 Identity / HTTP transport \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"));
@@ -9350,6 +9358,25 @@ async function collectIdentityInfo() {
9350
9358
  tokenHash
9351
9359
  };
9352
9360
  }
9361
+ async function collectTransport() {
9362
+ console.log(chalk2.bold("\n\u2500\u2500 Transport \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"));
9363
+ const transport2 = await select({
9364
+ message: "Transport mode:",
9365
+ choices: [
9366
+ { value: "stdio", name: "stdio \u2014 launched by Claude Desktop or an MCP client (recommended)" },
9367
+ { value: "http", name: "http \u2014 standalone HTTP server with bearer-token auth" }
9368
+ ],
9369
+ default: "stdio"
9370
+ });
9371
+ if (transport2 === "http") {
9372
+ console.log(
9373
+ chalk2.yellow(
9374
+ "\n \u26A0 HTTP mode requires every request to include:\n Authorization: Bearer <token>\n Set MIKROMCP_CONFIRMATION_SECRET in ~/.mikromcp/.env and create an identity above."
9375
+ )
9376
+ );
9377
+ }
9378
+ return transport2;
9379
+ }
9353
9380
  async function collectEnvPreference() {
9354
9381
  return confirm({
9355
9382
  message: "Write credentials to ~/.mikromcp/.env? (No = inject env vars at runtime)",
@@ -9410,17 +9437,16 @@ function writeDotEnv(data) {
9410
9437
  const userKey = `${data.envPrefix}_USER`;
9411
9438
  const passKey = `${data.envPrefix}_PASS`;
9412
9439
  const auditLogPath = defaultAuditLogPath();
9413
- const transport2 = data.createIdentity ? "http" : "stdio";
9414
- const confirmationSecret = data.createIdentity ? randomBytes(32).toString("hex") : "";
9440
+ const confirmationSecret = data.transport === "http" ? randomBytes(32).toString("hex") : "";
9415
9441
  const lines = [
9416
9442
  "# \u2500\u2500 Router credentials \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",
9417
- `${userKey}=`,
9418
- `${passKey}=`,
9443
+ `${userKey}=${data.routerUser}`,
9444
+ `${passKey}=${data.routerPass}`,
9419
9445
  "",
9420
9446
  "# \u2500\u2500 Transport \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",
9421
9447
  `# stdio \u2192 launched directly by Claude Desktop or another MCP client`,
9422
9448
  `# http \u2192 standalone server mode with bearer-token auth`,
9423
- `MIKROMCP_TRANSPORT=${transport2}`,
9449
+ `MIKROMCP_TRANSPORT=${data.transport}`,
9424
9450
  "",
9425
9451
  "# \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",
9426
9452
  `MIKROMCP_CONFIG_PATH=${join4(data.configDir, "routers.yaml")}`,
@@ -9446,9 +9472,6 @@ function writeDotEnv(data) {
9446
9472
  } else {
9447
9473
  writeFileSync2(data.envPath, content);
9448
9474
  }
9449
- console.log(
9450
- chalk2.dim(` Fill in ${userKey} and ${passKey} in ${data.envPath}`)
9451
- );
9452
9475
  }
9453
9476
  function registerClaudeDesktop() {
9454
9477
  const configPath = findClaudeDesktopConfig();
@@ -9486,6 +9509,7 @@ async function runInit() {
9486
9509
  const identityInfo = await collectIdentityInfo();
9487
9510
  const configDir = mikromcpDir2();
9488
9511
  const envPath = join4(configDir, ".env");
9512
+ const transport2 = await collectTransport();
9489
9513
  const writeEnv = await collectEnvPreference();
9490
9514
  let writeRouters = true;
9491
9515
  const routersYamlPath = join4(configDir, "routers.yaml");
@@ -9500,6 +9524,7 @@ async function runInit() {
9500
9524
  const data = {
9501
9525
  ...routerInfo,
9502
9526
  ...identityInfo,
9527
+ transport: transport2,
9503
9528
  envPath,
9504
9529
  configDir,
9505
9530
  writeEnv,
@@ -9550,10 +9575,14 @@ async function runInit() {
9550
9575
  }
9551
9576
 
9552
9577
  // src/cli/index.ts
9553
- var program = new Command().name("mikromcp").description("MikroTik RouterOS MCP server").version("1.0.3");
9578
+ var program = new Command().name("mikromcp").description("MikroTik RouterOS MCP server").version("1.0.5");
9554
9579
  program.command("serve", { isDefault: true }).description("Start the MCP server (default)").action(runServe);
9555
9580
  program.command("doctor").description("Check config, connectivity, and permissions").action(runDoctor);
9556
9581
  program.command("init").description("Interactive setup wizard").action(runInit);
9582
+ program.command("update").description("Update mikromcp to the latest version via npm").action(() => {
9583
+ const result = spawnSync("npm", ["update", "-g", "mikromcp"], { stdio: "inherit" });
9584
+ if (result.status !== 0) process.exit(result.status ?? 1);
9585
+ });
9557
9586
 
9558
9587
  // src/main.ts
9559
9588
  loadDotenv({ path: join5(homedir5(), ".mikromcp", ".env"), override: false });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mikromcp",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Production-grade MCP server for MikroTik RouterOS",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",