MikroTik MCP
MCP server for MikroTik RouterOS fleet management — REST-first, KeePass-backed credentials, read-only mode
Documentation
mikrotik-mcp
An MCP (Model Context Protocol) server for managing fleets of MikroTik RouterOS devices from AI assistants such as Claude.
It exposes 65 tools covering system administration, interfaces, bridging, IP, firewall, DHCP/DNS, PPP, monitoring, and diagnostics — all executed over the RouterOS REST API, with SSH reserved for free-form ros-command execution. Device credentials are never passed through the model: they are resolved from a KeePass vault at runtime.
Highlights
- Fleet-aware by design — every tool accepts a
targetof a single device ID, a comma-separated list (R1,R2,R3), orall. Commands fan out in parallel and return per-device results; one unreachable device never fails the batch. - REST-first transport — structured JSON from the RouterOS REST API (RouterOS v7.1+), no brittle terminal scraping. SSH is used only for the
ros-commandescape hatch. - KeePass-backed credentials — devices are enumerated from a
.kdbxvault group. The LLM only ever sees device IDs, never passwords. - Enforced read-only mode —
READ_ONLY=truewithholds all 14 write/execution and active-diagnostic tools at the protocol level, exposing only the 51 state-query tools. Ideal for monitoring-only agent access. Approval of individual write calls is left to the MCP client, which is where it can actually be enforced (see Write operations and approval). - Two MCP transports —
stdiofor local clients (Claude Desktop, Claude Code) and Streamable HTTP (with legacy SSE fallback) for a shared team server.
Tool overview
| Area | Examples |
|---|---|
| System | identity, clock, health, hardware, packages, license, history, note, certificates, log, files |
| Interfaces & bridging | interface list/stats, enable/disable, interface lists, bridges, ports, VLANs, MAC table, neighbors |
| IP | addresses, ARP, routes, pools, IP settings, IP services |
| Firewall | filter, NAT, mangle, address lists, connection tracking, RADIUS |
| DHCP & DNS | DHCP client/server, leases, networks, DNS settings, static entries |
| PPP & users | profiles, secrets, active sessions, AAA, system users, scheduler, scripts, logging rules |
| Services | NTP, SNMP, reboot/shutdown |
| Diagnostics | ping, traceroute, bandwidth test, torch, packet sniffer, profile, netwatch, fetch, speed test, WoL, MAC/IP scan, traffic generator |
| Fleet & escape hatch | device-list, setup-new-device, ros-command (arbitrary CLI over SSH) |
Quick start
1. Prepare the credential vault
Create a KeePass vault (e.g. config/vault.kdbx) with one entry per device inside a group (default: mikrotik):
- Title → device ID (how you'll refer to the device in prompts)
- Username / Password → RouterOS credentials
- URL → device hostname or IP
2. Run with Docker (shared HTTP server)
Using the prebuilt image:
docker run -d -p 8000:8000 \
-v ./config:/config:ro \
-e KEEPASS_PASSWORD='…' \
ghcr.io/vesact/mikrotik-mcp:latest # serves MCP on http://localhost:8000/mcp
Or build from source:
cp .env.example .env # set KEEPASS_PASSWORD at minimum
docker compose up -d
3. Or run locally over stdio (Claude Desktop / Claude Code)
npm ci && npm run build
{
"mcpServers": {
"mikrotik": {
"command": "node",
"args": ["/path/to/mikrotik-mcp/dist/index.js"],
"env": {
"KEEPASS_PATH": "/path/to/vault.kdbx",
"KEEPASS_PASSWORD": "…"
}
}
}
}
Then ask things like:
"What's the RouterOS version across the whole fleet?" "Show DHCP leases on router-01." "Add a firewall filter on R1,R2."
Configuration
All configuration is via environment variables (see .env.example):
| Variable | Default | Purpose |
|---|---|---|
KEEPASS_PASSWORD | — (required) | Master password of the KeePass vault |
KEEPASS_PATH | /config/keepass.kdbx | Path to the .kdbx vault file |
KEEPASS_GROUP | mikrotik | Vault group to enumerate devices from |
ROUTEROS_REST_PORT | 443 | REST API port on target devices |
ROUTEROS_REST_SCHEME | https | https or http |
ROUTEROS_TIMEOUT_MS | 10000 | REST request timeout |
SSH_TIMEOUT_MS | 10000 | Per-command SSH timeout (ros-command) |
ROUTEROS_SETUP_PORT | 80 (unchanged) | Target www port when bootstrapping via setup-new-device |
MCP_TRANSPORT | stdio (http in the Docker image) | MCP transport |
MCP_HTTP_PORT | 3000 (8000 in the Docker image) | HTTP listen port |
MCP_HOST | 0.0.0.0 | HTTP bind address |
READ_ONLY | false | Expose only read-only state-query tools |
Read-only mode
With READ_ONLY=true (also accepts 1/yes/on), the server exposes only the 51 read-only tools. ros-command, setup-new-device, and all active diagnostics (ping, traceroute, torch, bandwidth test, scans, …) are withheld — they mutate state or generate network traffic. The allow-list is explicit, so tools added in the future are withheld until deliberately classified.
Write operations and approval
The server does not implement its own confirmation step for writes. Write tools execute on the first call, and ros-command in particular runs whatever it is given, verbatim, on every device matched by target.
Approving individual calls is the MCP client's job — it is the layer that can actually enforce a decision and scope it per agent:
- Claude Code — permission modes plus
allow/ask/denyrules, e.g."deny": ["mcp__mikrotik__ros-command"]or anaskrule for the whole server, in.claude/settings.json. - Claude Desktop and other hosts — per-tool approval prompts, kept enabled for this server.
ros-command carries MCP annotations (readOnlyHint: false, destructiveHint: true) so clients can classify it without parsing its description.
Two server-side controls remain, because they are enforcement rather than instruction:
READ_ONLY=true— the tools are never registered, so no client configuration can invoke them.- The RouterOS credentials in the vault — a device account with restricted permissions bounds what any approved command can do.
Requirements
- Node.js ≥ 22 (or Docker)
- RouterOS v7.1+ with the REST API enabled (
www-sslorwwwservice) on managed devices - SSH enabled on devices only if you use
ros-commandorsetup-new-device
Development
npm ci
npm run build # TypeScript → dist/
npm test # unit tests (Vitest, no hardware needed)
npm run check # lint + format check (Biome)
npm run check:fix # apply Biome's fixes and formatting
npm run test:integration # integration tests against real hardware (see .env.test.example)
Unit tests run against fixtures, including a committed test vault (tests/fixtures/test-vault.kdbx, password test-password-123 — fake credentials only). Integration tests require a reachable RouterOS device and are configured via .env.test.
Architecture
MCP client (Claude, …)
│ stdio / Streamable HTTP
▼
mikrotik-mcp server ──► KeePass vault (device inventory + credentials)
│
│ fan-out: target = "R1" | "R1,R2" | "all" (parallel, per-device results)
▼
RouterOS REST API (all tools) / SSH (ros-command only)
The full architecture document lives in docs/architecture.md, and the original product requirements in docs/prd.md.
Contributing
See CONTRIBUTING.md. Security issues: see SECURITY.md.
License
Licensed under the Apache License 2.0.
Copyright 2026 Actemium Schweiz AG — a VINCI Energies company.
MikroTik and RouterOS are trademarks of Mikrotīkls SIA. This project is not affiliated with or endorsed by MikroTik.