mcp-sysadmin

mcp-sysadmin

Provider-agnostic MCP server for managing heterogeneous infrastructure (SSH, Proxmox VE, Virtualizor, Hetzner Cloud, Cloudflare) via a JSON inventory, exposing tools for VM/container management, DNS, firewalls, and SSH operations.

Category
Visit Server

README

MCP Sysadmin

Servidor MCP agnóstico de proveedor para administrar infraestructura heterogénea: servidores físicos, VPS por SSH, clusters Proxmox VE, paneles Virtualizor, Hetzner Cloud y Cloudflare.

A diferencia de MCPs atados a un hosting (p. ej. Cloudways), este proyecto usa un inventario JSON donde registras cada host con su proveedor y credenciales. Un mismo cliente MCP puede operar Proxmox en tu homelab, Virtualizor en un datacenter y servidores bare-metal en otra ubicación.

Arquitectura

flowchart LR
  Client[Cliente MCP / Cursor] --> MCP[mcp-sysadmin]
  MCP --> Inv[(inventory.json)]
  MCP --> SSH[SSH]
  MCP --> PVE[Proxmox API]
  MCP --> VZ[Virtualizor API]
  MCP --> HZ[Hetzner API]
  MCP --> CF[Cloudflare API]
  SSH --> Physical[Servidores físicos / VPS]
  PVE --> VMs1[VMs KVM / LXC]
  VZ --> VMs2[VPS OpenVZ/KVM/Xen]
  HZ --> VMs3[Cloud Servers]
  CF --> DNS[DNS / CDN / WAF]

Proveedores soportados

Provider Uso Autenticación
ssh Servidores físicos, VPS sin API, cualquier Linux Clave privada o password
proxmox Clusters / nodos Proxmox VE API Token (PVEAPIToken)
virtualizor Panel Virtualizor (Admin API) apiKey + apiPass
hetzner Hetzner Cloud (servidores, firewalls, volúmenes) API Token (Bearer)
cloudflare DNS, CDN, WAF (zonas y registros) API Token (Bearer)

Tools incluidos (38)

Inventario

  • list-hosts, get-host

Nodos / métricas

  • list-nodes, get-node-status, health-check

Máquinas virtuales / cloud

  • list-vms, list-containers, get-vm, vm-power
  • list-vm-snapshots, create-vm-snapshot
  • list-proxmox-tasks, get-proxmox-task
  • list-storage-usage, list-backups, create-backup
  • list-hetzner-firewalls, list-hetzner-volumes

Cloudflare (DNS / CDN)

  • list-zones, list-dns-records, get-dns-record
  • create-dns-record, update-dns-record, delete-dns-record (confirmToken)
  • purge-cache (confirmToken)
  • list-waf-rules

Red

  • list-network

SSH — operaciones controladas

  • ssh-exec, ssh-read-file (destructivas / confirmToken)

SSH — diagnóstico read-only

  • ssh-tail-log — journalctl o tail en /var/log/
  • list-firewall-rules — UFW / nftables / iptables
  • list-systemd-units — failed / running / all
  • cert-status — certbot / fechas SSL
  • dns-lookup, check-endpoint
  • list-cron, list-timers
  • docker-compose-ps

Instalación

📖 Manuales operativos: manuales/manual general y guías por provider.

Opción A — GitHub Packages + npx (recomendado)

Publicado en GitHub Packages como @kreodevs/mcp-sysadmin. No necesitas clonar el repo.

1. Registry de GitHub (una vez por máquina):

echo "@kreodevs:registry=https://npm.pkg.github.com" >> ~/.npmrc

O copia .npmrc.example. Los paquetes públicos no requieren token para instalar.

2. Inventario — crea tu inventory.json en cualquier ruta (p. ej. ~/mcp/inventory.json). Puedes basarte en config/inventory.example.json.

3. Probar en terminal:

