Files
homelable/mcp/app/main.py
T
Pouzor 7935b671d3 feat: add MCP server with HTTP/SSE transport for AI integration
Exposes homelab topology to MCP-compatible AI clients (Claude Code, etc.)
over LAN via HTTP/SSE on port 8001.

- New mcp/ service: FastAPI + mcp SDK, SSE transport
- Auth: X-API-Key for AI clients, X-MCP-Service-Key for backend (Docker-internal)
- Resources: canvas, nodes, edges, scan/pending, scan/runs
- Tools: create/update/delete nodes+edges, trigger scan, approve/hide devices
- Backend deps.py: accepts JWT or MCP service key (no plain-text password)
- 40 tests (auth, resources, tools) across asyncio + trio
- docker-compose.yml: mcp service on port 8001
- README: MCP setup section with Claude Code/Desktop config examples
2026-03-13 16:41:34 +01:00

44 lines
1.1 KiB
Python

from contextlib import asynccontextmanager
from fastapi import FastAPI
from mcp.server import Server
from mcp.server.sse import SseServerTransport
from .auth import ApiKeyMiddleware
from .backend_client import backend
from .resources import register_resources
from .tools import register_tools
mcp_server = Server("homelable")
register_resources(mcp_server)
register_tools(mcp_server)
@asynccontextmanager
async def lifespan(app: FastAPI):
await backend.start()
yield
await backend.stop()
app = FastAPI(title="Homelable MCP", lifespan=lifespan)
app.add_middleware(ApiKeyMiddleware)
sse = SseServerTransport("/mcp/messages")
@app.get("/mcp")
async def mcp_sse(request):
async with sse.connect_sse(request.scope, request.receive, request._send) as streams:
await mcp_server.run(streams[0], streams[1], mcp_server.create_initialization_options())
@app.post("/mcp/messages")
async def mcp_messages(request):
await sse.handle_post_message(request.scope, request.receive, request._send)
@app.get("/health")
async def health():
return {"status": "ok"}