Skip to content

MCP server

Daniel Frantík edited this page Jun 17, 2026 · 3 revisions

tik4net MCP server

Tools/tik4net.mcp is a small Model Context Protocol server that exposes tik4net to an MCP client (Claude Code, Claude Desktop, …) as a single tool, mikrotik_call. It lets an AI assistant — or any MCP client — run a MikroTik command against a live router over any tik4net transport and get the result back as JSON.

Its main purpose is protocol debugging across transports: because every transport shares the same low-level CallCommandSync, the exact same command/parameters run over Api, Telnet, WinboxNative, … and you can diff the results — and, with includeRawTrace, the raw words each transport exchanges.

This is a developer/diagnostics tool — its purpose is protocol debugging during tik4net development, not production router management. It ships in the repo under Tools/tik4net.mcp and is also published as a .NET global tool (dotnet tool install -g tik4net.mcp).

Looking for a production-ready MCP server for MikroTik? See tik4mcp — a standalone admin-grade MikroTik MCP server built on tik4net, with multi-router inventory, RBAC, and guardrails.

What it does

The server has one tool. Internally it builds a TikConnectionSetup, opens the chosen transport, runs the command via ITikConnection.CallCommandSync, and formats the !re sentences as a JSON array.

mikrotik_call(host, username, password, command,
              transport = "Api", port = 0, routerMac = null,
              includeRawTrace = false, parameters = null)
Parameter Type Description
host string Router IP or hostname
username string Login user
password string Login password (may be empty)
command string API command path, e.g. /ip/address/print, /system/resource/print, /ip/address/add
transport string Transport name (case-insensitive), default Api — see table below
port int TCP/UDP port; 0 = transport default
routerMac string Router MAC AA:BB:CC:DD:EE:FFonly MacTelnet / WinboxCliMac; omitted → MNDP discovery (~5 s)
includeRawTrace bool Also return the raw words exchanged for the command (protocol debugging), default false
parameters string[] Extra API words — filter ?name=value, name-value =name=value

Parameters format

The parameters array uses MikroTik API sentence words, identical on every transport:

  • Filter?name=value (e.g. ?disabled=yes, ?.id=*3)
  • NameValue=name=value (e.g. =address=10.0.0.1/24, =.id=*1)
// filtered print
{ "command": "/ip/firewall/filter/print", "parameters": ["?action=drop"] }
// set a field
{ "command": "/ip/address/set", "parameters": ["=.id=*1", "=disabled=yes"] }

Result

  • a JSON array of !re records (for print),
  • OK (no data returned) for writes that returned no rows,
  • ERROR (...) / TRAP [code]: message on failure,
  • …followed by a --- RAW TRACE … --- block when includeRawTrace = true.

Transports

All transports accept the same command / parameters. Only Api / ApiSsl support Listen/Streaming; the rest are request/response only.

transport Wire Default port Router prerequisite
Api binary API 8728 api service (default)
ApiSsl TLS API 8729 api-ssl service + cert
Rest HTTP REST 80 www service, RouterOS 7.1+
RestSsl HTTPS REST 443 www-ssl service + cert, 7.1+
Telnet plain CLI 23 /ip/service set telnet disabled=no
MacTelnet CLI over MAC layer (UDP) 20561 /tool/mac-server set allowed-interface-list=all
WinboxCli encrypted terminal CLI 8291 winbox service (default)
WinboxCliMac encrypted CLI over MAC (UDP) 20561 /tool/mac-server/mac-winbox set allowed-interface-list=all
WinboxNative ⚠️ alpha-preview structured M2 (no terminal) 8291 winbox service (default)

RAW trace — debugging the protocol

includeRawTrace: true appends the raw words exchanged for the command (not the login handshake). It rides the public OnWriteRow / OnReadRow events — see Communication debugging & testing — so the same trace is available to any tik4net program, not just the MCP. Rendering is per-transport:

Transport Trace form
Api / ApiSsl one word per line (/path, =name=value, !re, !done)
Rest / RestSsl the HTTP request / response
Telnet / MacTelnet / WinboxCli / WinboxCliMac the synthesized CLI command text + the raw CLI response
WinboxNative the raw M2 message of each request/reply, rendered by M2Message.Describe

Comparing a transport against the API baseline is the core workflow:

// A — source of truth
{ "command": "/system/resource/print", "transport": "Api" }
// B — should round-trip to the same records
{ "command": "/system/resource/print", "transport": "WinboxNative", "includeRawTrace": true }

WinboxNative trace format

For WinboxNative the trace is the raw M2 wire message>> per request, << per reply:

>> M2[55B] 0xFF0001=u32[]:[20,1] 0xFF0002=u32[]:[0,8] 0xFF0005=bool:True 0xFF0006=u8:2 …
<< M2[226B] 0xFF0008=u32:0 0xFE0002=msg[]:[{0x1=u32:3959728320,0x3=u32:16777215,0xA=u32:2,…},{…}] …
  • 0x<fullKey> — the 24-bit M2 field key (namespace<<16)|(keyHi<<8)|keyLo. Namespace 0xFF… = system/control, 0xFE… = session/record-frame, low keys (0x1, 0xD, …) = the handler's user fields (the ones mapped to API names via the .jg catalog).
  • <wireType>bool/u8/u32/u64/str/raw/u32[]/str[]/msg/msg[].
  • Key system fields, every message: 0xFF0001 = to-handler (u32[], e.g. [20,1] — the table being addressed), 0xFF0006 = command (getall/get/set/add/remove/move), 0xFF0008 = status on replies (0 = OK), 0xFE0002 = records array (msg[], one submessage per row).
  • Records under 0xFE0002 are expanded inline as [{…},{…}]; each {…} is one row's raw numeric M2 keys before the API-name mapping — diff this against the final JSON to find a mis-mapped or dropped field.
  • A single print can emit several >>/<< pairs: the data handler plus extra getalls on reference tables to resolve dynamic enums (e.g. /ip/address also reads the interface [20,0] and vrf [20,101] handlers to turn numeric ids into ether1 / main). N round-trips for one command is expected, not a bug.

Running it

The server is registered in the repo's .mcp.json and launched over stdio:

{
  "mcpServers": {
    "tik4net-mcp": {
      "command": "dotnet",
      "args": ["run", "--no-build", "--project", "Tools/tik4net.mcp/tik4net.mcp.csproj"],
      "type": "stdio"
    }
  }
}

--no-build. The launch uses --no-build, so the server runs whatever is already compiled. After changing the tool or the library, rebuild first — and note the running server keeps tik4net.dll loaded, which locks the build's copy step. Stop the MCP client, rebuild, then restart it.

Build it once before first use:

dotnet build Tools/tik4net.mcp/tik4net.mcp.csproj

See also

Clone this wiki locally