export SYSADMIN_INVENTORY_PATH=~/mcp/inventory.json
export SYSADMIN_PRODUCTION_MODE=true
export SYSADMIN_CONFIRM_TOKEN=$(openssl rand -hex 32)

npx -y @kreodevs/mcp-sysadmin

4. Cliente MCP — configura npx (ver Instalación por cliente MCP abajo).

Cliente Botón 1 clic
Cursor Add to Cursor
VS Code Install MCP in VS Code

⚠️ Tras el 1 clic, edita en el diálogo: SYSADMIN_INVENTORY_PATH (ruta a tu inventario) y SYSADMIN_CONFIRM_TOKEN.

Generar enlaces personalizados:

SYSADMIN_INVENTORY_PATH=/ruta/a/inventory.json ./scripts/generate-install-links.sh
# Modo desarrollo local (clone): INSTALL_MODE=local ./scripts/generate-install-links.sh

Opción B — Desarrollo desde fuente

git clone https://github.com/kreodevs/mcp-sysadmin.git
cd mcp-sysadmin
npm install
npm run build
cp config/inventory.example.json config/inventory.json

Usa scripts/run-mcp.sh o npm run dev.

Publicar nueva versión (maintainers)

  1. Sube la versión en package.json y src/index.ts
  2. Crea un GitHub Release (tag vX.Y.Z) → el workflow .github/workflows/publish.yml publica en GitHub Packages
  3. Verifica en Packages del repo: @kreodevs/mcp-sysadmin

Configuración

  1. Copia el inventario de ejemplo:
cp config/inventory.example.json config/inventory.json
  1. Edita config/inventory.json con tus hosts reales.

  2. Variables de entorno (opcional):

cp .env.example .env
SYSADMIN_INVENTORY_PATH=./config/inventory.json
SYSADMIN_PRODUCTION_MODE=true
SYSADMIN_CONFIRM_TOKEN=un-secreto-largo-que-el-llm-no-conoce
SYSADMIN_READ_ONLY=false
SYSADMIN_REQUIRE_CONFIRM=true
SYSADMIN_RATE_LIMIT_MAX=30
SYSADMIN_HTTP_TIMEOUT_MS=30000
SYSADMIN_SSH_TIMEOUT_MS=30000

ACL por host (inventario)

Cada host puede restringir qué tools puede usar el LLM:

{
  "defaults": { "readOnly": false, "requireConfirm": true },
  "hosts": [
    {
      "id": "pve-prod",
      "readOnly": false,
      "allowedTools": ["list-vms", "get-vm", "vm-power"],
      "provider": "proxmox",
      "...": "..."
    }
  ]
}
  • readOnly: true — solo tools de lectura en ese host
  • allowedTools — lista blanca; si se omite, todas las tools del provider están permitidas

Referencias a secretos en el inventario

Puedes usar ${VAR} para no guardar credenciales en texto plano:

{
  "tokenSecret": "${PROXMOX_HOMELAB_TOKEN}",
  "apiKey": "${VIRTUALIZOR_API_KEY}",
  "apiPass": "${VIRTUALIZOR_API_PASS}"
}

Ejemplo: Proxmox

{
  "id": "pve-prod",
  "name": "Proxmox Producción",
  "provider": "proxmox",
  "url": "https://10.0.0.2:8006",
  "tokenId": "root@pam!cursor-mcp",
  "tokenSecret": "${PROXMOX_TOKEN}",
  "verifySsl": false,
  "defaultNode": "pve1",
  "tags": ["production"]
}

Crea el token en Proxmox: Datacenter → Permissions → API Tokens.

Ejemplo: Virtualizor

{
  "id": "vz-panel",
  "name": "Virtualizor DC1",
  "provider": "virtualizor",
  "url": "https://panel.example.com:4085",
  "apiKey": "${VIRTUALIZOR_API_KEY}",
  "apiPass": "${VIRTUALIZOR_API_PASS}",
  "tags": ["vps"]
}

