fibaro-mcp-server
Version:
Model Context Protocol server for Fibaro Home Center 2 integration with AI assistants
662 lines • 22.1 kB
JavaScript
/**
* Fibaro Home Center 2 MCP Server
*/
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
import dotenv from 'dotenv';
import { FibaroClient } from './fibaro-client.js';
// Load environment variables
dotenv.config();
// Check for version flag
if (process.argv.includes('--version') || process.argv.includes('-v')) {
console.log('1.0.8');
process.exit(0);
}
// Get configuration from environment
const fibaroUrl = process.env.FIBARO_URL || process.env.FIBARO_HOST || '';
const fibaroUsername = process.env.FIBARO_USERNAME || '';
const fibaroPassword = process.env.FIBARO_PASSWORD || '';
const useHttps = process.env.FIBARO_USE_HTTPS === 'true';
// Parse URL to extract host and protocol if FIBARO_URL is provided
let host = fibaroUrl;
let https = useHttps;
if (fibaroUrl.startsWith('http://') || fibaroUrl.startsWith('https://')) {
https = fibaroUrl.startsWith('https://');
host = fibaroUrl.replace(/^https?:\/\//, '').replace(/\/.*$/, '');
}
// Initialize Fibaro client
const fibaroClient = new FibaroClient(host, fibaroUsername, fibaroPassword, https, 30000);
// Initialize MCP server
const server = new Server({
name: 'fibaro-home-center',
version: '0.1.0',
}, {
capabilities: {
tools: {},
},
});
// Define tools
const tools = [
// Device tools
{
name: 'list_devices',
description: 'List all devices in the Fibaro Home Center system',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_device',
description: 'Get detailed information about a specific device',
inputSchema: {
type: 'object',
properties: {
device_id: {
type: 'number',
description: 'The device ID',
},
},
required: ['device_id'],
},
},
{
name: 'control_device',
description: 'Control a device (turn on/off, set value, etc.)',
inputSchema: {
type: 'object',
properties: {
device_id: {
type: 'number',
description: 'The device ID',
},
action: {
type: 'string',
description: "Action to perform (e.g., 'turnOn', 'turnOff', 'setValue')",
},
args: {
type: 'array',
description: 'Optional arguments for the action',
items: {
type: 'string',
},
},
},
required: ['device_id', 'action'],
},
},
// Room tools
{
name: 'list_rooms',
description: 'List all rooms in the Fibaro Home Center system',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_room',
description: 'Get detailed information about a specific room',
inputSchema: {
type: 'object',
properties: {
room_id: {
type: 'number',
description: 'The room ID',
},
},
required: ['room_id'],
},
},
{
name: 'get_room_devices',
description: 'Get all devices in a specific room',
inputSchema: {
type: 'object',
properties: {
room_id: {
type: 'number',
description: 'The room ID',
},
},
required: ['room_id'],
},
},
// Scene tools
{
name: 'list_scenes',
description: 'List all scenes in the Fibaro Home Center system',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_scene',
description: 'Get detailed information about a specific scene',
inputSchema: {
type: 'object',
properties: {
scene_id: {
type: 'number',
description: 'The scene ID',
},
},
required: ['scene_id'],
},
},
{
name: 'trigger_scene',
description: 'Trigger/execute a scene',
inputSchema: {
type: 'object',
properties: {
scene_id: {
type: 'number',
description: 'The scene ID to trigger',
},
},
required: ['scene_id'],
},
},
// System tools
{
name: 'get_system_info',
description: 'Get Fibaro Home Center system information',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_weather',
description: 'Get weather information from Fibaro system',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_location',
description: 'Get location information from Fibaro system',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_diagnostics',
description: 'Get system diagnostics from Fibaro system',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'list_users',
description: 'List all users in Fibaro system',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_user',
description: 'Get a specific user by ID',
inputSchema: {
type: 'object',
properties: {
user_id: {
type: 'number',
description: 'User ID',
},
},
required: ['user_id'],
},
},
{
name: 'list_sections',
description: 'List all sections in Fibaro system',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_section',
description: 'Get a specific section by ID',
inputSchema: {
type: 'object',
properties: {
section_id: {
type: 'number',
description: 'Section ID',
},
},
required: ['section_id'],
},
},
{
name: 'get_energy',
description: 'Get energy consumption for rooms or devices',
inputSchema: {
type: 'object',
properties: {
type: {
type: 'string',
description: 'Type: rooms or devices',
},
id: {
type: 'number',
description: 'ID of room or device',
},
},
required: ['type', 'id'],
},
},
{
name: 'get_temperature_panel',
description: 'Get temperature data for rooms or devices',
inputSchema: {
type: 'object',
properties: {
type: {
type: 'string',
description: 'Type: rooms or devices',
},
method: {
type: 'string',
description: 'Method: single or compare',
},
id: {
type: 'number',
description: 'ID of room or device',
},
},
required: ['type', 'method', 'id'],
},
},
// Global variables tools
{
name: 'list_global_variables',
description: 'List all global variables',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_global_variable',
description: 'Get a specific global variable',
inputSchema: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'Variable name',
},
},
required: ['name'],
},
},
{
name: 'set_global_variable',
description: 'Set a global variable value',
inputSchema: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'Variable name',
},
value: {
type: 'string',
description: 'Variable value',
},
},
required: ['name', 'value'],
},
},
];
// List tools handler
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools };
});
// Call tool handler
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args = {} } = request.params;
try {
// Device tools
if (name === 'list_devices') {
const devices = await fibaroClient.getDevices();
return {
content: [
{
type: 'text',
text: `Found ${devices.length} devices:\n\n${devices
.map((d) => `- ID: ${d.id}, Name: ${d.name}, Type: ${d.type}, Room: ${d.roomID}`)
.join('\n')}`,
},
],
};
}
if (name === 'get_device') {
const device = await fibaroClient.getDevice(args.device_id);
return {
content: [
{
type: 'text',
text: `Device Information:\nID: ${device.id}\nName: ${device.name}\nType: ${device.type}\nRoom ID: ${device.roomID}\nEnabled: ${device.enabled}\nProperties: ${JSON.stringify(device.properties, null, 2)}\nActions: ${JSON.stringify(Object.keys(device.actions || {}), null, 2)}`,
},
],
};
}
if (name === 'control_device') {
const result = await fibaroClient.callAction(args.device_id, args.action, args.args);
return {
content: [
{
type: 'text',
text: `Action executed successfully: ${JSON.stringify(result)}`,
},
],
};
}
// Room tools
if (name === 'list_rooms') {
const rooms = await fibaroClient.getRooms();
return {
content: [
{
type: 'text',
text: `Found ${rooms.length} rooms:\n\n${rooms.map((r) => `- ID: ${r.id}, Name: ${r.name}`).join('\n')}`,
},
],
};
}
if (name === 'get_room') {
const room = await fibaroClient.getRoom(args.room_id);
return {
content: [
{
type: 'text',
text: `Room Information:\nID: ${room.id}\nName: ${room.name}\nSection ID: ${room.sectionID}`,
},
],
};
}
if (name === 'get_room_devices') {
const allDevices = await fibaroClient.getDevices();
const roomDevices = allDevices.filter((d) => d.roomID === args.room_id);
return {
content: [
{
type: 'text',
text: `Found ${roomDevices.length} devices in room:\n\n${roomDevices
.map((d) => `- ID: ${d.id}, Name: ${d.name}, Type: ${d.type}`)
.join('\n')}`,
},
],
};
}
// Scene tools
if (name === 'list_scenes') {
const scenes = await fibaroClient.getScenes();
return {
content: [
{
type: 'text',
text: `Found ${scenes.length} scenes:\n\n${scenes.map((s) => `- ID: ${s.id}, Name: ${s.name}`).join('\n')}`,
},
],
};
}
if (name === 'get_scene') {
const scene = await fibaroClient.getScene(args.scene_id);
// Build basic information
const infoParts = [
'Scene Information:',
`ID: ${scene.id}`,
`Name: ${scene.name}`,
`Type: ${scene.type || 'Unknown'}`,
`Room ID: ${scene.roomID}`,
`Enabled: ${scene.enabled}`,
`Autostart: ${scene.autostart || false}`,
`Run Config: ${scene.runConfig || 'N/A'}`,
`Running Instances: ${scene.runningInstances || 0}`,
`Visible: ${scene.visible !== undefined ? scene.visible : true}`,
`Is Lua Scene: ${scene.isLua || false}`,
];
// Add triggers information if available
const triggers = scene.triggers;
if (triggers) {
infoParts.push('\nTriggers:');
if (triggers.properties && triggers.properties.length > 0) {
infoParts.push(` Properties: ${JSON.stringify(triggers.properties)}`);
}
if (triggers.globals && triggers.globals.length > 0) {
infoParts.push(` Globals: ${JSON.stringify(triggers.globals)}`);
}
if (triggers.events && triggers.events.length > 0) {
infoParts.push(` Events: ${JSON.stringify(triggers.events)}`);
}
if (triggers.weather && triggers.weather.length > 0) {
infoParts.push(` Weather: ${JSON.stringify(triggers.weather)}`);
}
}
// Add actions information if available
const actions = scene.actions;
if (actions) {
infoParts.push('\nActions:');
if (actions.devices && actions.devices.length > 0) {
infoParts.push(` Devices: ${JSON.stringify(actions.devices)}`);
}
if (actions.scenes && actions.scenes.length > 0) {
infoParts.push(` Scenes: ${JSON.stringify(actions.scenes)}`);
}
if (actions.groups && actions.groups.length > 0) {
infoParts.push(` Groups: ${JSON.stringify(actions.groups)}`);
}
}
// Add LUA code if available
const luaCode = scene.lua;
if (luaCode) {
infoParts.push('\nLUA Code:');
infoParts.push('```lua');
infoParts.push(luaCode);
infoParts.push('```');
}
return {
content: [
{
type: 'text',
text: infoParts.join('\n'),
},
],
};
}
if (name === 'trigger_scene') {
const result = await fibaroClient.triggerScene(args.scene_id);
return {
content: [
{
type: 'text',
text: `Scene triggered successfully: ${JSON.stringify(result)}`,
},
],
};
}
// System tools
if (name === 'get_system_info') {
const info = await fibaroClient.getSystemInfo();
return {
content: [
{
type: 'text',
text: `System Information:\nSerial Number: ${info.serialNumber}\nHC Version: ${info.hcVersion}\nPlatform: ${info.platform}\nMAC: ${info.mac}`,
},
],
};
}
if (name === 'get_weather') {
const weather = await fibaroClient.getWeather();
return {
content: [
{
type: 'text',
text: `Weather Information:\n${JSON.stringify(weather, null, 2)}`,
},
],
};
}
if (name === 'get_location') {
const location = await fibaroClient.getLocation();
return {
content: [
{
type: 'text',
text: `Location Information:\n${JSON.stringify(location, null, 2)}`,
},
],
};
}
if (name === 'get_diagnostics') {
const diagnostics = await fibaroClient.getDiagnostics();
return {
content: [
{
type: 'text',
text: `Diagnostics Information:\n${JSON.stringify(diagnostics, null, 2)}`,
},
],
};
}
if (name === 'list_users') {
const users = await fibaroClient.getUsers();
return {
content: [
{
type: 'text',
text: `Found ${users.length} users:\n\n${users.map((u) => `- ID: ${u.id}, Name: ${u.name}, Email: ${u.email}`).join('\n')}`,
},
],
};
}
if (name === 'get_user') {
const user = await fibaroClient.getUser(args.user_id);
return {
content: [
{
type: 'text',
text: `User Information:\nID: ${user.id}\nName: ${user.name}\nEmail: ${user.email}\nType: ${user.type}\nHas GPS: ${user.hasGPS}`,
},
],
};
}
if (name === 'list_sections') {
const sections = await fibaroClient.getSections();
return {
content: [
{
type: 'text',
text: `Found ${sections.length} sections:\n\n${sections.map((s) => `- ID: ${s.id}, Name: ${s.name}`).join('\n')}`,
},
],
};
}
if (name === 'get_section') {
const section = await fibaroClient.getSection(args.section_id);
return {
content: [
{
type: 'text',
text: `Section Information:\nID: ${section.id}\nName: ${section.name}\nSort Order: ${section.sortOrder}`,
},
],
};
}
if (name === 'get_energy') {
const energy = await fibaroClient.getEnergy(args.type, args.id);
return {
content: [
{
type: 'text',
text: `Energy Information:\n${JSON.stringify(energy, null, 2)}`,
},
],
};
}
if (name === 'get_temperature_panel') {
const temperature = await fibaroClient.getTemperaturePanel(args.type, args.method, args.id);
return {
content: [
{
type: 'text',
text: `Temperature Information:\n${JSON.stringify(temperature, null, 2)}`,
},
],
};
}
// Global variables tools
if (name === 'list_global_variables') {
const variables = await fibaroClient.getGlobalVariables();
return {
content: [
{
type: 'text',
text: `Found ${variables.length} global variables:\n\n${variables
.map((v) => `- ${v.name}: ${v.value}`)
.join('\n')}`,
},
],
};
}
if (name === 'get_global_variable') {
const variable = await fibaroClient.getGlobalVariable(args.name);
return {
content: [
{
type: 'text',
text: `Variable: ${variable.name}\nValue: ${variable.value}\nModified: ${variable.modified}`,
},
],
};
}
if (name === 'set_global_variable') {
const result = await fibaroClient.setGlobalVariable(args.name, args.value);
return {
content: [
{
type: 'text',
text: `Variable set successfully: ${JSON.stringify(result)}`,
},
],
};
}
throw new Error(`Unknown tool: ${name}`);
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
});
// Start server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('Fibaro MCP Server running on stdio');
}
main().catch((error) => {
console.error('Server error:', error);
process.exit(1);
});
//# sourceMappingURL=index.js.map