MCP Servers
The Cedalo MQTT Platform ships with built-in MCP servers. They let an AI assistant such as Cursor or Claude Desktop read your platform inventory and your broker metrics directly, so you can ask questions about your deployment in plain language instead of clicking through the Platform UI or writing API calls.
What is MCP?
MCP (Model Context Protocol) is an open standard that lets an AI assistant call external tools in a structured way. Without MCP, an assistant can only work with what it already knows or what it finds on the web. With MCP, it can ask a system for live data and answer from that data.
Each tool has a name, a set of typed inputs, and a defined output. The assistant decides which tool fits your question, calls it, and answers using the result.
The MCP tools live on the same website as the Platform UI. To get the address,
open the Platform UI in your browser and copy the start of the URL (the part
before /app). Then add /api/mcp. Include the port if you see one in the
browser. Standard HTTPS (port 443) does not need a port.
Cedalo Cloud and a typical local setup. The Platform UI is at the root of the address:
- Local Docker Compose (default):
http://localhost:3000/api/mcp - Cloud:
https://<your-cloud-host>/api/mcp
On-premises. The Platform UI usually sits under /mqtt-platform so it can
share a server with the broker and other Cedalo products. If the UI opens at
https://<your-server>/mqtt-platform, the MCP address is:
https://<your-server>/mqtt-platform/api/mcp
Use that full address in Cursor, Claude, or similar tools. The extra
/mqtt-platform is only how the site is installed on the server. It is not
an extra MCP feature or a license setting. Your browser already includes it;
an AI client does not, so you have to type it.
The prefix is a deployment URL namespace, not an MCP or license requirement.
On-prem Platform typically shares a host (and reverse proxy) with the broker and
other Cedalo services. /mqtt-platform keeps / and /api free for those
services, uses one hostname and TLS certificate, and avoids colliding with the
broker’s /api. The browser prepends NEXT_PUBLIC_BASE_PATH; an external MCP
client (Cursor, Claude, curl) does not, so you must include it in the URL.
You point your AI client at that address, add an API token, and the tools appear in the client.
All tools are read-only. They query projects, brokers, certificates, and metrics. They never create, change, or delete anything in your deployment.
The two MCP servers
The endpoint hosts two independent servers. You can run either one or both.
| Server | Tool names | What it answers |
|---|---|---|
| MCP Platform | platform_* | What exists in my deployment — projects, brokers, certificates, plugins, bridges, topics. |
| MCP Prometheus | prometheus_* | How is it behaving — client counts, throughput, historical trends. |
MCP Platform
The Platform server answers inventory and configuration questions:
- Projects — the projects your token can reach, with broker counts and links.
- Brokers — broker inventory for a project: edition, host, version, liveness, connected clients, and recent traffic.
- Certificates — the project's TLS certificate pool with expiry status
(
expired,expiring_soon,ok,unknown), validity dates, and best-effort usage tags (ca,broker-tls,client-mtls,unused). - Plugins — the plugins loaded on a broker.
- Bridges — the MQTT bridges configured on a broker, with status and topic mappings.
- Topics — the live publish and subscribe topic tree of a broker, including a payload preview and publish rate. This requires the topic tree plugin on the broker.
Some of these have a second form that renders an interactive widget inside the chat — a sortable broker table, a certificate expiry calendar, a collapsible topic tree — instead of plain text. Ask to show or display something to get the widget; ask to list something to get text. Widgets need a client that supports inline MCP views; other clients fall back to the text answer.
MCP Prometheus
The Prometheus server answers questions about broker behaviour over time, using the platform's Prometheus integration:
- Health — whether the Prometheus integration is configured and reachable.
- Monitored brokers — which brokers Prometheus is currently scraping, and whether each one is up.
- Metric catalog — the metrics available, with units and descriptions.
- Current values — the latest value of one or more metrics for one or more brokers.
- Historical series — values over a time range, for charts and trends.
- Custom windows — an aggregate over a time window you choose, such as an average or a rate over the last 17 minutes.
The assistant never writes raw queries. It picks metrics from the catalog, which keeps answers consistent and avoids invented metric names.
Prerequisites
1. A license that includes the MCP features
The MCP servers are enterprise features included in the XL, Trial, and Enterprise plans. The S, M, L, Business, and open-source plans do not include them.
The Platform server and the Prometheus server are licensed separately. Check your current plan under Licenses.
2. Enable the servers
Both servers are off by default. Turn them on with environment variables on the platform service, then restart it.
| Variable | Enables |
|---|---|
MCP_PLATFORM_TOOLS_ENABLED | The MCP Platform server |
MCP_PROMETHEUS_TOOLS_ENABLED | The MCP Prometheus server |
Accepted values, case-insensitive: 1, true, on, yes, enabled. Anything
else, including leaving the variable unset, keeps the server off.
MCP_PLATFORM_TOOLS_ENABLED=true
MCP_PROMETHEUS_TOOLS_ENABLED=true
How you set them depends on the deployment:
- Docker Compose — add the variables to the
environmentsection of theplatformservice, then recreate the container. - Kubernetes — the variables are already defined under
platform.envinvalues.yaml. Set each one you need totrue, then upgrade the Helm release so the platform pod picks up the change.
With both variables off, the endpoint still accepts connections but offers no tools. The AI client will show the server as connected with nothing to call.
An optional variable controls how long a Prometheus tool may run before it gives
up. The default is 15000 milliseconds. Raise it if you regularly query wide time
ranges. In Kubernetes it is also under platform.env in values.yaml.
MCP_PROMETHEUS_TOOL_TIMEOUT_MS=15000
3. An API token
Every request needs an API token. The MCP servers use the same tokens as the REST API, so no separate credential is needed. See API Tokens for how to create one.
Two kinds of token work:
- Project token — bound to one project. This is the recommended choice. The tools automatically scope to that project, so you never have to name a project ID in your prompts.
- Root token — reaches every project on the platform. Use it for administrative tooling. With a root token, the assistant has to name a project for most tools, so mention the project in your prompt.
A token is displayed only once, when you create it. Copy it then and store it somewhere safe. Treat it like a password: anyone holding it can read everything the token is scoped to.
4. Configure your AI client
Add the endpoint and token to your client's MCP configuration file, then restart the client. The tools appear once the client reconnects.
Cursor — ~/.cursor/mcp.json:
{
"mcpServers": {
"cedalo": {
"url": "<platform-base-url>/api/mcp",
"headers": { "Authorization": "Bearer <your-api-token>" }
}
}
}
Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json
on macOS:
{
"mcpServers": {
"cedalo": {
"url": "<platform-base-url>/api/mcp",
"headers": { "Authorization": "Bearer <your-api-token>" }
}
}
}
Use the address from the start of this page. On-prem, that usually includes
/mqtt-platform. On Cloud or a typical local Docker Compose setup, it does
not (http://localhost:3000/api/mcp).
Additional prerequisites for MCP Prometheus
The Prometheus server can only report what Prometheus actually collects, and it finds brokers through the platform. Two things have to be in place.
On the brokers: the Prometheus metrics exporter plugin must be loaded, so each broker exposes metrics for scraping. See Prometheus Metrics Exporter.
In Prometheus: the scrape targets must come from the platform's service discovery API. That API tells Prometheus which broker nodes exist and where their exporter endpoints are, and it is what lets the platform match a metric back to a specific broker.
How to satisfy this depends on how you run Prometheus:
- Default Docker or Kubernetes setup — nothing to do. The setups shipped with this release include Prometheus, already enabled and already configured to discover Pro Edition for Eclipse Mosquitto (Pro Mosquitto) broker nodes through the platform service discovery API.
- Prometheus Operator — configure the platform integration so that Prometheus discovers broker targets through the platform service discovery API, rather than through a hand-written target list or service monitor.
- Any other Prometheus — point it at the platform service discovery API.
If Prometheus discovers brokers by some other means — for example a ServiceMonitor
that scrapes broker pods directly — the metrics are collected, but the platform
cannot associate them with brokers. The Prometheus MCP tools will report no
monitored brokers and return no data. Configure platform service discovery for
those tools to work.
Using the MCP servers
Once the tools are connected, ask questions in plain language. The assistant picks the tool.
| Ask | What you get |
|---|---|
| "List my brokers." | Broker inventory as text, scoped to your token's project. |
| "Show my brokers." | The same inventory as an interactive table. |
| "Which certificates expire in the next 30 days?" | Certificates with expiry status. |
| "Give me a calendar of certificate expiries." | A month-grid calendar widget. |
| "Which bridges are configured on this broker?" | Bridge list with status and topic mappings. |
| "Is monitoring up?" | Prometheus health, then the list of scraped brokers. |
| "How many clients are connected right now?" | Current value of the online-clients metric. |
| "What was the publish rate over the last 17 minutes?" | A custom-window aggregate. |
Tips
Name the tools if the assistant answers from elsewhere. General-purpose assistants sometimes answer from their training data or search the web instead of calling a tool. If that happens, say so directly:
Use the Cedalo MCP tools to answer this.
or
Using the cedalo MCP server, list the brokers in this project.
That is usually enough to redirect it for the rest of the conversation.
Say "show" for widgets, "list" for text. Words like show, view, and display signal that you want the interactive widget. Words like list and which produce a text answer with structured data behind it.
Use a project token for everyday work. It removes the need to mention project IDs and keeps the assistant inside one project.
Ask about metrics before asking for numbers. If you are unsure what is available, ask "which client metrics can you query?" first. The assistant reads the metric catalog and can then use exact metric names.
Keep metric requests focused. Asking for many metrics across many brokers over a long time range at a fine resolution can exceed the request limits. Narrow the time range, widen the interval between points, or split the question.
Start a fresh chat after changing configuration. Clients cache the tool list from when they connected. After enabling a server or replacing a token, restart the client.
Verify the connection
To confirm the endpoint works before involving an AI client, list the available tools directly:
curl -sS <your-mcp-url> \
-H "Authorization: Bearer <your-api-token>" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }'
Use the same MCP address you put in the AI client.
A working setup returns the tools for each enabled server. An empty list means neither server is enabled.
Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| The client shows the server but no tools | Neither server is enabled, or the client cached an empty tool list | Set at least one of the MCP_*_TOOLS_ENABLED variables, restart the platform, then restart the client |
| Requests are rejected as unauthorized | The token is missing, mistyped, expired, or revoked | Create a new token and paste the complete value into the client configuration |
| Requests are rejected because of the license | The plan does not include the enabled features, or the license has expired | Move to XL, Trial, or Enterprise, renew the license, or disable the server your license does not cover |
| The client cannot reach the platform | Wrong address or port, or the platform is not running | Copy the Platform UI address from the browser, add /api/mcp, and check that the platform is reachable from your machine |
| Connection fails, or tools never appear, on on-premises | The URL is missing /mqtt-platform | Use https://<your-server>/mqtt-platform/api/mcp. Do not use /api/mcp on its own |
| The assistant answers without using the tools | The model chose its own knowledge | Ask again and name the MCP server explicitly |
| The assistant asks which project you mean | You are using a root token | Name the project in your prompt, or switch to a project token |
| Prometheus tools report that monitoring is not configured | The platform's Prometheus integration is not set up | Configure the Prometheus integration in the Platform UI admin board |
| No monitored brokers, although Prometheus is running | Prometheus does not discover brokers through the platform service discovery API | Reconfigure Prometheus to use platform service discovery |
| Metric answers are empty for one broker | The broker is not being scraped, or its exporter plugin is not loaded | Ask "which brokers are monitored?" to check, then verify the exporter plugin on that broker |
| A metrics question times out | Too many brokers or metrics, too wide a range, or too fine an interval | Narrow the request, or raise MCP_PROMETHEUS_TOOL_TIMEOUT_MS |
Advanced configuration
Beyond the two enable variables, a small set of optional environment variables
controls what the tools disclose (MCP Platform) and how much data a single
request may pull (MCP Prometheus). They are set in the same place as the enable
variables: the environment section of the platform service in Docker Compose,
or platform.env in values.yaml in Kubernetes.
All defaults are safe for production. Change them only for a concrete reason.
Output disclosure (MCP Platform)
These are boolean flags. Accepted values, case-insensitive: 1, true, on,
yes, enabled and 0, false, off, no, disabled. An unset or blank
value keeps the default.
| Variable | Default | Effect |
|---|---|---|
MCP_PLATFORM_DISCLOSE_NETWORK | true | When set to false, broker host and port, bridge remote addresses, and literal IPv4/IPv6 addresses are omitted from structured output, and IP addresses in free text are replaced with [REDACTED]. Hostnames such as localhost or Docker and Kubernetes DNS names are classified as hostnames, not IPs, and are never redacted. |
MCP_PLATFORM_PAYLOAD_PREVIEW | true | When set to false, payload_preview is omitted from both topic tools. When enabled, the preview is always capped at 256 characters; the cap cannot be raised. |
MCP_PLATFORM_DISCLOSE_CERTS | false | When set to true, certificate results include the filename (basename only), issuer, and subject. Disabled by default because this metadata can fingerprint your PKI. |
MCP_PLATFORM_DISCLOSE_CERTS=true exposes PKI metadata to every valid API
token. Filename, issuer, and subject appear in tool results in any authenticated
assistant session. Enable it only if agents need to reason about certificate
identity or expiry chains.
Request budgets (MCP Prometheus)
These limit the fan-out of a single tool call. Values must be whole integers. Floats, hexadecimal, and scientific notation are rejected and fall back to the default. Values outside the bounds are clamped to the nearest bound, not rejected.
| Variable | Default | Range | Effect |
|---|---|---|---|
MCP_PROMETHEUS_MAX_BROKERS | 20 | 1–100 | Maximum broker or node targets per prometheus_get_metric_points, prometheus_get_metric_series, and prometheus_query_metric call. |
MCP_PROMETHEUS_MAX_METRICS | 50 | 1–200 | Maximum metric IDs per points or series call. |
MCP_PROMETHEUS_MAX_SAMPLES_PER_SERIES | 500 | 1–5000 | Maximum data points per individual series. |
MCP_PROMETHEUS_MAX_TOTAL_SAMPLES | 5000 | 1–200000 | Hard ceiling on brokers × metrics × points for one series call. |
MCP_PROMETHEUS_CATALOG_SUMMARY_IDS | 50 | 1–500 | How many metric IDs the catalog text summary lists before it shortens the rest to +N more. |
Raising the MCP_PROMETHEUS_MAX_* limits has three costs: more load on
Prometheus, larger MCP payloads, and more of the assistant's context window
consumed by raw numbers. Large requests usually hit the tool timeout before the
raised ceiling becomes useful, so a request that fails is more often a sign to
narrow the question — fewer brokers, fewer metrics, a shorter range, or a wider
interval between points — than to raise the budget. Raise the timeout only after
confirming the deadline is the actual bottleneck.
Related variables
| Variable | Default | Effect |
|---|---|---|
MCP_TOOL_TIMEOUT_MS | 15000 | Wall-clock deadline in milliseconds for a single tool action. Exceeding it returns mcp_tool_timeout. |
MCP_TRUST_FORWARDED_ORIGIN | false | When set to true, X-Forwarded-* headers are trusted when building project deep links. Prefer NEXTAUTH_URL or BASE_URL, which take precedence whenever they are set. |
Defaults
The full set of defaults, ready to copy into an .env file:
MCP_PLATFORM_DISCLOSE_NETWORK=true
MCP_PLATFORM_PAYLOAD_PREVIEW=true
MCP_PLATFORM_DISCLOSE_CERTS=false
MCP_PROMETHEUS_MAX_BROKERS=20
MCP_PROMETHEUS_MAX_METRICS=50
MCP_PROMETHEUS_MAX_SAMPLES_PER_SERIES=500
MCP_PROMETHEUS_MAX_TOTAL_SAMPLES=5000
MCP_PROMETHEUS_CATALOG_SUMMARY_IDS=50
Before changing a value
Changes apply only after a restart. All of these variables are read once, when the first MCP subsystem starts. Every later request uses that frozen snapshot. There is no hot reload.
Invalid values are silently replaced. An unrecognised boolean such as
MCP_PLATFORM_DISCLOSE_NETWORK=yes_please logs an [mcp-config] warning and
keeps the default; other flags are unaffected. An out-of-range integer such as
MCP_PROMETHEUS_MAX_TOTAL_SAMPLES=999999 is clamped to 200000 and logs an
[mcp-config] issue. In both cases the server keeps running, so check the
platform log after a change to confirm the value was accepted.
Redaction cannot be turned off. The sanitizer runs on every result regardless of
configuration: secrets, stack traces, absolute filesystem paths, connection
strings, and Prometheus integrator URLs are always stripped. Similarly, license.issued_to and
license.issued_by are always omitted, while plan, edition, and validity dates
are always returned. No environment variable changes this.