Skip to main content
ClaudeWave

MCP server for MikroTik RouterOS over the binary API. Addresses rules by their real .id, never by list position.

MCP ServersOfficial Registry0 stars0 forksPythonMITUpdated today
ClaudeWave Trust Score
87/100
Trusted
Passed
  • Open-source license (MIT)
  • Actively maintained (<30d)
  • Clear description
  • Topics declared
  • Documented (README)
Flags
  • !Install pipes a remote script into a shell (curl | sh)
Last scanned: 9/16/2026
Install in Claude Code / Claude Desktop
Method: UVX (Python) · mikrotik-mcp
Claude Code CLI
claude mcp add mikrotik-mcp -- uvx mikrotik-mcp
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "mikrotik-mcp": {
      "command": "uvx",
      "args": ["mikrotik-mcp"]
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
Use cases

MCP Servers overview

# mikrotik-mcp

<!-- The MCP registry verifies package ownership by looking for this token in
     the PyPI description, which is this README. It must sit on its own line. -->
mcp-name: io.github.StefanKnol/mikrotik-mcp

An MCP server for MikroTik RouterOS, over the **binary API** rather than by
driving the CLI over SSH.

That distinction is the whole point. The CLI prints *positional* numbers, which
are not a rule's identity. A server that lists rules by position and then writes
by position either fails outright — `where .id=3` matches nothing, so every
write reports "not found" for rules that plainly exist — or, worse, succeeds
against a different rule once the order has shifted. On a firewall that means
deleting the wrong rule.

The binary API returns the real `.id` (`*7`, `*1f`) on every read. So:

- every read returns `id`, and every write takes one back;
- list results also carry `position`, which is display-only and **refused** for
  writes, with an error that explains why;
- writes read back what they wrote, so a change can be verified rather than assumed;
- `remove_firewall_rule` takes an optional `confirm_comment` and returns the
  rule it deleted.

## Use it

```bash
uvx mikrotik-mcp
```

Configure through the environment — `ps` would show a password passed as a flag:

| Variable | Default | Meaning |
| --- | --- | --- |
| `MIKROTIK_HOST` | — | Router address. Required. |
| `MIKROTIK_USERNAME` | — | Required. |
| `MIKROTIK_PASSWORD` | — | |
| `MIKROTIK_PORT` | `8729` | `8729` for api-ssl, `8728` for plaintext. |
| `MIKROTIK_TLS` | `true` | |
| `MIKROTIK_TLS_FINGERPRINT` | — | SHA-256 of the router certificate, to pin it. |
| `MIKROTIK_TIMEOUT` | `10` | |

In an MCP client's config:

```json
{
  "mcpServers": {
    "mikrotik": {
      "command": "uvx",
      "args": ["mikrotik-mcp"],
      "env": {
        "MIKROTIK_HOST": "192.168.88.1",
        "MIKROTIK_USERNAME": "mcp-agent",
        "MIKROTIK_PASSWORD": "..."
      }
    }
  }
}
```

## On the router

```
/ip service enable api-ssl
/user group add name=mcp policy=api,read,write,test
/user add name=mcp-agent group=mcp password=<strong-password>
```

The `api` policy is not optional, and its absence produces a login error
**identical** to a wrong password — so if credentials look right and login still
fails, check the group first.

Set `MIKROTIK_TLS_FINGERPRINT` if you can. MikroTik's API-SSL certificate is
self-signed, so ordinary CA validation cannot succeed against a stock device;
pinning is what makes the connection authenticated rather than merely encrypted.

## Tools

34 of them, covering system info, interfaces, IP addressing, firewall filter
(IPv4 and IPv6), firewall address lists, NAT, DHCP leases, DNS, routes and logs
— plus `ros_list`, which reads any RouterOS path and so covers everything
without a dedicated tool.

There is deliberately **no** generic write escape hatch.

Three things worth knowing before the first call:

- **Writes take an `id` (`*7`), never a `position`.** Both appear in every list
  result. `position` is where a rule currently sits in evaluation order; it
  shifts whenever anything is added, removed or moved, and it is counted across
  the whole table rather than within the chain you filtered to. Passing one to
  a write is rejected rather than guessed at.
- **IPv4 and IPv6 are separate rule sets.** The firewall tools take a `family`
  and default to `ipv4`, so a device can read as locked down while its IPv6
  table is empty and therefore accepting everything. Listing IPv4 reports the
  IPv6 rule count for exactly this reason.
- **Address lists hold state no configuration export shows.** Entries a rule
  adds at runtime carry a timeout and exist only in memory. Ask
  `list_address_list_entries` for a `count_only` first: a populated block list
  can hold tens of thousands.

## With mcphub

Two ways, and the first is the better default:

**Launched as a subprocess** by [mcphub](https://github.com/StefanKnol/mcphub),
configured as a command — `uvx mikrotik-mcp` — with credentials as encrypted
environment variables. It runs in its own process and cannot read credentials
held for other backends.

**Loaded in-process** via the `mcphub.plugins` entry point this package also
ships, which gives typed host/username/password fields in mcphub's settings UI.
Nicer to configure, but an in-process plugin can read everything the hub holds.
Install it into the hub's environment to use this route.

## Publishing to the MCP registry

`server.json` is the manifest for the [official MCP registry](https://registry.modelcontextprotocol.io),
validated against the published schema. It declares the `uvx mikrotik-mcp`
command and every `MIKROTIK_*` variable, marking which are required and which
are secret — so a client that browses the registry can generate a correct
settings form without knowing anything about this server.

Publishing has an order to it, because the registry verifies that whoever
publishes an entry actually owns the package it points at.

**1. The package must already be on PyPI.** The registry fetches
`pypi.org/pypi/mikrotik-mcp/<version>/json` and refuses an entry whose package
does not exist. Tag a release and let CI publish it:

```bash
git tag v0.1.0 && git push --tags
```

That needs a PyPI Trusted Publisher first, and because this project does not
exist on PyPI yet it has to be a **pending** publisher — the per-project
Publishing tab only appears once a project exists, which is the chicken-and-egg
this page solves:

> pypi.org → Account settings → **Publishing** → *Add a new pending publisher*
>
> | Field | Value |
> | --- | --- |
> | PyPI Project Name | `mikrotik-mcp` |
> | Owner | `StefanKnol` |
> | Repository name | `mikrotik-mcp` |
> | Workflow name | `ci.yml` |
> | Environment name | `pypi` |

The environment name matters: the publish job declares `environment: pypi`, and
PyPI rejects the upload if they disagree.

**2. The README must carry the ownership token.** The registry looks for
`mcp-name: io.github.StefanKnol/mikrotik-mcp` in the PyPI description, which is
this file — it is at the top, on its own line. That is what proves the person
publishing the registry entry controls the PyPI package.

**3. The registry entry publishes itself.** The `registry` job in `ci.yml`
runs after the PyPI upload on the same tag, authenticating with
`mcp-publisher login github-oidc`. GitHub signs a short-lived OIDC token, the
registry verifies it and grants the `io.github.StefanKnol/*` namespace from the
repository owner. There is no secret to store and no device-flow login to sit
through on each release.

It waits for PyPI to actually serve the new version first. The registry fetches
`pypi.org/pypi/mikrotik-mcp/<version>/json` and refuses an entry whose package
it cannot see, and that endpoint lags the upload by some seconds — long enough
that publishing straight afterwards races it.

Re-running it is safe: a version already in the registry is the outcome the job
exists to produce, so it reports that and passes rather than failing on the
registry's duplicate refusal.

To publish by hand — recovering a failed run, or a version released before this
job existed:

```bash
curl -sL https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_linux_amd64.tar.gz | tar xz mcp-publisher
./mcp-publisher login github && ./mcp-publisher publish
```

`login github` opens the device flow and proves you are `StefanKnol`, which
authorises the same namespace the OIDC path gets without asking.

The version appears in four places — `pyproject.toml`, `__version__`,
`server.json`, and again inside that file's `packages` entry. Rather than
edit them by hand:

```bash
uv run python scripts/release.py 0.2.0 --tag
```

It sets all four, verifies them, commits and tags. The registry treats each
version as its own row and checks PyPI has the package at exactly that
version, so the nested `packages[].version` matters as much as the top-level
one — and it is the one that gets missed, because the manifest still validates
without it. A test enforces that they agree.

## Development

```bash
uv sync --extra dev
uv run pytest
```

## License

MIT
firewallhomelabmcpmikrotikmodel-context-protocolnetworkingrouteros

What people ask about mikrotik-mcp

What is StefanKnol/mikrotik-mcp?

+

StefanKnol/mikrotik-mcp is mcp servers for the Claude AI ecosystem. MCP server for MikroTik RouterOS over the binary API. Addresses rules by their real .id, never by list position. It has 0 GitHub stars and its last recorded update is dated 2026-09-15.

How do I install mikrotik-mcp?

+

You can install mikrotik-mcp by cloning the repository (https://github.com/StefanKnol/mikrotik-mcp) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is StefanKnol/mikrotik-mcp safe to use?

+

Our security agent has analyzed StefanKnol/mikrotik-mcp and assigned a Trust Score of 87/100 (tier: Trusted). See the full breakdown of passed checks and flags on this page.

Who maintains StefanKnol/mikrotik-mcp?

+

StefanKnol/mikrotik-mcp is maintained by StefanKnol. The last recorded GitHub activity is dated 2026-09-15, with 0 open issues.

Are there alternatives to mikrotik-mcp?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy mikrotik-mcp to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: StefanKnol/mikrotik-mcp
[![Featured on ClaudeWave](https://claudewave.com/api/badge/stefanknol-mikrotik-mcp)](https://claudewave.com/repo/stefanknol-mikrotik-mcp)
<a href="https://claudewave.com/repo/stefanknol-mikrotik-mcp"><img src="https://claudewave.com/api/badge/stefanknol-mikrotik-mcp" alt="Featured on ClaudeWave: StefanKnol/mikrotik-mcp" width="320" height="64" /></a>

More MCP Servers

mikrotik-mcp alternatives