Add MCP Schema Endpoint for API Discovery

- Implemented `/mcp` endpoint to expose server capabilities
- Created `src/mcp/schema.ts` with comprehensive tool and resource definitions
- Updated README.md with MCP Schema documentation
- Modified security middleware to allow unauthenticated access to schema endpoint
- Included detailed tool descriptions for list_devices, control, and event subscription
This commit is contained in:
jango-blockchained
2025-02-01 06:42:16 +01:00
parent aa911c179d
commit 155a6ea5ba
4 changed files with 171 additions and 2 deletions

View File

@@ -6,6 +6,7 @@ import { sseManager } from './sse/index.js';
import { ILogger } from "@digital-alchemy/core";
import express from 'express';
import { rateLimiter, securityHeaders, validateRequest, sanitizeInput, errorHandler } from './security/index.js';
import { MCP_SCHEMA } from './mcp/schema.js';
// Load environment variables based on NODE_ENV
const envFile = process.env.NODE_ENV === 'production'
@@ -42,6 +43,12 @@ app.use(sanitizeInput);
// Initialize LiteMCP
const server = new LiteMCP('home-assistant', '0.1.0');
// MCP schema endpoint - no auth required as it's just the schema
app.get('/mcp', (_req, res) => {
// Return the MCP schema without requiring authentication
res.json(MCP_SCHEMA);
});
// Health check endpoint
app.get('/health', (req, res) => {
res.json({

118
src/mcp/schema.ts Normal file
View File

@@ -0,0 +1,118 @@
import { z } from 'zod';
import { DomainSchema } from '../schemas.js';
export const MCP_SCHEMA = {
tools: [
{
name: "list_devices",
description: "List all devices connected to Home Assistant",
parameters: {
type: "object",
properties: {
domain: {
type: "string",
enum: [
"light",
"climate",
"alarm_control_panel",
"cover",
"switch",
"contact",
"media_player",
"fan",
"lock",
"vacuum",
"scene",
"script",
"camera"
]
},
area: { type: "string" },
floor: { type: "string" }
},
required: []
}
},
{
name: "control",
description: "Control Home Assistant entities (lights, climate, etc.)",
parameters: {
type: "object",
properties: {
command: {
type: "string",
enum: [
"turn_on",
"turn_off",
"toggle",
"open",
"close",
"stop",
"set_position",
"set_tilt_position",
"set_temperature",
"set_hvac_mode",
"set_fan_mode",
"set_humidity"
]
},
entity_id: { type: "string" },
state: { type: "string" },
brightness: { type: "number" },
color_temp: { type: "number" },
rgb_color: {
type: "array",
items: { type: "number" },
minItems: 3,
maxItems: 3
},
position: { type: "number" },
tilt_position: { type: "number" },
temperature: { type: "number" },
target_temp_high: { type: "number" },
target_temp_low: { type: "number" },
hvac_mode: { type: "string" },
fan_mode: { type: "string" },
humidity: { type: "number" }
},
required: ["command", "entity_id"]
}
},
{
name: "subscribe_events",
description: "Subscribe to Home Assistant events via SSE",
parameters: {
type: "object",
properties: {
events: {
type: "array",
items: { type: "string" }
},
entity_id: { type: "string" },
domain: { type: "string" }
},
required: []
}
},
{
name: "get_sse_stats",
description: "Get statistics about SSE connections",
parameters: {
type: "object",
properties: {},
required: []
}
}
],
prompts: [],
resources: [
{
name: "Home Assistant API",
url: "https://developers.home-assistant.io/docs/api/rest/"
},
{
name: "Home Assistant WebSocket API",
url: "https://developers.home-assistant.io/docs/api/websocket"
}
]
};

View File

@@ -127,8 +127,8 @@ export class TokenManager {
// Request validation middleware
export function validateRequest(req: Request, res: Response, next: NextFunction) {
// Skip validation for health endpoint
if (req.path === '/health') {
// Skip validation for health and MCP schema endpoints
if (req.path === '/health' || req.path === '/mcp') {
return next();
}