Skip to main content

Let AI Clients Operate the Broker

The Coreflux broker can listen as an MCP (Model Context Protocol) server. An AI client — Cursor, Claude Desktop, or any MCP-capable assistant — connects over HTTP, presents a broker-issued token, and calls tools that map to broker commands and your LoT (Language of Things) Actions. You stay in the editor; the assistant deploys Actions, lists connectors, and inspects topics as a named broker user, with that user’s RBAC. This is a broker configuration feature (Mcp.Enabled), not a LoT connector. There is no DEFINE ROUTE for it. TYPE MCP_SERVER was removed.
Like giving an assistant a badge for the control room. The badge (a bearer token) is minted for a specific operator. Every tool call is checked against that operator’s permissions — not against a shared admin back door.

When to use this

  • You want Cursor or Claude Desktop to deploy LoT, inspect topics, and run broker commands against a live broker
  • You need a least-privilege identity for the assistant (not root) so RBAC still applies
  • You are migrating off a saved TYPE MCP_SERVER connector or an old /sse client URL

Three different MCP surfaces

Coreflux uses MCP in three places. They are not interchangeable: The Coreflux HUB AI assistant does not talk to this MCP server. HUB is a control plane for enabling it and minting tokens — not an MCP client of the broker.
Enable the listener, mint a token for a real broker user, point the client at /mcp, then verify with /health and $SYS/Coreflux/MCP/Info.

Quick Start

The listener starts only when Mcp.Enabled is on and the broker has restarted. Default bind is loopback on the broker host: 127.0.0.1:6278 at path /mcp. In a container, that’s the container’s own loopback. See Docker and Kubernetes.
Add an Mcp block to the broker configuration, then restart:
Mint a token for an existing broker user. The plaintext is returned once in data.token:
Point the AI client at http://127.0.0.1:6278/mcp with Authorization: Bearer <token>.
Probe the unauthenticated health path on the MCP port (this is not the ops /health on port 9100):
A healthy listener returns status: "healthy" and a tools_count. Then subscribe in MQTT Explorer to $SYS/Coreflux/MCP/Info — the retained payload includes http_endpoint and status.

Endpoints

The MCP listener is a separate HTTP port from MQTT and from the operational endpoints (/health, /ready, /info, /metrics on port 9100). Default URL on the broker host:
The server is HTTP-only:
  • Transport is stateless Streamable HTTP. There is no stdio transport.
  • /sse and /message are rejected. There is no SSE compatibility mode.
  • Native TLS for this listener is not in this release. Bind loopback, or terminate TLS in front of a non-loopback bind.
Authenticated requests send:
Anonymous MQTT login is not inherited. A client with no token gets 401 on /mcp and /info. The listener still stays up if you enabled it with zero tokens — every request is refused until you mint one.
A bind outside loopback (0.0.0.0 or a LAN address) sends bearer tokens in the clear. Put TLS in front (a reverse proxy) before exposing the MCP port beyond the broker host.

Docker and Kubernetes

The MCP server has its own HTTP listener. It isn’t a path on the MQTT port (1883) or the WebSocket port (5000). A client URL such as https://broker.example.com/mcp reaches it only when the proxy in front of that host sends /mcp to port 6278. A proxy that sends every path to port 5000 delivers the request to the WebSocket listener instead. Publishing port 6278 isn’t enough on its own. Inside a container, 127.0.0.1 is the container’s own loopback, so a Docker port mapping or a Kubernetes Service can’t reach a listener bound there. The administrator who deploys the broker sets all of these: If you changed Port or Endpoint, use those values instead of 6278 and /mcp.
Add the MCP port and the two variables to the broker service:
The 127.0.0.1: prefix keeps the port off the host’s public interfaces, so only a proxy on the same host reaches it. A proxy in the same Compose network can use broker:6278 and needs no published port.
/health and /info are on the same listener. Route them to 6278 too if operators should reach them through the public host. /info needs a token. The AI client needs only /mcp.

Check the route

From outside the cluster or host, call /mcp without a token:
The MCP listener answers 401 with WWW-Authenticate: Bearer and asks for a token from -createMcpToken. Any other answer, such as a 404 with an empty body, means the request reached a different listener, usually the WebSocket port. Then point the client at the same URL with its bearer token.

Configuration reference

Environment variables override the JSON block. Changes apply on restart.

Environment variables

HUB Advanced also exposes ServerName and ServerVersion. Restrict the tool list from HUB with Expose all tools off and the allow-list picker — write advertised names (get_route_template), not internal command tokens (route_code). Add action_* names with Custom tool.

Bearer tokens

Every MCP HTTP request except GET /health requires a broker-issued bearer token. Tool calls run as the broker user the token was minted for and are checked against that user’s RBAC. These three commands are operator-only. They are not advertised as MCP tools. The username must already exist. Removing a broker user also deletes that user’s tokens. Token names must not contain whitespace (the command parser splits on spaces). The locked built-in AllowMcpTokenManagement admits root, AllowedUserManagement, and AllowedSystemConfiguration — the same flags as other user-management gates. You cannot override that gate with a custom rule; set permission flags instead. See Operation scopes.

Create a token

Publish to $SYS/Coreflux/Command (or run it from Command Console / the broker console):
Optional third argument is lifetime in days (0 = no expiry), overriding Mcp.TokenLifetimeDays. Success envelope (secret redacted here):
Store data.token immediately. -listMcpTokens will never show it again.
MQTT command replies always go to $SYS/Coreflux/Command/Output. The default AllowSubscribeCommandOutput audience is wider than McpTokenManagement, so a user who cannot mint tokens may still read a mint reply. To keep the plaintext off that topic, mint from the broker console or from the HUB MCP tab (HUB keeps the value in the create dialog only). If a token may have been observed, -revokeMcpToken and mint again.
Mint for a least-privilege account. Do not mint for root unless the client should have full operator access.

