Development Blog on software and related things

Beyond Metrics: Instant RouterOS Diagnostics with MKTXP 2.0

The previous post took a look under the hood at the architectural overhaul that set the stage for MKTXP 2.0. The codebase was decoupled into single-responsibility packages with a strategy-based diagnostic engine to support upcoming interactive CLI diagnostics, along with a sneak peek of the areas they were going to cover.

Prometheus and Grafana are good for things like 30-day trends, capacity forecasting, and alerting. But when something feels off right now — WiFi starts stuttering during a video call, your WAN uplink gets saturated, or you suspect a script-kiddie is hitting your SSH port — spinning up a dashboard or clicking through half a dozen nested menus in WinBox is rarely the fastest way to get an answer.

Sometimes you just want to run a one-liner in your terminal and immediately see what is happening.

Well, today MKTXP 2.0.0 is officially out on PyPI.


Answering Network Questions from the Terminal

In the refactoring post, there was a quick wish list of questions to be asked on the fly. Here is how the new mktxp diag engine answers them in practice (using representative, sanitized output from production RouterOS networks):

1. “Which wireless clients have poor signal or low rates?”

Wireless issues are notoriously subjective. Someone complains “the Wi-Fi is slow,” but you need to know: are they actually sitting on a weak 2.4 GHz signal with an 18 Mbps negotiated PHY rate, or is it an upstream issue?

In multi-AP office networks managed by CAPsMAN, “sticky clients” are another frequent problem. A conference room printer, tablet, or roaming laptop connects to a distant access point across the building—like an AP in the cafeteria or reception—and clings to it at -87 dBm and a 1 Mbps rate, even when a ceiling AP in the meeting room sits right overhead.

The -cc (CAPsMAN) and -wc (WiFi) diagnostic domains provide multi-criteria filtering across AP interfaces, signal thresholds, and negotiation rates. Out of dozens or hundreds of active wireless devices, you can immediately isolate the problematic connections:

# Pinpoint clients clinging to distant APs with weak signal (default: <= -75 dBm) and bottom-tier rates
$ mktxp diag -en MKT-CORE -cc --low-signal --low-rate 1M
+----------------------+--------------+-------------------+-----------+------------------+--------+---------+---------+---------+
|      dhcp_name       | dhcp_address |    mac_address    | rx_signal |    interface     |  ssid  | tx_rate | rx_rate | uptime  |
+======================+==============+===================+===========+==================+========+=========+=========+=========+
| wlan0 (Conf Printer) | 10.20.10.49  | D8:1F:12:AD:3C:55 |    -87    | AP-Breakroom-2G  | Office | 36 Mbps | 1 Mbps  | 6 hours |
| wlan0 (Sales Laptop) | 10.20.10.53  | D8:1F:12:AD:32:00 |    -87    | AP-Breakroom-2G  | Office | 11 Mbps | 1 Mbps  | 3 hours |
|                      |              |                   |           |                  |        |         |         |         |
| wlan0 (Boardroom Tab)| 10.20.10.97  | 10:5A:17:0C:B9:C8 |    -84    | AP-Reception-2G  | Office | 24 Mbps | 1 Mbps  |  a day  |
| wlan0 (Desk Phone 04)| 10.20.10.109 | 10:5A:17:0E:11:7F |    -83    | AP-Reception-2G  | Office | 36 Mbps | 1 Mbps  | 2 days  |
|                      |              |                   |           |                  |        |         |         |         |
| wlan0 (Badge Reader) | 10.20.10.70  | D8:1F:12:AD:44:72 |    -78    | AP-Warehouse-2G  | Office | 24 Mbps | 1 Mbps  | 3 days  |
| wlan0 (Floor Scanner)| 10.20.10.69  | D8:1F:12:AD:33:DF |    -76    | AP-Warehouse-2G  | Office | 1 Mbps  | 5 Mbps  | 3 days  |
+----------------------+--------------+-------------------+-----------+------------------+--------+---------+---------+---------+
AP-Breakroom-2G clients: 2
AP-Reception-2G clients: 2
AP-Warehouse-2G clients: 2
Matching CAPsMAN clients: 6 (Total connected: 127)