Ejemplo: Servidor físico (SSH)

{
  "id": "metal-01",
  "name": "Bare Metal Rack A",
  "provider": "ssh",
  "host": "203.0.113.50",
  "port": 22,
  "username": "root",
  "privateKeyPath": "~/.ssh/id_ed25519",
  "tags": ["physical", "production"]
}

Ejemplo: Hetzner Cloud

{
  "id": "hz-cloud",
  "name": "Hetzner Cloud",
  "provider": "hetzner",
  "apiToken": "${HETZNER_API_TOKEN}",
  "defaultLocation": "fsn1",
  "allowedTools": ["list-vms", "get-vm", "vm-power", "list-nodes", "health-check"],
  "tags": ["cloud", "hetzner"]
}

Crea el token en Hetzner Cloud Console → Security → API Tokens (permisos Read & Write para power actions).

Ejemplo: Cloudflare

{
  "id": "cf-main",
  "name": "Cloudflare Production",
  "provider": "cloudflare",
  "apiToken": "${CLOUDFLARE_API_TOKEN}",
  "defaultZoneId": "${CLOUDFLARE_ZONE_ID}",
  "readOnly": true,
  "allowedTools": ["list-zones", "list-dns-records", "get-dns-record", "list-waf-rules"],
  "tags": ["dns", "cdn"]
}

Crea un API Token en Cloudflare con permisos mínimos: Zone → DNS (Read) y, si necesitas escritura, DNS Edit + Cache Purge.

Instalación por cliente MCP

Transporte stdio: el cliente lanza npx @kreodevs/mcp-sysadmin (GitHub Packages) o un script local en desarrollo.

Requisito previo: @kreodevs:registry=https://npm.pkg.github.com en ~/.npmrc o --registry=https://npm.pkg.github.com en los args de npx (incluido en los ejemplos).

Instalación rápida (1 clic)

Los botones de la sección Instalación → Opción A usan npx + GitHub Packages. Solo debes ajustar SYSADMIN_INVENTORY_PATH y SYSADMIN_CONFIRM_TOKEN en el diálogo del IDE.

# Enlaces con tu inventario:
SYSADMIN_INVENTORY_PATH=/ruta/a/inventory.json ./scripts/generate-install-links.sh

Cursor

Archivo: ~/.cursor/mcp.json (global) o .cursor/mcp.json (por proyecto)

UI: Settings → Tools & MCP → New MCP Server

Manual (GitHub Packages):

{
  "mcpServers": {
    "sysadmin": {
      "command": "npx",
      "args": ["-y", "--registry=https://npm.pkg.github.com", "@kreodevs/mcp-sysadmin"],
      "env": {
        "SYSADMIN_INVENTORY_PATH": "/ruta/a/inventory.json",
        "SYSADMIN_PRODUCTION_MODE": "true",
        "SYSADMIN_CONFIRM_TOKEN": "tu-secreto-humano",
        "SYSADMIN_REQUIRE_CONFIRM": "true",
        "PROXMOX_HOMELAB_TOKEN": "..."
      }
    }
  }
}

<details> <summary>Desarrollo local (clone del repo)</summary>

{
  "mcpServers": {
    "sysadmin": {
      "command": "/ruta/absoluta/mcp-sysadmin/scripts/run-mcp.sh",
      "env": {
        "SYSADMIN_INVENTORY_PATH": "/ruta/absoluta/mcp-sysadmin/config/inventory.json",
        "SYSADMIN_PRODUCTION_MODE": "true",
        "SYSADMIN_CONFIRM_TOKEN": "tu-secreto-humano"
      }
    }
  }
}

</details>


Claude Desktop

Archivo:

SO Ruta
macOS ~/Library/Application Support/Claude/claude_desktop_config.json
Windows %APPDATA%\Claude\claude_desktop_config.json

UI: Settings → Developer → Edit Config

