What is MCP?
Model Context Protocol (MCP) is Anthropic's open standard for connecting AI assistants to external tools and data sources. Instead of just chatting with Claude, you can give it the ability to actually do things - query databases, control smart home devices, trigger deployments, or interact with any API you expose.
For homelab enthusiasts, this is incredibly powerful. Imagine asking Claude Code to "check if my media server is healthy" and having it actually query Prometheus, or saying "restart the broken container" and having it SSH into your server and run the command.
In this article, I'll walk through how I set up MCP servers for my homelab, including a custom gateway for n8n workflows.
How MCP Works
At a high level, MCP servers expose "tools" that Claude can call. When you ask Claude to do something that requires external access, it can invoke these tools and use the results in its response.
There are two main transport mechanisms:
- stdio - The MCP server runs as a local process, communicating via stdin/stdout
- SSE (Server-Sent Events) - The MCP server runs remotely, communicating over HTTP
For homelab use, SSE is usually what you want. Your MCP server can run on your homelab infrastructure and be accessed from any workstation on your network.
Setting Up n8n as an MCP Server
n8n has native MCP support, which means you can expose any n8n workflow as a tool that Claude can call. This is incredibly useful because n8n can already talk to basically everything in your homelab.
Enabling n8n's MCP Server
In n8n, go to Settings → MCP Server and enable it. You'll get a bearer token that clients need to authenticate. Save this somewhere secure - you'll need it for the gateway.
The MCP server exposes an endpoint at /mcp-server/http using the Streamable HTTP transport. The catch is that Claude Code expects SSE, not Streamable HTTP. So we need a gateway to translate between them.
Building an SSE Gateway
I created a simple Express server that bridges SSE to n8n's HTTP endpoint:
const express = require('express');
const { v4: uuidv4 } = require('uuid');
const app = express();
const N8N_MCP_URL = process.env.N8N_MCP_URL;
const N8N_MCP_TOKEN = process.env.N8N_MCP_TOKEN;
// Store active sessions
const sessions = new Map();
// SSE endpoint for Claude Code to connect to
app.get('/sse', (req, res) => {
const sessionId = uuidv4();
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
sessions.set(sessionId, res);
// Send the endpoint URL for this session
res.write(`event: endpoint\n`);
res.write(`data: /messages/${sessionId}\n\n`);
req.on('close', () => sessions.delete(sessionId));
});
// Messages endpoint - proxies to n8n
app.post('/messages/:sessionId', express.json(), async (req, res) => {
const response = await fetch(N8N_MCP_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${N8N_MCP_TOKEN}`
},
body: JSON.stringify(req.body)
});
const data = await response.json();
res.json(data);
});
app.listen(8002);
This runs in a Docker container on my AI server (the same host as n8n) and is exposed through Traefik at n8n-mcp.local.brianrogers.dev.
Configuring Claude Code
Create a .mcp.json file in your home directory or project root:
{
"mcpServers": {
"n8n": {
"type": "sse",
"url": "https://n8n-mcp.local.brianrogers.dev/sse"
}
}
}
Restart Claude Code, and you should see the n8n tools available. Any workflow you've enabled for MCP in n8n will show up as a callable tool.
Creating a Custom Homelab MCP Server
Beyond n8n, I also run a custom MCP server that exposes homelab-specific tools:
- Monitoring - Query Prometheus metrics, check Uptime Kuma status
- Deployments - Trigger Ansible playbooks, run Terraform plans
- Smart Home - Control Home Assistant entities, query sensor data
- Network - Check Orbi router status, view connected devices
The server is a Node.js application that implements the MCP protocol and exposes these capabilities as tools. Each tool has a schema that defines its inputs and outputs, which helps Claude understand how to use them.
Example Tool: Check Service Health
{
"name": "check_service_health",
"description": "Check the health status of a homelab service",
"inputSchema": {
"type": "object",
"properties": {
"service": {
"type": "string",
"description": "Name of the service (e.g., jellyfin, grafana, n8n)"
}
},
"required": ["service"]
}
}
When Claude calls this tool, the server queries Uptime Kuma's API and returns the current status, response time, and recent uptime percentage.
Security Considerations
Exposing your infrastructure to an AI assistant requires some thought about security:
Network isolation. My MCP servers are only accessible on my local network. They're behind Traefik with local DNS - there's no public access.
Principle of least privilege. The tools I expose are mostly read-only. For anything destructive (like restarting services), I require explicit confirmation or limit it to specific safe operations.
Audit logging. Every MCP request is logged so I can see what Claude is doing. This is useful for debugging and for catching any unexpected behavior.
Token rotation. The bearer tokens for n8n and other services are rotated periodically and stored in 1Password.
What Can You Do With This?
Once you have MCP set up, the possibilities are pretty broad:
- "What's the current status of my homelab?" - Claude queries multiple monitoring endpoints and summarizes
- "Show me the CPU usage on the media server for the past hour" - Claude pulls Prometheus metrics and describes the trend
- "Turn off the office lights" - Claude calls Home Assistant through the MCP server
- "Deploy the latest changes to the website" - Claude triggers an n8n workflow that runs the deployment
- "What containers are running on homelab-ai?" - Claude SSHs in (through a tool) and runs docker ps
The key insight is that MCP turns Claude from a chat assistant into an actual operator that can interact with your systems. It's not just answering questions about infrastructure - it's actually querying and controlling it.
Getting Started
If you want to try this yourself, start simple:
- Enable n8n's MCP server if you're already running n8n
- Set up the SSE gateway (or use
npx supergatewayif you don't mind Node.js on your workstation) - Create one simple workflow that does something useful - like checking a service status
- Add the MCP configuration to Claude Code and test it
Once you see it working, you'll probably have a dozen ideas for other tools to add. That's the fun part.