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

@@ -54,6 +54,7 @@ See [SSE_API.md](docs/SSE_API.md) for complete documentation of the SSE system.
- [Configuration](#configuration)
- [Development](#development)
- [API Reference](#api-reference)
- [MCP Schema](#mcp-schema-endpoint)
- [Device Control](#device-control)
- [Add-on Management](#add-on-management)
- [Package Management](#package-management)
@@ -248,6 +249,49 @@ TEST_HASS_TOKEN=test_token # Test token
## API Reference
### MCP Schema Endpoint
The server exposes an MCP (Model Context Protocol) schema endpoint that describes all available tools and their parameters:
```http
GET /mcp
```
This endpoint returns a JSON schema describing all available tools, their parameters, and documentation resources. The schema follows the MCP specification and can be used by LLM clients to understand the server's capabilities.
Example response:
```json
{
"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", ...]
},
"area": { "type": "string" },
"floor": { "type": "string" }
}
}
},
// ... other tools
],
"prompts": [],
"resources": [
{
"name": "Home Assistant API",
"url": "https://developers.home-assistant.io/docs/api/rest/"
}
]
}
```
Note: The `/mcp` endpoint is publicly accessible and does not require authentication, as it only provides schema information.
### Device Control
#### Common Entity Controls

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();
}