{
  "mcpServers": {
    "sysadmin": {
      "command": "npx",
      "args": ["-y", "--registry=https://npm.pkg.github.com", "@kreodevs/mcp-sysadmin"],
      "env": {
        "SYSADMIN_INVENTORY_PATH": "/ruta/a/inventory.json",
        "SYSADMIN_PRODUCTION_MODE": "true",
        "SYSADMIN_CONFIRM_TOKEN": "tu-secreto-humano"
      }
    }
  }
}

Reinicia Claude Desktop tras guardar.


Claude Code (CLI)

claude mcp add sysadmin -- npx -y --registry=https://npm.pkg.github.com @kreodevs/mcp-sysadmin

Exporta SYSADMIN_INVENTORY_PATH y SYSADMIN_CONFIRM_TOKEN en el entorno o en la config de Claude Code.


OpenCode

Archivo: opencode.json / opencode.jsonc (proyecto) o ~/.config/opencode/opencode.json

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "sysadmin": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "--registry=https://npm.pkg.github.com",
        "@kreodevs/mcp-sysadmin"
      ],
      "enabled": true,
      "environment": {
        "SYSADMIN_INVENTORY_PATH": "/ruta/a/inventory.json",
        "SYSADMIN_PRODUCTION_MODE": "true",
        "SYSADMIN_CONFIRM_TOKEN": "tu-secreto-humano",
        "SYSADMIN_REQUIRE_CONFIRM": "true"
      }
    }
  }
}

OpenCode usa environment, no env. El command debe ser un array.

opencode mcp add
opencode mcp list

VS Code

Archivo: .vscode/mcp.json (workspace)

Manual:

{
  "servers": {
    "sysadmin": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "--registry=https://npm.pkg.github.com", "@kreodevs/mcp-sysadmin"],
      "env": {
        "SYSADMIN_INVENTORY_PATH": "/ruta/a/inventory.json",
        "SYSADMIN_PRODUCTION_MODE": "true",
        "SYSADMIN_CONFIRM_TOKEN": "tu-secreto-humano"
      }
    }
  }
}

Requiere GitHub Copilot con MCP o extensión compatible.


Windsurf (Cascade)

Archivo: ~/.codeium/windsurf/mcp_config.json

{
  "mcpServers": {
    "sysadmin": {
      "command": "npx",
      "args": ["-y", "--registry=https://npm.pkg.github.com", "@kreodevs/mcp-sysadmin"],
      "env": {
        "SYSADMIN_INVENTORY_PATH": "/ruta/a/inventory.json",
        "SYSADMIN_PRODUCTION_MODE": "true",
        "SYSADMIN_CONFIRM_TOKEN": "tu-secreto-humano"
      }
    }
  }
}

Pulsa Refresh en MCPs. Límite ~100 tools entre servidores.


Variables de entorno recomendadas (todos los clientes)

SYSADMIN_INVENTORY_PATH=/ruta/a/inventory.json
SYSADMIN_PRODUCTION_MODE=true
SYSADMIN_CONFIRM_TOKEN=<openssl rand -hex 32>
SYSADMIN_READ_ONLY=false
SYSADMIN_REQUIRE_CONFIRM=true
PROXMOX_HOMELAB_TOKEN=...
HETZNER_API_TOKEN=...
CLOUDFLARE_API_TOKEN=...

Desarrollo local del servidor (sin cliente MCP):

npm run dev

Seguridad

Modo producción

Activa siempre en prod:

SYSADMIN_PRODUCTION_MODE=true
SYSADMIN_CONFIRM_TOKEN=<secreto-largo-aleatorio>

Con esto:

  • SSH exige hostKeyFingerprint (anti-MITM) — falla al arrancar si falta
  • SYSADMIN_CONFIRM_TOKEN obligatorio — falla al arrancar si falta
  • SSH usa allowlist estricta (sin cat/grep; lecturas solo vía ssh-read-file)
  • Prohibido password en inventario SSH
  • vm-power requiere confirmación incluso para start
  • Regex custom validadas (sin .* ni patrones demasiado amplios)

