A production-grade MCP server that gives Claude.ai secure, structured access to your Obsidian vault, n8n workflows, Docker containers, git repos, Homepage dashboard, and infrastructure health — all through 37 purpose-built tools behind OAuth 2.1 authentication. No shell access. No open ports. Every action is a named tool with a bounded blast radius, exposed through your secure HTTPS endpoint and locked down with container allowlists and path traversal prevention. Built for engineers who run real infrastructure and want to manage it from anywhere Claude.ai runs — including their phone.
What's included
- 37 MCP tools across 7 categories — Vault (9), n8n (14), Docker (5), Infrastructure (5), Git (1), Homepage (2), Notifications (1)
- OAuth 2.1 authentication with PKCE — works with Claude.ai's native MCP connector
- Full n8n control — list, activate, deactivate, execute, and inspect workflows and executions
- Docker container management — status, logs, restart, stop for allowlisted containers only
- Vault operations — search, read, create, update notes with full path traversal prevention
- Infrastructure monitoring — disk, memory, CPU, container health, and Homepage widget data
- Git operations — status checks across your tracked repositories
- Telegram notifications — send alerts and action items to your phone
- 4-layer security architecture — Cloudflare Tunnel, OAuth 2.1, tool allowlists, container isolation
- No shell execution, no exec, no eval — every operation is explicitly defined and scoped
- Template configs included — docker-compose.yml, .env.example, secrets guide, security whitepaper
Requirements
- Docker and Docker Compose
- A domain with HTTPS (Cloudflare Tunnel recommended)
- Claude.ai Pro, Team, or Enterprise plan (required for MCP connectors)
- Obsidian vault or any markdown-based notes directory
- Optional: n8n instance, Homepage dashboard, Telegram bot token
server.py
# 37 tools. Zero shell access. Every action scoped.
ALLOWED_CONTAINERS = {
"n8n", "homepage", "nginx-proxy-manager",
# Only containers you explicitly approve
}
@mcp.tool()
async def docker_restart(container_name: str):
if container_name not in ALLOWED_CONTAINERS:
return {"error": "Not in allowlist"}
container = docker_client.containers.get(container_name)
container.restart()
return {"status": "restarted"}