Notice how mktxp enriches raw MAC addresses with DHCP lease names and comments, groups them by AP interface with automatic separators, and breaks down the client count. You can see immediately that devices sitting in the conference room or boardroom are hanging onto distant APs in the breakroom or reception at 1 Mbps, dragging down channel airtime.

This is the point where you decide whether the issue is client roaming behavior, AP placement, 2.4 GHz coverage, or an access-list policy—not where you blindly disconnect every weak client. The filtered list gives you the exact MAC, hostname, and AP interface needed to validate that decision.

The same wireless diagnostic engine also answers other common questions teased previously, like pinpointing exactly where a specific device is attached or catching new associations on 2.4 GHz:

# Locate one known device: AP, SSID, interface, and leased IP
$ mktxp diag -en MKT-CORE -cc -in "Boardroom Tab"

# Find newly joined clients still using the 2.4 GHz band
$ mktxp diag -en MKT-CORE -cc --band 2g --recent 15m

For standalone routers running RouterOS v7 WiFi, -wc provides the same targeted inspection.


2. “What are those mystery devices on the network?”

Over time, DHCP lease tables fill up with stale entries, IoT gadgets with generic MAC vendor names, and devices without hostnames.

The -dc command queries DHCP server leases and filters them by identity and lease state:

# Surface unidentified devices (no hostname and no configured comment)
$ mktxp diag -en MKT-CORE -dc --unidentified
+-------------------+---------+-------------------+--------------+----------------+---------------+
|     host_name     | server  |    mac_address    |   address    | active_address | expires_after |
+===================+=========+===================+==============+================+===============+
| 70:EE:50:AA:BB:CC | defconf | 70:EE:50:AA:BB:CC | 10.20.10.189 | 10.20.10.189   | 11h 22m       |
| 94:E6:86:DD:EE:FF | defconf | 94:E6:86:DD:EE:FF | 10.20.10.204 | 10.20.10.204   | 8h 05m        |
+-------------------+---------+-------------------+--------------+----------------+---------------+
defconf clients: 2
Matching DHCP clients: 2 (Total: 46)

You can also filter by lease state (--active-only to hide offline entries, or --inactive-only to see stale ones) or inspect only dynamic DHCP assignments (--dynamic) to quickly spot rogue devices plugged into a switch port.


3. “Who is opening hundreds of connections?”

When a local client is infected with malware, running BitTorrent, or getting hit by an aggressive web crawler, the IP connection tracking table explodes.

The -cn domain aggregates active firewall connections per source IP:

# Identify the top 5 connection holders on the network
$ mktxp diag -en MKT-CORE -cn --top 5
+----------------------+--------------+------------------+------------------------------------+
|      dhcp_name       | src_address  | connection_count |           dst_addresses            |
+======================+==============+==================+====================================+
| Workstation-Pro      | 10.20.10.88  |       482        | 198.51.100.1, 203.0.113.50, ...    |
|                      |              |                  |                                    |
| Apple-TV (Living Rm) | 10.20.10.145 |       118        | 198.51.100.25, 203.0.113.88, ...   |
|                      |              |                  |                                    |
| Home-Server          | 10.20.10.50  |        94        | 198.51.100.10, 192.0.2.14, ...     |
|                      |              |                  |                                    |
+----------------------+--------------+------------------+------------------------------------+
Matching source addresses: 3 (Total: 42)
Matching open connections: 694 (Total: 1170)

You can also use --min-conns 50 to filter out lightweight background connections and focus only on high-socket hosts. (Note: Destination addresses are populated when connection_stats_destinations = True is enabled in mktxp.conf.)


4. “Am I under attack? Show me dynamic firewall bans.”

If you run honeypots or automated firewall drop rules (e.g., blocking repeated SSH brute-force attempts or port knock scanners), you often want to verify whether malicious IPs are actually being caught and when their timeouts expire.

The -al domain inspects RouterOS firewall address lists:

# Check active dynamic blacklist entries
$ mktxp diag -en MKT-CORE -al blacklist,port_scanners --dynamic-only
Address Lists (IPv4):
+---------------+---------------+--------------------+----------+---------+----------+
|     list      |    address    |      comment       | timeout  | dynamic | disabled |
+===============+===============+====================+==========+=========+==========+
| blacklist     | 198.51.100.42 | SSH brute force    | 23:48:12 |   Yes   |    No    |
| blacklist     | 203.0.113.19  | Port knock scanner | 14:12:05 |   Yes   |    No    |
| port_scanners | 192.0.2.77    | TCP SYN probe      | 01:05:44 |   Yes   |    No    |
+---------------+---------------+--------------------+----------+---------+----------+
Matching entries: 3 (Total: 48)
Unique lists: 2