Gate humano: confirmToken

El LLM puede poner confirm: true por prompt injection, pero no conoce SYSADMIN_CONFIRM_TOKEN (solo está en env del MCP, no en el chat):

{
  "hostId": "bare-metal-01",
  "command": "systemctl status nginx",
  "confirm": true,
  "confirmToken": "tu-secreto-humano-no-compartir-con-el-modelo"
}

Tú proporcionas el token cuando apruebas la operación.

Token de un solo uso (recomendado)

./scripts/mcp-approve.sh
# Válido 5 minutos; úsalo como confirmToken en la tool call

Alternativa: el token fijo SYSADMIN_CONFIRM_TOKEN en env MCP.

Obtener fingerprint SSH

ssh-keyscan -H 10.0.0.5 | ssh-keygen -lf -
# Copia la línea SHA256:... al inventario como hostKeyFingerprint

Controles implementados

Control Descripción
confirmToken Secreto humano en env MCP; el modelo no lo tiene por defecto
Modo producción Allowlist SSH, host key pinning, sin passwords SSH
Modo read-only SYSADMIN_READ_ONLY=true bloquea tools de escritura
ACL por host readOnly, allowedTools, allowedCommandPatterns
Allowlist SSH Solo diagnóstico (systemctl status, journalctl, docker ps, etc.) — sin lectura de archivos
Lectura de archivos Exclusivamente vía ssh-read-file (paths + symlinks + confirmToken)
cwd restringido Solo /tmp, /var/log, /var/www, /home/*, /opt/* en ssh-exec
Regex inventario Patrones custom validados; prohibido .* y regex demasiado amplias
Blocklist SSH Capa extra: rm -rf, pipes a shell, multiline, etc.
Paths remotos readlink -f antes de leer; bloqueo de shadow/symlink bypass
Rate limit 30 req/tool/host/min (configurable)
TLS Proxmox verifySsl default true
Redacción Secretos, configs VM, errores API filtrados
Auditoría JSON en stderr: [mcp-sysadmin:audit]

Allowlist SSH por defecto

Incluye solo diagnóstico operativo: systemctl status, journalctl, docker ps/logs, kubectl get, ls, df, free, nginx -t, etc.

No incluye cat, grep, head, tail — usa ssh-read-file para leer archivos.

Añade patrones específicos en inventario (sin .*):

{
  "allowedCommandPatterns": ["^systemctl restart nginx$"]
}

Tools que requieren confirm + confirmToken

  • ssh-exec — siempre
  • ssh-read-file — siempre
  • vm-power — todas las acciones en producción; stop/shutdown/reboot/reset siempre
  • create-vm-snapshot — siempre
  • create-backup — siempre
  • create-dns-record, update-dns-record, delete-dns-record, purge-cache — siempre

Checklist pre-producción

  • [ ] SYSADMIN_PRODUCTION_MODE=true
  • [ ] SYSADMIN_CONFIRM_TOKEN generado (openssl rand -hex 32)
  • [ ] Fingerprint SSH en cada host
  • [ ] Tokens Proxmox / Hetzner / Cloudflare con permisos mínimos
  • [ ] verifySsl: true en Proxmox
  • [ ] allowedTools por host según necesidad
  • [ ] Inventario sin passwords en texto plano
  • [ ] Probar una operación destructiva con token manual

CI y publicación

Extensión

Para añadir otro proveedor (oVirt, VMware, AWS, etc.):

  1. Añade el provider en src/config/schema.ts
  2. Implementa cliente en src/providers/<nombre>/client.ts
  3. Regístralo en src/providers/registry.ts
  4. Expone tools en src/tools/

La estructura sigue el patrón del cloudways-mcp-server, pero con inventario multi-proveedor en lugar de una API única.

Desarrollo

npm run typecheck
npm run build

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured