Skip to main content
Glama
index.ts4.1 kB
#!/usr/bin/env node import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import express from "express"; import { registerTools } from "./tools/index.js"; // Server metadata const SERVER_NAME = "homelab-mcp-server"; const SERVER_VERSION = "1.0.0"; /** * Create and configure the MCP server */ function createServer(): McpServer { const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }); // Register all homelab tools registerTools(server); return server; } /** * Run server with stdio transport (for Claude Code, local integrations) */ async function runStdio(): Promise<void> { const server = createServer(); const transport = new StdioServerTransport(); await server.connect(transport); // Log to stderr (stdout is reserved for MCP protocol) console.error(`${SERVER_NAME} v${SERVER_VERSION} running on stdio`); } /** * Run server with HTTP transport (for remote access, multiple clients) */ async function runHTTP(): Promise<void> { const server = createServer(); const app = express(); app.use(express.json()); // Health check endpoint app.get("/health", (_req, res) => { res.json({ status: "ok", server: SERVER_NAME, version: SERVER_VERSION }); }); // MCP endpoint - stateless JSON mode app.post("/mcp", async (req, res) => { const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, enableJsonResponse: true }); res.on("close", () => transport.close()); await server.connect(transport); await transport.handleRequest(req, res, req.body); }); const port = parseInt(process.env.PORT || "3000", 10); const host = process.env.HOST || "127.0.0.1"; app.listen(port, host, () => { console.error(`${SERVER_NAME} v${SERVER_VERSION} running on http://${host}:${port}/mcp`); }); } /** * Print usage information */ function printUsage(): void { console.log(` ${SERVER_NAME} v${SERVER_VERSION} MCP server for managing homelab Docker infrastructure across multiple hosts. USAGE: node dist/index.js [--stdio | --http] OPTIONS: --stdio Run with stdio transport (default, for Claude Code) --http Run with HTTP transport (for remote access) --help Show this help message CONFIGURATION: Create a config file at one of these locations (checked in order): 1. Path specified by HOMELAB_CONFIG_FILE env var 2. ./homelab.config.json (current directory) 3. ~/.config/homelab-mcp/config.json 4. ~/.homelab-mcp.json Example config file: { "hosts": [ {"name": "unraid", "host": "unraid.local", "port": 2375, "protocol": "http"}, {"name": "proxmox", "host": "proxmox.local", "port": 2375, "protocol": "http"}, {"name": "local", "host": "localhost", "dockerSocketPath": "/var/run/docker.sock"} ] } ENVIRONMENT VARIABLES: HOMELAB_CONFIG_FILE Path to config file (optional, overrides default paths) HOMELAB_HOSTS_CONFIG JSON config as env var (fallback if no config file) PORT HTTP server port (default: 3000) HOST HTTP server bind address (default: 127.0.0.1) CLAUDE CODE CONFIG (~/.claude/claude_code_config.json): { "mcpServers": { "homelab": { "command": "node", "args": ["/path/to/homelab-mcp-server/dist/index.js"], "env": { "HOMELAB_CONFIG_FILE": "/path/to/your/homelab.config.json" } } } } `); } // Main entry point const args = process.argv.slice(2); if (args.includes("--help") || args.includes("-h")) { printUsage(); process.exit(0); } const transport = args.includes("--http") ? "http" : "stdio"; if (transport === "http") { runHTTP().catch((error) => { console.error("Server error:", error); process.exit(1); }); } else { runStdio().catch((error) => { console.error("Server error:", error); process.exit(1); }); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jmagar/homelab-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server