mcp-server
Servidor MCP: proveedor modular de comandos
Un servidor FastAPI que expone comandos de terminal arbitrarios —además de calendarios CalDAV, fuentes ICS, repositorios de Gitea y proveedores de notificación— como herramientas reutilizables para un modelo de lenguaje. Los programas CLI se registran colocando un archivo YAML en registry/; las integraciones se activan mediante variables de entorno. El modelo descubre las herramientas disponibles a través del esquema OpenAPI y las invoca mediante endpoints HTTP tipados.
Por qué
Independiente del lenguaje – envuelve cualquier script, binario o programa compilado.
Autodescriptivo — cada comando lleva un esquema JSON de sus argumentos.
Descubrible —
GET /commandslo lista todo; OpenAPI, en/openapi.json.Ejecución segura — los argumentos se validan contra el esquema antes de ejecutar el comando; un tiempo de espera de 30 s evita bloqueos que nos mantienen.
Registro condicional — los endpoints solo existen cuando el servicio que les da soporte está configurado. El LLM nunca ve rutas que devolverían un 404.
Clave API opcional — si define
MCP_API_KEY, se requiere autenticación en todos los endpoints excepto/api/healthy/api/about.
Related MCP server: Graft
Inicio rápido
Los siguientes comandos te guían para empezar:
cd ~/projects/mcp-server
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
# Optional: set an API key to secure the server
export MCP_API_KEY="your-secret-key"
.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000El servidor queda a la espera en la hora http://127.0.0.1:8000.
Si se define MCP_API_KEY, todos los endpoints excepto /api/health y /api/about requieren una cabecera X-API-Key que coincida con la clave. Si no se define, el servidor arranca en abierto (adecuado para desarrollo local o redes de confianza).
Seguridad de inicio: si no hay nada configurado (ni proveedores de calendario, ni Gitea, ni proveedores de notificación, ni clima, ni comandos registrados), el servidor se niega a arrancar. Al menos una función tiene que estar activada.
Arquitectura
El servidor utiliza un patrón de fábrica (create_app()) que inspecciona las variables de entorno al arrancar y registra los routers de forma condicional para cada integración configurada. Esto significa que el esquema OpenAPI solo contiene los endpoints que van a funcionar de verdad: el LLM nunca descubre rutas que devolverían un 404.
Sistema de proveedores
Las integraciones de calendario (CalDAV e ICS) se implementan como proveedores que implementan un protocolo común. Un provider_registry global mantiene todos los proveedores activos. El router unificado (unified_routes.py) expone /events, /calendars y —cuando ICS está configurado— /calendars/refresh en todos los proveedores. Las operaciones de escritura (crear, actualizar y eliminar eventos) solo se registran cuando existe un proveedor editable (es decir, CalDAV con CALDAV_EDITABLE_CALENDAR definida).
Trabajos en segundo plano
Un pequeño planificador de trabajos (jobs.py) ejecuta tareas periódicas en segundo plano durante toda la vida de la aplicación. Actualmente se usa para renovar la caché de ICS. Su estado se puede consultar en GET /jobs.
API
Los endpoints se registran de forma condicional según la configuración. La tabla siguiente muestra todos los endpoints posibles; solo están presentes los correspondientes a las funciones configuradas.
Núcleo (siempre presente)
Method | Path | Description |
GET |
| Puesta en vivo (no autenticado) |
GET |
| Nombre y version del servidor (no autente) |
GET |
| Lista todos los comandos registrados |
GET |
| Obtiene el esquema de un comando |
GET |
| Valida todos los archivos del registro (informe detallado) |
GET |
| Muestra el estado de los trabajos periódicos en segundo plano |
POST |
| Ruta dedicada a cada comando del registro (auto-generada) |
Calendario (si CalDAV o ICS está configurado)
Method | Path | Description |
GET |
| Lista los eventos de todos los proveedores de calendario |
GET |
| Obtiene un único evento por UID |
GET |
| Lista los calendarios accesibles con metadatos |
POST |
| Refresca la caché de ICS (cuando hay ICS) |
POST |
| Crea un evento (solo con proveedor editable) |
PUT |
| Actualiza un evento (solo con proveedor editable) |
DELETE |
| Elimina un evento (solo con proveedor editable) |
Tareas CalDAV (cuando CalDAV está configurado)
Method | Path | Descripción |
GET |
| Lista las tareas de calendario (VTODO) |
GET |
| Obtiene una tarea por su UID |
POST |
| Crea una tarea (solo con proveedor editable) |
PUT |
| Actualiza una tarea (solo con proveedor editable) |
DELETE |
| Elimina una tarea (solo con proveedor editable) |
Gitea (cuando GITEA_URL está configurado)
Method | Path | Descripción |
GET |
| Muestra la información de un repositorio |
GET |
| Lista los repositorios accesibles |
GET |
| Lista los últimos commits |
GET |
| Compara dos referencias (tools extra) |
GET |
| Lista de issues (repositorio por defecto u owner/repo) |
GET |
| Obtiene un issue por su índice |
POST |
| Crea un issue nuevo |
PATCH |
| Modifica un issue (p. ej., cerrarlo) |
GET |
| Lista los comentarios de un issue |
POST |
| Comenta un issue |
GET | */branches | Lista las ramas (repositor por defecto u owner/repo) |
POST |
| Crea una nueva rama |
PUT |
| Actualiza una rama |
DELETE |
| Elimina una rama |
GET |
| Lista las pull requests |
POST |
| Crea una pull request |
GET |
| Obtiene una PR determinada |
PATCH |
| Actualiza una PR (p. ej., cerrarla) |
POST |
| Fusiona una pull request |
GET |
| Lista las revisiones de una PR (tools extra) |
POST |
| Comenta en una PR |
GET |
| Muestra las ejecuciones de CI workflows |
GET |
| Obtiene los checks de estado de CI (tools extra) |
GET |
| Lista las releases |
POST |
| Crea una release |
GET |
| Obtiene una release |
PATCH |
| Actualiza una release |
DELETE |
| Elimina una release |
Extra tools:
/repos/.../compare,/prs/{index}/reviewsy/commits/{sha}/statusesestán ocultos del esquema OpenAPI por defecto para reducir el recuento de tokens. DefinaMCP_GITEA_EXTRA_TOOLS=1para exponerlos.
Notificación (cuando Discord o Ntfy está configurado)
Método | Nome de la ruta | Descripción |
POST |
| Envía una notificación a los proveedores configurados |
Clima (cuando WEATHER_LOCATION está definido)
Método | Ruta | Descripción |
GET |
| Condiciones actuales y previsión a varios días |
Ejemplo
# List available commands
curl http://127.0.0.1:8000/commands
# Execute the `log` command (dedicated route — the only way to run it)
curl -X POST http://127.0.0.1:8000/log \
-H 'Content-Type: application/json' \
-d '{"message": "Server started"}'Response:
{"stdout": "[2026-01-15T10:30:00-0500] [INFO] Server started\n", "stderr": "", "exit_code": 0, "success": true}...Si hay una clave API, inclúyela en la libreta:
curl -H "X-API-Key: your-secret-key" http://127.0.0.1:8000/commandsValidar el registro
Antes de reiniciar el servidor tras editar los archivos del registro, puede validarlos; igual que caddy validate hace con la configuración de Caddy.
CLI
Salida
python -m app.validateTambién puedes indicar un directorio de registro distinto:
python -m app.validate /path/to/registryOutput:
MCP Server registry validation: /app/registry
✓ log.yaml → log
✓ log_read.yaml → log_read
✗ broken.yaml: mapping values are not allowed here
⚠ noprogram.yaml → noprogram: Executable not found: /usr/bin/nonexistent
4 file(s) checked · 1 error(s) · 1 warning(s)
Registry has errors — fix them before restarting.Códigos de salida:
0— todos los archivos est; canutos son válidos (las advertencias no importan)1— uno o más archivos tienen errores2— el directorio del registro no existe
HTTP
curl http://127.0.0.1:8000/validateDevuelve un informe en JSON con el resultado por archivo, incluida detección de nombres duplicados y comprobación de que los ejecutables existen.
Registrar una orden
Crear un archivo en registry/ (p. ej., my_tool.yaml):
name: my_tool
description: Does something useful.
executable: /usr/local/bin/my_tool
# (relative paths like scripts/my_tool.sh are resolved against
# the project root, so they work in any clone or Docker image)
args:
- name: input
type: string
required: true
help: Path to the input file.
- name: --verbose
type: flag
required: false
help: Enable verbose output.
- name: --mode
type: string
required: false
choices: [fast, slow]
help: Execution mode.Spec de campo de los argumentos
Campo | Tipo | Notas |
| string | Ruta (posicion) place holders o nombre de la opción |
| string |
|
| bool | Por defecto |
| list | Lista optativa de valores permitidos. |
| any | Valor por defecto opcional, que se aplica automáticamente si el llamador omite este argumento. |
| string | Descripción legible para humanos. |
| string | Nombre opcional (limpio) para el parámetro del tema entre la herramienta original. Si se establece, se convierte en el nombre de la propiedad OpenAPI (p. ej. |
| bool | Cuando es |
El tipo flag indica solo presencia (sin valor): el nombre del flag se añade a la línea de comandos dependiendo únicamente de que el argumento sea truthy.
Comendos condicionados (requires)
Los comandos pueden pos summary:
requires:
- "MCP_LOG_ENABLED != false"Esto se usa en log and log_read para desaparecer cuando el logging está desactivado por MCP_LOG_ENABLED=false.
Default
Cualquier argumento puede llevar un valor por defecto. Cuando el llamador no incluye ese argumento, el executor lo rellena automáticamente; muy útil para obligar el paso de flags que siempre deben estar activos (por ejemplo, discord.sh -q para modo silencioso):
args:
- name: -q
type: flag
default: true
help: Quiet mode — forced on by default.Rutas nativas para los registry commands
Cada comando definido en registry/ se expone automáticamente como su propia ruta FastAPI — POST /{command_name} — con una petición generada por pydantic a partir del schema YAML de argumentos. De este La plataforma puede leer el esquema de OpenAPI y presentar cada comando como una herramienta nativa con parámetros bien tipados (strings, enums, flags, default values).
Estas rutas dedicadas son la única forma de ejecutar comandos del registry — no hay un endpoint genérico POST /execute. Los archivos del registry siguen alimentando GET /commands y GET /validate para que puedas descubrir e inspeccionar comandos, pero la execucución commite en las rutas tipadas pro command.
Los campos desconectados son rechazados (extra: forbid) con una respuesta 422, y si falta un argumento requerido, también devuelve 422.
La clave YAML field_name controla cómo se llama el parámetro en la tool que el modelo ve. Si no se especifica, se usa el name del arg (eliminando los guiones iniciales).
Si el nombre de un comando del registro coincide con una ruta existente (p. ej. events, issues), la ruta dedicada se omite con una advertencia y el comando no se puede ejecutar por HTTP (aunque sigue apareciendo en GET /commands). Renombra el comando en el registro para permitir su ejecución.
Biblioteca del cliente
Un pequeño cliente síncrono basado en httpx se encuentra en app/client.py. Refleja la API HTTP para que un modelo o un script pueda tratar cada comando registrado como una función Python nativa.
from app.client import MCPClient
mc = MCPClient("http://127.0.0.1:8000", api_key="your-secret-key")
# Discover available commands
for cmd in mc.list_commands():
print(cmd["name"], "-", cmd["description"])
# Execute a command
result = mc.execute("log", message="Server started")
print(result["stdout"])
# Bind a command to a reusable callable
log = mc.tool("log")
log(message="Deploy complete")Los nombres de las opciones que empiezan con - no son identificadores válidos de Python, así que puedes pasarlos mediante desempaquetado de diccionario: **{"-c": "green"}.
Si el servidor tiene MCP_API_KEY definida, pásale api_key= al cliente: se enviará como X-API-Key en cada petición.
El cliente también funciona como gestor de contexto:
with MCPClient() as mc:
mc.execute("log_read", lines="10")El cliente también ofrece métodos de conveniencia tipados para las API de calendario, tareas y Gitea (list_events, create_task, list_issues, etc.).
Estructura del proyecto
mcp-server/
├─ app/
│ ├─ __init__.py # package marker, resolves version via importlib.metadata
│ ├─ main.py # FastAPI app factory + conditional router registration
│ ├─ auth.py # API key authentication dependency
│ ├─ models.py # Pydantic schemas (commands, args, validation)
│ ├─ executor.py # validation + subprocess wrapper with timeout
│ ├─ registry.py # YAML/JSON command loader + validate_registry()
│ ├─ validate.py # `python -m app.validate` CLI
│ ├─ client.py # httpx client library (commands + calendar + Gitea API)
│ ├─ registry_routes.py # Auto-generated native routes for registry commands
│ ├─ caldav_models.py # Pydantic models for CalDAV events/tasks
│ ├─ caldav_service.py # CalDAV service (1 editable + N read-only calendars)
│ ├─ caldav_routes.py # FastAPI router for /tasks (CalDAV-specific)
│ ├─ ics_models.py # Pydantic models for ICS feed config
│ ├─ ics_service.py # ICS feed fetcher, parser, cache
│ ├─ ics_routes.py # ICS service singleton management
│ ├─ unified_routes.py # Unified /events, /calendars router across providers
│ ├─ provider_adapters.py # CalDAVProvider, ICSProvider adapters
│ ├─ providers.py # Global provider registry
│ ├─ gitea_models.py # Pydantic models for Gitea resources
│ ├─ gitea_service.py # Gitea API service (issues, PRs, branches, releases)
│ ├─ gitea_routes.py # FastAPI router for /issues, /prs, /branches, etc.
│ ├─ notify_models.py # Pydantic models for notifications
│ ├─ notify_service.py # Discord + Ntfy notify providers
│ ├─ notify_routes.py # FastAPI router for /notify
│ ├─ weather_models.py # Pydantic models for weather config
│ ├─ weather_service.py # Open-Meteo API client
│ ├─ weather_routes.py # FastAPI router for /weather
│ └─ jobs.py # Lightweight background job scheduler
├─ registry/ # command definitions (one file per command)
│ ├─ log.yaml # logging command
│ └─ log_read.yaml # read log tail
├─ scripts/ # helper scripts referenced by registry YAMLs
│ ├─ log.sh # append to log file
│ ├─ log_read.sh # read log tail
│ └─ config.sh.example # template (unused in Docker; for reference)
├─ tests/ # pytest test suite
│ ├─ conftest.py
│ ├─ test_models.py
│ ├─ test_executor.py
│ ├─ test_registry.py
│ ├─ test_api.py
│ ├─ test_client.py
│ ├─ test_auth.py
│ ├─ test_caldav.py
│ ├─ test_ics.py
│ ├─ test_ics_recurrence.py
│ ├─ test_gitea.py
│ ├─ test_notify.py
│ ├─ test_weather.py
│ ├─ test_logging.py
│ ├─ test_jobs.py
│ └─ test_conditional_endpoints.py
├─ Dockerfile # multi-arch base image definition
├─ LICENSE # MIT license
├─ variants/ # variant Dockerfiles (PHP, Node, etc.)
│ ├─ Dockerfile.php
│ └─ Dockerfile.node
├─ docker-compose.yml # easy local run with volumes
├─ .env.example # environment variable template
├─ .dockerignore # excludes venv, secrets, tests, etc.
├─ pyproject.toml # package metadata + pytest/ruff config
└─ requirements.txt # pip dependencies (used by Dockerfile)Configuración
Toda la configuración se realiza mediante variables de entorno. Consulta .env.example para ver una referencia completa con comentarios. El servidor las lee al arranque y registra los endpoints de forma condicional.
Variable | Funcionalidad | Descripción |
| Autenticación | Clave de API para los endpoints (sin definir = acceso abierto) |
| Registro | Directorio de registro personalizado |
| Registro | Ruta del archivo de registro |
| Registro | Directorio de registro (dentro, el archivo es |
| Registro | Nivel de registro (por defecto: INFO) |
| Registro | Establécelo en |
| CalDAV | URL del servidor CalDAV |
| CalDAV | Nombre de usuario de CalDAV |
| CalDAV | Contraseña de CalDAV |
| CalDAV | Nombre del calendario editable (sin definir = todo es de solo lectura) |
| CalDAV | Nombres de calendarios de solo lectura separados por comas |
| ICS | URL de la fuente ICS de solo lectura |
| ICS | Nombre visible para la fuente ICS |
| ICS | Intervalo de refresco de la caché en segundos (por defecto 300) |
| Gitea | URL del servidor de Gitea |
| Gitea | Token de API |
| Gitea | Propietario del repositorio por defecto |
| Gitea | Nombre del repositorio por defecto |
| Gitea | Exponer endpoints de nicho en el esquema OpenAPI |
| Notificaciones | URLs de webhooks de Discord (por nivel de gravedad) |
| Notificaciones | Anulación del nombre visible del bot |
| Notificaciones | Sufijo de título para los mensajes de Discord |
| Notificaciones | URL del servidor Ntfy |
| Notificaciones | Temas de Ntfy (por nivel de gravedad) |
| Notificaciones | Token de acceso de Ntfy |
| Notificaciones | Autenticación básica de Ntfy |
| Notificaciones | Sufijo de título para los mensajes de ntfy |
| Meteorología |
|
| Servidor | Zona horaria (por defecto UTC) |
Calendario CalDAV
El servidor puede conectarse a un servidor CalDAV (p. ej. Radicale, Baikal, Nextcloud) para gestionar eventos y tareas de calendario. El diseño utiliza un calendario editable (donde se pueden crear, actualizar y eliminar eventos y tareas) y varios calendarios de solo lectura (visibles pero no modificables).
Cuando CALDAV_EDITABLE_CALENDAR no está definido, todos los calendarios son de solo lectura y no se registran endpoints de creación/actualización/eliminación.
Todos los eventos y tareas incluyen un indicador editable y un calendar_name, de modo que el modelo puede ver la vista unificada del calendario, pero no correr el riesgo de modificar calendarios que no debería tocar.
Configuración
CALDAV_URL=https://caldav.example.com/dav
CALDAV_USERNAME=user
CALDAV_PASSWORD=secret
# Optional: set to make a calendar writable. When unset, all calendars
# are read-only and write endpoints are not registered.
#CALDAV_EDITABLE_CALENDAR=MyCalendar
# Optional: comma-separated list of read-only calendar names to include.
# If empty, all calendars except the editable one are included as read-only.
#CALDAV_READONLY_CALENDARS=Personal,WorkCuando CALDAV_URL no está definida, los endpoints de calendario no se registran.
Features
Eventos (VEVENT): listar (con filtrado por rango de fechas), obtener por UID, crear, actualizar y eliminar; se admiten eventos de todo el día y con hora.
Tareas (VTODO): listar, obtener por UID, crear, actualizar y eliminar; con gestión de prioridad, fecha de vencimiento y estado.
Recuperación de conexión: si el servidor del CalDAV se vuelve inalcanzable a la mitad de una operación, el servicio restablece su conexión automáticamente y reintza una vez. Captura
DAVError,ConnectionError,TimeoutErroryOSError.Caché de calendarios: la lista de calendarios se obtiene una vez por conexión y se la guarda en caché, evitando así idas y vueltas redundantes al servidor.
UUID explícitos: los eventos y tareas creados siempre reciben un
uuid4como UID, lo que garantiza que se puedan actualizar o eliminar de inmediata after creation.
Calendario ICS (solo lectura)
El servidor puede fusionar una fuente de calendario ICS de solo lectura (p. ej. un calendario publicado de Outlook, iCal de Google Calendar) en el endpoint /events, junto con los eventos de CalDAV.
ICS_CALENDAR_URL=https://outlook.office365.com/owa/calendar/.../calendar.ics
ICS_CALENDAR_NAME=Work
ICS_REFRESH_INTERVAL=300 # seconds (default 300, minimum 30)La fuente de ICS se obtiene y guarda en caché al iniciarse, y luego una tarea en segundo plano la actualiza periódicamente. Usa POST /calendars/refresh para forzar manualmente una actualización de la caché.
Integración con Gitea
El servidor puede conectarse a una instancia de Gitea para gestionar repositorios, issues, pull requests, ramas, releases y acciones de CI. Cuando GITEA_URL no está definida, los endpoints de Gitea no se registran.
Configuración
GITEA_URL=https://git.example.com
GITEA_TOKEN=your-api-token
GITEA_DEFAULT_OWNER=your-username
GITEA_DEFAULT_REPO=your-repoLos endpoints de incidencias, ramas, PRs y releases aceptan parámetros opcionales de consulta owner y repo, que toman por defecto los valores configurados. Los endpoints de información de repositorio, commits y comparación utilizan rutas parametrizadas (/repos/{owner}/{repo}/...).
Notify
El servidor puede enviar notificaciones a través de webhooks de Discord y/o Ntfy. Puede haber varios proveedores activos a la vez: una llamada a /notify se reenvía a todos los proveedores configurados.
Los webhooks de Discord se configuran por nivel de gravedad (info, notice, critical, emergency). Si un nivel no está configurado, el sistema uscesa al siguiente inferior configurado.
Ntfy funciona de forma similar con temas por nivel de gravedad. La autenticación admite por tokens o auth básica.
Registro
Los comandos log y log_read proporcionan una utilidad de registro simple: añadir mensajes con marca de tiempo a un archivo y leerlos.
# Log a message
curl -X POST http://127.0.0.1:8000/log \
-H 'Content-Type: application/json' \
-d '{"message": "Deploy complete"}'
# Log with a level
curl -X POST http://127.0.0.1:8000/log \
-H 'Content-Type: application/json' \
-d '{"message": "Disk full", "level": "error"}'
# Read the last 20 lines
curl -X POST http://127.0.0.1:8000/log_read \
-H 'Content-Type: application/json' \
-d '{"lines": "20"}'La ruta del archivo de registro se determina en este orden de prioridad:
La variable de entorno
MCP_LOG_FILE— ruta completa del archivo de registro.La variable de entorno
MCP_LOG_DIR— un directorio; el archivo esmcp.logdentro de él.Predeterminado:
/tmp/mcp/mcp.log.
Los directorios padre se crean automáticamente si no existen.
Establece MCP_LOG_ENABLED=false para desactivar el registro por completo; los comandos log y log_read no se registrarán y sus rutas no existirán.
Docker
El servidor incluye un Dockerfile multarquitectura listo para amd64 y arm64.
Construcción
docker build -t digitaladapt/mcp-server:latest .Para compilactions multarquitectura (requiere buildx):
docker buildx build --platform linux/amd64,linux/arm64 -t digitaladapt/mcp-server:latest .Ejecución
docker run -d --name mcp-server -p 8000:8000 \
--env-file .env \
-e MCP_API_KEY="your-secret-key" \
-v ./registry:/app/registry \
digitaladapt/mcp-server:latestO con docker compose:
docker compose up -dVolumenes
Mount | Finalidad |
| Definiciones de comandos: anular o ampliar en tiempo de ejecución. |
| Localización por defecto del archivo de registro (o establece MCP_LOG_FILE). |
El directorio scripts/ (incluido log.sh) se incluye dentro de la imagen. Los secretos nunca se incluyen en la imagen; se proporcionan mediante variables de entorno (--env-file .env).
Detalles de la imagen
Base:
python:3.12-slim(multarquitectura)Dependencias del sistema:
curl,jq(para scripts),tiniSe ejecuta como: usuario no root
mcp(uid 1000)Entrypoint:
tini(manejo correcto de señales PID-1)
Compilar variantes (PHP, Node, etc.)
El Dockerfile base está diseñado como base. En la directorio variants/ se encuentran los Dockerfile de las variantes y añaden runtimes extra por encima:
Variante | Dockerfile | Runtime | Comandos de ejemplo |
PHP |
| PHP CLI + curl, mbstring, xml |
|
Node.js |
| Node.js 22 LTS + npm |
|
Compile a varante (desde la raíz del repositorio):
# PHP
docker build -f variants/Dockerfile.php -t digitaladapt/mcp-server:php .
# Node.js
docker build -f variants/Dockerfile.node -t digitaladapt/mcp-server:node .Run a variant:
docker run -p 8000:8000 \
--env-file .env \
-v ./registry:/app/registry \
digitaladapt/mcp-server:phpCrea tu propia variante:
# variants/Dockerfile.ruby
FROM digitaladapt/mcp-server:latest
USER root
RUN apt-get update && apt-get install -y --no-install-recommends \
ruby && rm -rf /var/lib/apt/lists/*
USER mcpLuego añade un registry/ruby_eval.yaml que apunte a /usr/bin/ruby.
Pruebas
El proyecto incluye una suite de pytest completa que cubre modelos, ejecutor, registro, endpoints de API, librería de modelo, autenticación, operaciones CalDAV, análisis ICS, integración con Gitea, notificaciones, meteorología, logs, trabajos en segundo plano y registro de endpoints condicional.
# Install dev dependencies
pip install -e ".[dev]"
# Run the full suite
pytest
# Run with verbose output
pytest -v
# Run a single test module
pytest tests/test_executor.pyLa regresión de los valores por defecto de las opciones (por ejemplo, una opción con default: true) está cubierta por test_executor.py::TestValidateAndBuild::test_flag_default_true_*.
La lógica de timeout y terminación del grupo de procesos del ejecutor se prueba en test_executor.py.
Notas de seguridad
Solo se pueden ejecutar los comandos presentes en
registry/: no existe un endpoint de comandos arbitrarios.Los argumentos se validan (tipo, obligatorios, opciones) antes de lanzar el subproceso, y se rechazan los argumentos desconocidos.
Cada comando tiene un timeout fijo de 30 s acompañado de terminación del grupo de procesos.
Autenticación por API key — define
MCP_API_KEYpara exigir la cabeceraX-API-Keyen todos los endpoints excepto/api/healthy/api/about. Sin definir, el servidor queda abierto.Los mensajes de error se saneigen — los detalles internos se registran en el servidor, pero no se exponen en las respuestas HTTP (es importante, porque los errores son devueltas hacia la ventana de contexto del LLM).
Ejecuta el servidor con una cuenta de usuario limitada; no le des sudo.
Comandos que permiten la introspección del sistema de archivos del servidor o la ejecución de código arbitrario han sido eliminados a propósito — solo deben registrarse comandos específicos y permitidos.
Creado por Lyra — tu asistente de pelo plateado en la esquina. ✨
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.
AI-callable tools for API mocking, testing, monitoring, security, and automation.
Verified, pay-per-use API tools for AI agents through one authenticated connection.
Build, validate, deploy — HTTP APIs, cron jobs, webhooks and MCP tools — from your AI client.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI models to access external services including weather data, file system operations, and SQLite database interactions through a standardized JSON-RPC interface. Features production-ready architecture with security, rate limiting, and comprehensive error handling.225MIT
- AlicenseNot gradedqualityCmaintenanceEnables building agent-ready APIs that expose tools as both HTTP and MCP endpoints from a single server definition, with automatic OpenAPI, discovery docs, and interactive API reference.5Apache 2.0
- AlicenseNot gradedqualityDmaintenanceProvides AI assistants with 28 developer tools across file, git, code analysis, HTTP, and system domains, enabling tasks like file editing, repository management, code analysis, and shell command execution.232MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to execute Python functions and system commands via Streamable HTTP, including bash, Python code execution, file operations, and text searching.2,013MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/digitaladapt/mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server