domotz-mcp
Version:
MCP server for Domotz API and BMS (Building Management System) integration with IoT device monitoring
122 lines (121 loc) • 4.63 kB
JavaScript
import mqtt from "mqtt";
import { z } from "zod";
import { MCPTool } from "mcp-framework";
// Store active MQTT connections
const mqttConnections = new Map();
export default class MQTTConnectionTool extends MCPTool {
name = "mqtt_connect";
description = "Connect to an MQTT broker for IoT device communication";
schema = {
broker_url: {
type: z.string(),
description: "MQTT broker URL (e.g., mqtt://localhost, ws://broker.hivemq.com)"
},
client_id: {
type: z.string().optional(),
description: "Client ID for the connection (auto-generated if not provided)"
},
username: {
type: z.string().optional(),
description: "Username for authentication"
},
password: {
type: z.string().optional(),
description: "Password for authentication"
},
port: {
type: z.string().optional(),
description: "Port number (default: 1883 for mqtt, 8083 for ws)"
},
clean_session: {
type: z.boolean().optional(),
description: "Start with clean session (default: true)"
},
keepalive: {
type: z.string().optional(),
description: "Keepalive interval in seconds (default: 60)"
}
};
async execute(params) {
try {
const { broker_url, client_id = `mcp_${Date.now()}`, username, password, port, clean_session = true, keepalive = "60" } = params;
// Close existing connection if any
const existingClient = mqttConnections.get(client_id);
if (existingClient) {
existingClient.end();
mqttConnections.delete(client_id);
}
// Parse broker URL and set default port if not provided
let connectUrl = broker_url;
// Ensure the URL has a protocol
if (!broker_url.startsWith('mqtt://') && !broker_url.startsWith('mqtts://') &&
!broker_url.startsWith('ws://') && !broker_url.startsWith('wss://')) {
// If no protocol specified, assume mqtts:// for port 8883, mqtt:// otherwise
const protocol = port === '8883' ? 'mqtts://' : 'mqtt://';
connectUrl = protocol + broker_url;
}
if (port) {
try {
const url = new URL(connectUrl);
url.port = port;
connectUrl = url.toString();
}
catch (e) {
return {
success: false,
error: `Invalid broker URL: ${broker_url}`
};
}
}
// Connection options
const options = {
clientId: client_id,
clean: clean_session,
keepalive: parseInt(keepalive),
reconnectPeriod: 5000,
};
if (username) {
options.username = username;
options.password = password;
}
// Create connection
const client = mqtt.connect(connectUrl, options);
return new Promise((resolve) => {
const timeout = setTimeout(() => {
client.end();
resolve({
success: false,
error: "Connection timeout after 10 seconds"
});
}, 10000);
client.on("connect", () => {
clearTimeout(timeout);
mqttConnections.set(client_id, client);
resolve({
success: true,
message: "Connected to MQTT broker",
connection_id: client_id,
broker: connectUrl,
status: "connected"
});
});
client.on("error", (error) => {
clearTimeout(timeout);
client.end();
resolve({
success: false,
error: `MQTT connection error: ${error.message}`
});
});
});
}
catch (error) {
return {
success: false,
error: error.message || "Failed to connect to MQTT broker"
};
}
}
}
// Export the connections map for use in other tools
export { mqttConnections };