Run MQTT.Agent on a local Mosquitto broker
⚠️ Future direction. This guide describes the planned standalone experience using vanilla Mosquitto with no account. The published
@cloudsignal/agentv0.1.1 and@cloudsignal/mcp-over-mqttpackages currently require CloudSignal-style credentials (orgId+tokenServiceUrl); the anonymous-auth variant shown below will land in a future minor release. For working-today code against a CloudSignal-style broker, see@cloudsignal/agentand@cloudsignal/mcp-over-mqtt.
This guide walks you through standing up a complete MQTT.Agent testbed on your laptop: a local Mosquitto broker plus the two reference SDK packages (@cloudsignal/agent and @cloudsignal/mcp-over-mqtt). At the end you will have an MQTT-backed agent calling an MQTT-backed MCP tool, end to end, with no broker account or external service.
Prerequisites
- Docker (for the Mosquitto container) - any recent version.
- Node.js 20 or later.
- A scratch directory to put four files in. No existing project required.
- Familiarity with running shell commands. No prior MQTT knowledge needed.
Steps
1. Create the broker compose file
In your scratch directory, create docker-compose.yml:
services:
mosquitto:
image: eclipse-mosquitto:2
ports:
- "1883:1883"
volumes:
- ./mosquitto.conf:/mosquitto/config/mosquitto.conf2. Create the broker config
Create mosquitto.conf in the same directory:
listener 1883
allow_anonymous trueThis config accepts unauthenticated connections on port 1883. That is fine for a local testbed; do not use it in production.
3. Bring up the broker
docker compose up -dExpected: the container starts and docker compose ps shows mosquitto as running. Port 1883 is now listening on localhost.
4. Install the SDK packages
npm install @cloudsignal/mcp-over-mqtt @cloudsignal/agentExpected: both packages install. The transitive @cloudsignal/mqtt-client lands automatically.
5. Create the tool server
Create tool-server.ts:
import { MCPServer, defineTool } from '@cloudsignal/mcp-over-mqtt';
const echoTool = defineTool({
name: 'echo',
description: 'Echoes input back to the caller.',
input_schema: {
type: 'object',
properties: { text: { type: 'string' } },
required: ['text'],
},
handler: async ({ args }) => ({ echo: args.text }),
});
const server = new MCPServer({
name: 'example-server',
tools: [echoTool],
broker: 'mqtt://localhost:1883',
credentials: { anonymous: true }, // planned
});
await server.start();This registers a single MCP tool called echo that returns whatever text you pass it. The defineTool helper validates the JSON Schema and binds the handler; MCPServer then registers the tool on the broker.
6. Create the agent
Create agent.ts:
import { MCPClient } from '@cloudsignal/mcp-over-mqtt';
const client = new MCPClient({
clientId: 'agent-a',
broker: 'mqtt://localhost:1883',
credentials: { anonymous: true }, // planned
});
await client.start();
const result = await client.call('echo', { text: 'hello' });
console.log(result);The client connects to the same broker, finds the echo tool, and calls it. (In a future SDK release, an Agent instance for A2A peer presence could be created alongside the MCPClient for richer behavior; today's published MCPClient handles the tool-call side cleanly on its own.)
7. Run the tool server
In one terminal:
npx tsx tool-server.tsExpected: the process connects to the broker, publishes its tool card on a retained topic, and stays running while waiting for calls. You should see no errors. Leave this terminal open.
8. Run the agent
In a second terminal:
npx tsx agent.tsExpected: the agent connects, finds the tool, calls it, and prints:
{ echo: 'hello' }The agent process exits after the call completes.
Verification
You have a working MQTT.Agent stack if all of the following are true:
- The Mosquitto container is running (
docker compose ps). - The tool server stays connected without errors.
- The agent prints
{ echo: 'hello' }and exits cleanly.
If the agent hangs or errors, check that the tool server is running and connected to the same broker URL. Both processes must use mqtt://localhost:1883.
Note: this guide is currently aspirational pending a future SDK release adding anonymous-auth support; see the callout at the top of this page.
Next steps
- Replace Mosquitto with EMQX, HiveMQ, VerneMQ, NanoMQ, or any other conforming MQTT 5 broker. The SDK code does not change - only the
brokerfield. - Read the Substrate spec for the topic conventions and identity claims this example uses.
- Read
@cloudsignal/agentand@cloudsignal/mcp-over-mqttfor the full SDK surface. - For a broker that enforces identity-bound ACL at the wire level, see the example on the home page.