5. “Who is hogging the bandwidth right now?”

If your uplink starts choking, RouterOS Kid Control provides real-time per-device byte accounting. This view requires Kid Control device tracking to be enabled on RouterOS for the devices you want to observe. The -kc domain pulls these counters, translates them into human-readable transfer rates, and computes aggregate LAN throughput on the fly.

You can instantly surface the top bandwidth consumers:

# Surface the top 5 talkers on the network
$ mktxp diag -en MKT-CORE -kc --top 5
+----------------------+-----------------+------+--------------+-------------------+---------------+-----------+-----------+-----------+
|      dhcp_name       |      name       | user | dhcp_address |    mac_address    |  ip_address   |  rate_up  | rate_down | idle_time |
+======================+=================+======+==============+===================+===============+===========+===========+===========+
| Apple-TV (Living Rm) | Apple-TV-Living |      | 10.20.10.145 | 40:A1:08:12:34:56 | 10.20.10.145  | 1.1 Mbps  | 23.7 Mbps | 2 seconds |
| Workstation-Pro      | Workstation-Pro | Alex | 10.20.10.88  | 3C:06:30:AB:CD:EF | 10.20.10.88   | 180 kbps  | 4.1 Mbps  | 5 seconds |
| Kid-Tablet           | Kid-Tablet      | Kids | 10.20.10.210 | 74:83:C2:55:66:77 | 10.20.10.210  | 45 kbps   | 2.1 Mbps  | 12 seconds|
| Laptop-Guest         | Laptop-Guest    |      | 10.20.10.199 | B8:27:EB:11:22:33 | 10.20.10.199  | 12 kbps   | 520 kbps  | 30 seconds|
| Smart-TV-Office      | Smart-TV-Office |      | 10.20.10.160 | 50:C7:BF:88:99:AA | 10.20.10.160  | 8 kbps    | 310 kbps  | 1 minute  |
+----------------------+-----------------+------+--------------+-------------------+---------------+-----------+-----------+-----------+
Active LAN Traffic: 1.3 Mbps Up / 30.7 Mbps Down
Top 5 Kid Control devices by rate (Matching: 18, Total: 18)

If you want to track specific bandwidth thresholds, mktxp diag supports composite parameters, allowing you to combine --top 5 with --rate-above 2M to ignore low-bandwidth trickle traffic. You can also narrow results to dynamic auto-discovered Kid Control entries versus manually configured static entries using --dynamic-only or --static-only.


RouterOS Netwatch is commonly used for ICMP ping checks against upstream DNS providers, WAN gateways, or remote tunnel endpoints.

Instead of scanning through logs or scripting alerts:

# Show only failed or unreachable Netwatch probes
$ mktxp diag -en MKT-CORE -nw --down-only
Netwatch Entries:
+-----------+---------+-------------------+--------+------+----------+---------+----------+
|   name    |  host   |      comment      | status | type |  since   | timeout | interval |
+===========+=========+===================+========+======+==========+=========+==========+
| gw-backup | 1.1.1.1 | Cloudflare Backup |  Down  | icmp | 00:14:32 | 1000ms  |   10s    |
+-----------+---------+-------------------+--------+------+----------+---------+----------+
Matching entries: 1 (Total: 6)
Up: 0
Down: 1

Thoughtful CLI Ergonomics

Diagnostics are only useful if the tool is comfortable to use under pressure. A few ergonomic details were prioritized during this release:

Context-Aware Scoped Help

In many CLI tools, asking for help with -h dumps every flag from every possible subcommand into a wall of 200 lines.

With MKTXP’s new scoped help formatter, when you specify a diagnostic domain, --help intelligently narrows itself down to only the filters relevant to that specific command:

# Shows only Kid Control switches and filters, keeping help compact
$ mktxp diag -en MKT-CORE -kc -h

Config-Driven Help Defaults

Instead of showing generic placeholders like (default: None), the CLI reads your active _mktxp.conf and prints the exact thresholds configured for your environment:

