Crear un servidor MCP personalizado

Instalar servidores MCP públicos está bien para aprender. Pero el salto útil llega cuando expones tus propias herramientas: buscar en tu documentación, validar un repo, consultar una base interna o crear un informe acotado.

Objetivos de aprendizaje
  • Diseñar un servidor MCP mínimo con tools estrechas.
  • Separar lógica de negocio, validación y transporte MCP.
  • Probarlo antes de conectarlo a Claude Code, Hermes u otro cliente.
En cristiano: servidor MCP custom. Es un pequeño servicio que expone herramientas a una app de IA mediante el protocolo MCP. El agente no recibe acceso total: recibe funciones concretas con argumentos definidos.
Terminal
# Estructura mínima
mcp-debug/
  server.py
  pyproject.toml
  tests/
    test_tools.py

# Tool útil:
# run_lint(project_path) -> ejecuta solo comandos permitidos
# search_docs(query) -> busca en una carpeta concreta
Idea clave. Tu primera tool debe leer o verificar. No empieces con borrar, publicar, enviar emails o tocar producción.
Terminal
from mcp.server.fastmcp import FastMCP
from pathlib import Path
import subprocess

mcp = FastMCP("aulafy-debug-tools")
ROOT = Path("/Users/me/proyectos").resolve()

def safe_path(path: str) -> Path:
    target = Path(path).resolve()
    if ROOT not in target.parents and target != ROOT:
        raise ValueError("Path fuera del workspace permitido")
    return target

@mcp.tool()
def list_markdown_files(path: str) -> list[str]:
    base = safe_path(path)
    return [str(p.relative_to(base)) for p in base.rglob("*.md")][:100]

@mcp.tool()
def run_lint(path: str) -> str:
    base = safe_path(path)
    result = subprocess.run(
        ["npm", "run", "lint"],
        cwd=base,
        text=True,
        capture_output=True,
        timeout=120,
    )
    return result.stdout[-6000:] + result.stderr[-3000:]

if __name__ == "__main__":
    mcp.run()
Cuidado. Si aceptas `command: string` y lo pasas a una shell, has creado una puerta peligrosa. Usa listas de comandos permitidos, timeouts y rutas validadas.

Checklist antes de conectar un agente

  • La tool rechaza rutas fuera del workspace.
  • Hay timeout y límite de salida.
  • No acepta comandos arbitrarios.
  • Registra argumentos, decisión y resultado.
  • Tiene pruebas con inputs maliciosos.
Comprueba que funciona. Prueba tres ataques: `../.env`, una ruta inexistente y un repo sin `package.json`. El servidor debe fallar claro y sin filtrar secretos.
Guardar y reabrir el proyecto.
Un MCP custom bueno es aburrido: pocas tools, validación fuerte, logs claros y permisos mínimos. Eso lo hace útil en proyectos reales.