mqtt-readonly-mcp
Provides listen-only tools for MQTT brokers, enabling inspection of live traffic: topic lists, topic trees, broker statistics, latest values, recent messages, message rates, and waiting for new messages. Supports wildcards, redaction, allow/ignore filters, and a rolling buffer.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mqtt-readonly-mcpwhich topic is flooding the broker right now?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mqtt-readonly-mcp
First attempt. This is an early, hobby-grade release: it works on the author's own Home Assistant setup and has a test suite, but it has not been used by many people or on many brokers. Expect rough edges, and please read the disclaimer before you point it at anything you care about.
A small listen-only MQTT tool for Claude Code and other MCP clients.
Purpose
The goal is to let an AI assistant watch the traffic on a smart-home MQTT broker live, understand it, and then help you bring that traffic under control through Home Assistant.
The tool itself only listens. It shows the assistant what Home Assistant, Zigbee2MQTT, Frigate and your devices are publishing: which topics are chatty, what a sensor sends when something happens, how busy the broker is. The assistant then uses that picture, together with Home Assistant, to change things: for example lowering a presence radar's update rate or turning down a noisy Zigbee2MQTT log level. Those changes are made through Home Assistant (or Zigbee2MQTT), not through this tool, and they need your approval like any other change the assistant proposes.
server.py: an MCP server (stdio). Keeps a rolling buffer of what the broker publishes, so the assistant can ask "what did topic X send in the last N minutes?".stream.py: prints one line per message, for Claude Code's Monitor tool (live notifications in the chat).mqtt_common.py: shared code (buffer, redaction, payload formatting, connection).
Neither program contains any publish code. tests/test_no_publish.py fails if publish-like code appears in them.
Related MCP server: MQTT MCP Server
What it is good for
It was built to answer questions like these on a real smart home:
Which device is flooding the broker? (
mqtt_ratesfound that one presence radar produced 87% of about 1,400 messages per minute; after the radar's update rate was lowered in Home Assistant, traffic fell to about a fifth.)Did the Zigbee2MQTT change I just made actually reduce traffic?
What exactly does this sensor publish when the door opens? (
mqtt_wait)
Redaction: on by default, how to switch it
Message payloads end up in the AI conversation, and MQTT carries secrets (the Zigbee2MQTT network key, camera passwords in URLs, API tokens). So redaction is on by default.
You want | Set |
Secrets scrubbed (default) | nothing, or |
Payloads exactly as published |
|
Set it in the environment of the server, for example when registering with Claude Code:
claude mcp add --scope user mqtt-readonly -e MQTT_RO_HOST=192.168.1.10 -e MQTT_RO_REDACT=0 -- /path/to/.venv/bin/python /path/to/server.pyTo turn redaction back on, remove that variable or set MQTT_RO_REDACT=1, then restart the server (in Claude Code, reload the session). The same variable controls stream.py. Details of what is scrubbed are in Redaction below. Turn it off only on a broker whose traffic you are happy to paste into a chat.
Requirements
Python 3.10 or newer
An MQTT broker you can log in to. Create a separate login for this tool.
pip install -r requirements.txt(mcpis pinned below 2 because version 2 renamed the server API)
Setup
Create a virtual environment and install the requirements.
python -m venv .venv .venv/bin/pip install -r requirements.txt # Windows: .venv\Scripts\pipPut the broker login in a credentials file that is not inside this project. The default location is
~/.config/mqtt-readonly/credentials.json:{"username": "mqtt_readonly", "password": "..."}Restrict it to your own account (
chmod 600, oricaclson Windows). The tool never prints it.Register the server with Claude Code. The password is not on the command line:
claude mcp add --scope user mqtt-readonly \ -e MQTT_RO_HOST=192.168.1.10 -e MQTT_RO_PORT=1883 \ -- /path/to/.venv/bin/python /path/to/server.pyAny other MCP client works the same way: run
python server.pyover stdio with the environment variables below.
Environment variables
Variable | Default | Meaning |
|
| Broker address |
|
| Broker port |
|
| Credentials file |
| unset |
|
|
| Comma-separated subscription filters |
| empty (allow all) | Comma-separated topic filters this tool may see at all (see below) |
| empty | Comma-separated topic filters to skip (noisy sources) |
|
| Messages kept in the rolling buffer |
|
|
|
The connection is plain MQTT. There is no TLS option yet, so use it on a trusted network.
Tools
Tool | What it does |
| Connection state, buffer fill, uptime |
| Topics seen, newest first, with counts |
| Topic tree: topics grouped by their first |
| Broker statistics from |
| Latest value per matching topic (includes retained values) |
| Messages from the buffer, oldest first |
| Messages per minute, busiest first: finds chatty topics |
| Waits for NEW messages (max 60 s) |
MQTT wildcards + and # work in every filter. Retained messages (replayed on connect) go only into the last-value map, not the buffer. Responses are capped at 20,000 characters.
Limiting what it can see (MQTT_RO_ALLOW)
By default the tool subscribes to # and can read every topic your login can. Set MQTT_RO_ALLOW to a comma-separated list of topic filters to make that a hard limit:
MQTT_RO_ALLOW=zigbee2mqtt/#,alarm/#,$SYS/#The server only subscribes to filters inside the allow list, and drops any message outside it before it is stored.
stream.pyreads the same variable and refuses ([ERROR], exit code 2) any--filterthe allow list does not cover, so the Monitor tool cannot widen access.MQTT_RO_FILTERSonly chooses what the server subscribes to.MQTT_RO_ALLOWis the limit that also constrainsstream.py.Include
$SYS/#if you wantmqtt_broker_statsto work.
This restricts the tool, not your broker login. For enforcement on the broker itself, use an ACL (see "What read-only means here").
Broker statistics
The server also subscribes to $SYS/# (the # filter alone does not match $SYS topics). Mosquitto publishes these roughly every 10 seconds, so only the latest value of each is kept and they never fill the message buffer. mqtt_broker_stats reports a short list of the useful figures. If the broker publishes no $SYS topics, or your login may not read them, the tool says so rather than failing. Other brokers use different $SYS names, so the output may be sparse there.
Redaction
Message payloads end up in the AI conversation, and MQTT carries secrets: the Zigbee2MQTT network key, camera passwords in URLs, API tokens. So redaction is on by default:
JSON values whose key contains
pass,secret,token,key,psk,authorcredentialbecome[REDACTED], at any depth.The same pattern is applied to non-JSON text (
key=value), anduser:password@inside URLs is masked.zigbee2mqtt/bridge/*topics (exceptbridge/state) report their size only, because they carry network and device configuration.Redaction runs before a payload is trimmed or stored, so a secret cannot survive a cut.
Binary payloads (camera JPEGs) are shown as
[binary N bytes].
Redaction is pattern based. It will miss a secret that sits under an unusual key name, so treat it as a safety net, not a guarantee. Set MQTT_RO_REDACT=0 only on a broker whose traffic you are happy to paste into a chat. JSON is re-serialised compactly when redaction is on, so spacing differs from the original.
Monitor (live stream)
python stream.py --filter "zigbee2mqtt/#" --exclude "zigbee2mqtt/bridge/#" --max-per-minute 30 --seconds 120Each printed line becomes a chat notification when run through Claude Code's Monitor tool, so a per-minute cap applies and the excess is summarised as [suppressed N messages ...]. It prints [ERROR] ... and exits if credentials are missing, the login fails, or the broker cannot be reached. Retained replay is skipped unless you pass --retained.
What "read-only" means here
The code has no publish path, and a test enforces that. But the broker login can still publish unless you restrict it on the broker. For real enforcement, give the login read access only. With Mosquitto, an ACL file like this does it:
user mqtt_readonly
topic read #Be careful: once you enable acl_file, every other user and client must also be listed in it, or they lose access. Back up the broker configuration first.
Known limits
The buffer holds 5,000 messages by default. A very chatty device shortens the window; use
MQTT_RO_IGNOREor lower that device's update rate.mqtt_ratesreports the effective window.The buffer only holds what arrived while the server was running.
No TLS and no MQTT 5 specific features.
Tests
Most tests run without a broker. The integration tests need a throwaway broker and skip themselves when it is not running:
docker run -d --rm --name mqtt-ro-test -p 18830:1883 eclipse-mosquitto:2 mosquitto -c /mosquitto-no-auth.conf
python -m unittest discover -s tests -t .
docker stop mqtt-ro-test(Git Bash on Windows needs MSYS_NO_PATHCONV=1 in front of docker run.) tests/demo_publisher.py publishes sample messages to that test broker so the Monitor tool has something to stream. It is a test helper and is not part of the server.
Acknowledgments
Pat (OdorDecoder): idea, requirements, testing on a real Home Assistant installation, and every decision about what the tool should and should not do.
Claude (Anthropic's AI assistant, used through Claude Code): wrote the code, tests and documentation in collaboration with Pat.
Built on the MCP Python SDK, Eclipse Paho MQTT client and Eclipse Mosquitto (used as the throwaway test broker).
Ideas for features came from looking at descriptions of other MQTT MCP servers: mcmqtt, tspspi/mcpMQTT and rsbohn/mqtt-bridge. No code was copied from them, and thanks to their authors for showing what is useful.
Disclaimer: use at your own risk
This is a first attempt, shared as is, under the MIT license, which already says the software comes without warranty of any kind. In plain words:
The author takes no responsibility for anything that goes wrong from using, misusing or relying on this software. That includes, without limit, exposed secrets or private data, a broker or smart-home device that misbehaves or loses access, wrong advice from an AI assistant that uses this tool, and any cost or damage that follows.
The tool is read-only in its own code, but your broker login may still be able to publish unless you restrict it on the broker. See "What read-only means here".
Redaction is pattern based and can miss a secret. Do not rely on it as your only protection. Review what you send to any AI service.
Test on a non-critical setup first, and take a backup before changing your broker or Home Assistant configuration.
A note on personal information
Care was taken to scrub this repository of personal information: the author's network addresses, file paths, credentials and device names were removed from the code, tests and documentation, and the full git history was checked for secrets before publishing. The example values you see (such as 192.168.1.10, mqtt_readonly or the fake passwords in the tests) are placeholders. No scrub is perfect, so if you spot something that should not be here, please open an issue.
License
MIT, see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Live browser debugging for AI assistants — DOM, console, network via MCP.
- SpanlyOAuthcom.spanly
MCP observability. Query live traffic, errors, duration, and alerts from your AI agent.
- OnsombleOAuthai.onsomble
Track how AI assistants talk about your brand and market, and learn how to show up better.
Heartbeat and tokens/sec monitoring for self-hosted LLM servers (Ollama etc.), with down alerts.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables AI assistants to publish and subscribe to MQTT topics with configurable transport options (STDIO, Streamable HTTP, SSE), supporting both local development and web deployments with flexible broker authentication.2MIT
- AlicenseNot gradedqualityDmaintenanceConnects AI assistants to MQTT brokers for smart home automation and IoT device control, enabling topic discovery, sensor reading, command sending, and event monitoring.2MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to control Home Assistant via natural language, including device control, automation management, and system monitoring.MIT
- AlicenseAqualityAmaintenanceEnables AI agents to query MQTT message history stored in SQLite, including topic inventories, last values, historical data, silent devices, and collector connection gaps. Supports publishing messages when write mode is enabled.9MIT