Kid Control Filters (-kc):
  --top [N]             Show top N talkers (default: 10)
  --rate-above [RATE]   Show devices with rate above threshold (default: 1M)

Flexible Flag Abbreviations

You don’t have to memorize exact naming permutations. Standard CLI prefix matching works out of the box—--wifi, --kid, --conn, or --addr all resolve cleanly to their respective commands.

And for muscle memory, mktxp print remains available as a transparent alias for mktxp diag.


Diagnostic Quick Reference

Here is an overview of the primary diagnostic commands and common filter patterns in practice:

# Wireless & CAPsMAN
$ mktxp diag -en ROUTER -wc --low-signal             # Wi-Fi clients with weak signal (default: <= -75 dBm)
$ mktxp diag -en ROUTER -wc --low-rate               # Clients with low negotiated PHY rates
$ mktxp diag -en ROUTER -cc -in "Boardroom Tab"      # Find device: AP, SSID, interface, leased IP
$ mktxp diag -en ROUTER -cc --band 2g --recent 15m   # 2.4 GHz associations in the last 15 min
$ mktxp diag -en ROUTER -cc -in "AP-Office*"         # CAPsMAN clients on APs matching glob

# DHCP lease tracking
$ mktxp diag -en ROUTER -dc --unidentified           # Leases with no hostname and no comment
$ mktxp diag -en ROUTER -dc --dynamic                # Dynamic DHCP assignments only
$ mktxp diag -en ROUTER -dc --inactive-only          # Inactive or waiting leases (offline devices)

# IP connection tracking
$ mktxp diag -en ROUTER -cn --top 10                 # Top 10 connection holders
$ mktxp diag -en ROUTER -cn --min-conns 50           # Filter hosts with at least 50 open connections

# Firewall address lists
$ mktxp diag -en ROUTER -al blacklist --dynamic-only # Active dynamic threat bans & drop lists

# Bandwidth & devices (Kid Control)
$ mktxp diag -en ROUTER -kc                          # Active devices & aggregate LAN throughput
$ mktxp diag -en ROUTER -kc --top 5                  # Surface top 5 talkers
$ mktxp diag -en ROUTER -kc --rate-above 2M          # Only devices active above 2 Mbps
$ mktxp diag -en ROUTER -kc --dynamic-only           # Dynamic auto-discovered entries only

# Upstream link health
$ mktxp diag -en ROUTER -nw --down-only              # Unreachable gateways or failed ICMP probes

# Scoped help
$ mktxp diag -en ROUTER -kc -h                       # Domain-specific filters & configured defaults

Under the Hood: Clean Pipeline Execution

Under the hood, diagnostics follow a consistent, decoupled execution flow from command line entry to terminal presentation:

[ CLI Invocations (e.g. -wc, -kc, -cn) ]
                   │
                   ▼
[ Options Parser (MKTXPOptionsParser) ]
                   │
                   ▼
     [ Dispatcher (MKTXPDispatcher) ]
                   │
                   ▼
  [ Diagnostic Handler (BaseDiagHandler) ]
                   │
                   ▼
       [ RouterEntry API Session ]
                   │
                   ▼
       [ Collect, Enrich & Filter ]
                   │
                   ▼
       [ Responsive ASCII Tables ]

Data enrichment (resolving MAC addresses to DHCP hostnames, translating bps to human-readable network units, parsing durations) happens in decoupled utility layers, with everything being covered by comprehensive unit tests:

Unit & Integration Tests (.venv):
=================== 355 passed in 0.52s ===================

Getting Started

MKTXP 2.0.0 is available today on PyPI, with Homebrew to follow:

# Install or upgrade via pip
❯ pip install --upgrade mktxp

# Or via pipx
❯ pipx install mktxp     # Fresh installation
❯ pipx upgrade mktxp     # Upgrade existing

# Via Homebrew (once formula update merges)
❯ brew install mktxp     # Fresh installation
❯ brew upgrade mktxp     # Upgrade existing

(Note: Homebrew Core currently lists MKTXP 1.2.20 and does not yet install 2.0.0 while the automated formula update is pending.)

If you have a MikroTik router on your desk or in your rack, try pointing mktxp diag at it and see what your network is doing right now.


For full documentation, configuration templates, and examples, visit the MKTXP GitHub Repository.