ADR 006: Plugin MCP interno¶
Estado¶
Aceptado — 2026-06 · Diseño de ingeniería (sin implementación aún)
Relacionado con ADR 001 (MCP como fachada IA), ADR 005 (auth en MCP) y ADR 008 (tools de booking).
Contexto¶
Los agentes de IA consumen módulos vía Model Context Protocol (MCP). La API REST sigue siendo la fuente de verdad del negocio; MCP es la fachada estandarizada hacia agentes.
Patrón acordado: igual que REST/OpenAPI — infraestructura en framework (submódulo io.mcp — ADR 010), capacidades en plugins. Un módulo interno Dependiente expone el servidor MCP; cada plugin registra tools opcionales.
Hoy no existe código MCP en el monorepo.
Decisión¶
Módulo interno¶
- Paquete
cortex_framework.io.mcp(siempre cargado, no desactivable víaCORTEX_ENABLED_PLUGINS). Ver ADR 010. - Servidor MCP con transporte HTTP en ruta dedicada (p. ej.
/api/v1/mcp). - Stdio solo para desarrollo local / pruebas con agentes CLI.
SPI en core¶
Nuevo hook en core/cortex_core/registrar.py:
class McpToolRegistrar(Protocol):
def register_tool(
self,
name: str,
description: str,
input_schema: dict[str, Any],
handler: Callable[..., Awaitable[Any]],
) -> None: ...
Hook opcional del plugin: register_mcp_tools(registry: McpToolRegistrar) -> None.
Convención de nombres: {plugin_id}.{action} — p. ej. booking.create, booking.cancel.
Regla de oro¶
Los handlers MCP no duplican lógica de negocio. Invocan:
- Servicios internos del plugin (funciones compartidas con los routers REST), o
- Cliente HTTP interno hacia
localhost/api/v1/...del mismo proceso (menos preferido).
OpenAPI del plugin documenta la API humana; MCP documenta la superficie agente.
Descubrimiento dinámico¶
- Al boot:
McpToolRegistryensambla tools de plugins enCORTEX_ENABLED_PLUGINS. - Al togglear plugin en panel Control: registry se actualiza en caliente (misma semántica que plugin guard REST).
tools/listdel servidor MCP refleja solo tools de plugins activos para el tenant.
Autenticación MCP¶
- Mismas reglas que REST: Bearer OIDC + tenant (ADR 005).
- Conexión MCP autenticada; sin acceso anónimo en producción.
Leyenda: MCP como fachada IO hacia agentes; REST y PG son fuente de verdad. Actores: agente, servidor MCP, plugins activos. Estado: Diseño.
flowchart TB
subgraph agent [Agente IA]
LLM["Modelo / Orquestador"]
end
subgraph mcp_layer [cortex_framework.io.mcp]
Server[MCP Server HTTP]
Registry[McpToolRegistry]
end
subgraph plugins [CORTEX_ENABLED_PLUGINS]
BK[cortex_plugin_booking]
CL[cortex_plugin_clients]
end
subgraph truth [Fuente de verdad]
REST["REST /api/v1"]
DB[(PostgreSQL tenant)]
end
LLM --> Server
Server --> Registry
Registry --> BK
Registry --> CL
BK --> REST
CL --> REST
REST --> DB Leyenda: Flujo tools/list y tools/call sin duplicar lógica REST. Estado: Diseño.
sequenceDiagram
participant Agent as Agente
participant MCP as MCP Server HTTP
participant Reg as McpToolRegistry
participant Svc as BookingService
Agent->>MCP: tools/list
MCP->>Reg: tools de plugins activos
Agent->>MCP: tools/call booking.create
MCP->>Svc: handler registrado
Svc->>Svc: misma lógica que POST /api/v1/booking/bookings Leyenda: Ejemplo booking.create invocando el mismo servicio que POST REST. Estado: Diseño.
Integración con loader¶
En load_plugins() (tras hooks existentes):
- Instanciar
McpToolRegistry. - Para cada plugin habilitado: invocar
register_mcp_toolssi existe. - Montar router MCP en
create_app.
Tools objetivo del plugin booking (detalle en ADR 008)¶
| Tool | Acción REST equivalente |
|---|---|
booking.check_availability | GET /api/v1/booking/slots |
booking.create | POST /api/v1/booking/bookings |
booking.cancel | PATCH /api/v1/booking/bookings/{id}/cancel |
booking.list_agenda | GET /api/v1/booking/agenda |
Consecuencias¶
- Positivas: desacople agente ↔ módulo, tools aparecen al activar plugin, un solo lugar para protocolo MCP.
- Negativas: superficie de seguridad nueva; tests E2E con cliente MCP.
- Requiere ampliar
registrar.pyy loader sin romper plugins existentes (hook opcional).