Point a client at the broker

Put the same JSON shape in the file your client actually reads. "type": "http" is optional in Cursor (it infers HTTP from url) but required in Claude Code and Claude Desktop — without it they skip the entry with no error.
Project file: .cursor/mcp.json (filename is mcp.json, not .mcp.json). Global fallback: ~/.cursor/mcp.json.
Do not commit a minted token. After changing the file, start a new Claude Code session. In Cursor, if the server shows resources but 0 tools, remove the entry, save, and add it back (or quit Cursor) — an empty tools/list result can stay cached in memory; reloading the server is not enough. When the broker binds 0.0.0.0, $SYS/Coreflux/MCP/Info still prints that bind in http_endpoint. HUB substitutes the host it is connected to when offering snippets; a loopback bind is copied as written.

What the tools do

A connected client calls tools/list on /mcp. The exact set is whatever this broker advertises (/health tools_count and $SYS/Coreflux/MCP/Tools). It is not a second copy of $SYS/Coreflux/Command. Typical surface when EnableAllTools is true: Token, license, and password commands are never advertised (-createMcpToken, -listMcpTokens, -revokeMcpToken, -changeUserPassword, -activateLicense, -loadLicense, -refreshLicense, -enroll). User-management tools (add_user, remove_user, change_user_settings, add_user_to_group, remove_user_from_group) are on the default surface. add_user takes a password in its arguments — chat transcripts will see it. Mint the token for a user without user-management permission, or turn EnableAllTools off and omit those names. List-shaped tools default to a concise page of 50 items (items, total, next_cursor). Pass response_format=detailed for full objects.
lot_diagnostic is a process-wide tracing toggle (true / false), not a per-entity report. Use diagnose for health and Action error topics for compile failures.
Clients can call resources/list and resources/read. There is no resources/subscribe (the server is stateless). Unknown URIs return JSON-RPC -32602 (Invalid params).To install the public skill set straight into a coding agent instead, see Agent Skills.Reads require CommandCall on the token’s user. Topic URIs are filtered again by that user’s subscribe rules (Subscribe / SubscribeSys).prompts/list advertises lot_authoring (optional entity_type: action, model, route, rule).

System topics

When the MCP host starts or stops, it republishes two retained topics. Neither payload includes token values, hashes, or the usernames tokens map to.

$SYS/Coreflux/MCP/Info

The live payload lists every advertised tool name. The sample below is abbreviated.
status is running or stopped. A clean shutdown republishes stopped so a stale retain does not claim the server is up.

$SYS/Coreflux/MCP/Tools

An array of { "name": "…" } objects — currently advertised MCP names only, not the full possible catalogue. When EnableAllTools is false and EnabledTools is empty, this topic is an empty list.
These topics are $SYS. Subscribe with an identity that is allowed to read system topics (MQTT Explorer as an admin user). HUB maps status: "running" to Listening. If Info is missing after a saved, applied Mcp.Enabled: true, HUB still treats the server as Listening rather than as another pending restart.
The ops HTTP /info on port 9100 (separate from MCP /info on 6278) includes a compact mcp object when the feature is enabled (enabled, endpoint, bind, port, toolsCount, tokensActive, auth) — still no token secrets. See Operational endpoints.

Moving off TYPE MCP_SERVER and SSE

A saved project that still carries DEFINE ROUTE … WITH TYPE MCP_SERVER fails to load with a message that the type was removed. The MCP client connector (TYPE MCP, ADD MCP_CONFIG, CALL MCP) is unchanged. Action:
  1. Remove the TYPE MCP_SERVER definition from the project.
  2. Enable Mcp.Enabled (or COREFLUX_MCP_ENABLED=1) and restart the broker.
  3. Mint a token: -createMcpToken <username> <token-name>.
  4. Point the client at http://127.0.0.1:6278/mcp (or your bind, port, and endpoint) with Authorization: Bearer <token>.
There is no compatibility mode. Every existing /sse client configuration stops working.

Best practices

Mint a dedicated broker user for the assistant. Leave user-management and AllowedSystemConfiguration off unless the client must administer the broker. Prefer EnableAllTools: false plus an allow-list of the tools that job needs.
Keep BindIP at 127.0.0.1 when the AI client runs on the same host as the broker. Only bind a LAN address when a remote client must connect, and terminate TLS in front. In a container, bind 0.0.0.0 and reach the port only through the TLS proxy. See Docker and Kubernetes.
Prefer the HUB create-token dialog or the broker console over MQTT when other administrators share $SYS/Coreflux/Command/Output. Revoke and re-mint if a token may have leaked into a chat log.
MCP /health is on the MCP port (default 6278). Orchestrator probes for the broker process still use ops /health on port 9100. See Operational endpoints.
The MCP server does not speak OAuth 2.0 / OIDC. Identity is the minted bearer token only. An OIDC access token used as an MQTT password is a different credential and is not accepted on /mcp. Don’t publish the MCP port directly on the internet. Reach it only through a proxy that terminates TLS.

Next Steps

MCP Connectors

Connect the broker as a client to external MCP servers and call their tools from LoT Actions.

System Configuration

Enable the listener and mint tokens from the Coreflux HUB MCP tab.
Last modified on October 21, 2026