UNPKG

halton-iot-mcp

Version:

MCP Server for Halton IoT Data API

303 lines 9.68 kB
#!/usr/bin/env node /** * Halton IoT MCP Server * Model Context Protocol server for Halton IoT Data API */ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import { HaltonApiClient } from "./api-client.js"; // Get API token from environment variable const API_TOKEN = process.env.HALTON_API_TOKEN; if (!API_TOKEN) { console.error("Error: HALTON_API_TOKEN environment variable is required"); process.exit(1); } const apiClient = new HaltonApiClient(API_TOKEN); // Create server instance const server = new McpServer({ name: "halton-iot", version: "1.0.0", }); // ============ System Tools ============ server.tool("get_all_systems", "Get basic information about all accessible IoT systems", {}, async () => { try { const result = await apiClient.getAllSystems(); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); server.tool("get_systems", "Get basic information about specified IoT systems", { systems: z .array(z.string()) .describe("Array of system IDs to retrieve (e.g., ['FI02728', 'US02145'])"), }, async ({ systems }) => { try { const result = await apiClient.getSystems(systems); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); // ============ Variable Tools ============ server.tool("get_system_variables", "Retrieve a list of variables (sensors/data points) for specified systems", { systems: z .array(z.string()) .describe("Array of system IDs to get variables for"), }, async ({ systems }) => { try { const result = await apiClient.getSystemVariables(systems); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); server.tool("search_variables", "Search for variables across systems using search words", { systems: z.array(z.string()).describe("Array of system IDs to search in"), searchWords: z .array(z.string()) .describe("Array of search terms (e.g., ['Airflow', 'Temperature'])"), pageNumber: z.number().optional().default(1).describe("Page number for pagination"), pageSize: z.number().optional().default(100).describe("Number of results per page"), includeLastEventValues: z .boolean() .optional() .default(false) .describe("Include the last recorded value for each variable"), }, async ({ systems, searchWords, pageNumber, pageSize, includeLastEventValues }) => { try { const result = await apiClient.searchSystemVariables({ systems, searchWords, pagination: { pageNumber: pageNumber ?? 1, pageSize: pageSize ?? 100, orderByType: "Ascending", }, }, includeLastEventValues); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); // ============ Time Series Data Tools ============ server.tool("get_aggregate_data", "Get aggregated time series data for a single variable (includes min, max, avg, median, etc.). Default interval is hourly.", { variable: z.string().describe("The variable name to get data for"), systems: z.array(z.string()).describe("Array of system IDs"), fromDate: z.string().describe("Start date/time in ISO 8601 format"), toDate: z.string().describe("End date/time in ISO 8601 format"), intervalSeconds: z .number() .optional() .default(3600) .describe("Aggregation interval in seconds (default: 3600 = hourly)"), }, async ({ variable, systems, fromDate, toDate, intervalSeconds }) => { try { const result = await apiClient.getAggregateSeries(variable, { systems, dateTimeRange: { from: fromDate, to: toDate, }, intervalSeconds: intervalSeconds ?? 3600, }); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); server.tool("get_aggregate_data_multiple", "Get aggregated time series data for multiple variables. Default interval is hourly.", { variables: z .array(z.string()) .describe("Array of variable names to get data for"), systems: z.array(z.string()).describe("Array of system IDs"), fromDate: z.string().describe("Start date/time in ISO 8601 format"), toDate: z.string().describe("End date/time in ISO 8601 format"), intervalSeconds: z .number() .optional() .default(3600) .describe("Aggregation interval in seconds (default: 3600 = hourly)"), }, async ({ variables, systems, fromDate, toDate, intervalSeconds }) => { try { const result = await apiClient.getAggregateSeriesMultiple({ variables, systems, dateTimeRange: { from: fromDate, to: toDate, }, intervalSeconds: intervalSeconds ?? 3600, }); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); server.tool("get_last_value", "Get the most recent value for a single variable", { variable: z.string().describe("The variable name to get the last value for"), systems: z.array(z.string()).describe("Array of system IDs"), }, async ({ variable, systems }) => { try { const result = await apiClient.getLastEventValue(variable, systems); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); server.tool("get_last_values_multiple", "Get the most recent values for multiple variables", { variables: z .array(z.string()) .describe("Array of variable names to get last values for"), systems: z.array(z.string()).describe("Array of system IDs"), }, async ({ variables, systems }) => { try { const result = await apiClient.getLastEventValueMultiple({ variables, systems, }); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); // ============ Main ============ async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Halton IoT MCP Server running on stdio"); } main().catch((error) => { console.error("Fatal error:", error); process.exit(1); }); //# sourceMappingURL=index.js.map