Arquitectura¶
Para curiosos y contribuidores. La fuente autoritativa es
docs/architecture.md
del repositorio.
Claude (cliente MCP)
│ stdio (JSON-RPC MCP)
▼
odoo_mcp.server ──lista/despacha──▶ registry (ToolRegistry)
│ │
│ ▼
│ tools/ (crud, meta, export, i18n, report)
│ │ resolve_model / resolve_fields
│ ▼
│ compat/ (detect → deltas → resolve)
▼ │
tenancy.ConnectionManager ──▶ session.OdooSession ──▶ transport/
(por tenant) (auth, facts, cache) fallback → jsonrpc | xmlrpc
│
▼
Instancia Odoo
Capas¶
- transport/ —
XmlRpcTransport,JsonRpcTransportyFallbackTransport(auto: JSON-RPC primero, fallback transparente a XML-RPC ante rechazo de API key o error de transporte; fija XML-RPC tras el primer fallback y avisa una vez). - session.py —
OdooSessionguarda credenciales, autentica de forma perezosa (uid), cachea los facts de versión/edición/despliegue y envuelve las lecturas de esquema en la caché TTLSchemaCache.ConnectionManager(tenancy.py) mapea la huella del tenant (url|db|login, nunca el secreto) a una sesión. - compat/ —
detect.probe()construyeEnvFacts;deltas.pyes el mapa declarativo de deltas;resolve.pyconvierte un modelo/campo/capacidad solicitado en lo que exista en el destino. Cada herramienta llama aresolve_*antes del ORM. - tools/ — manejadores delgados registrados sobre el
registrycompartido. Las herramientas de escritura llevanread_only=Falsepara futuras compuertas de política; el núcleo público no aplica compuertas de aprobación (eso pertenece a una capa de gobernanza privada). - observability.py — métricas Prometheus y trazas OTLP opcionales, ambas apagadas por defecto y no-ops si los extras no están instalados.
- server.py / main.py — cableado MCP stdio y el punto de entrada
odoo-mcp. Los manejadores corren en un hilo de trabajo (anyio.to_thread) para que un RPC bloqueante nunca detenga el event loop. Los logs van a stderr; stdout es exclusivo del canal MCP.
Transportes y modos¶
- stdio (por defecto): un solo tenant, credenciales del entorno. Es el modo
que usa la entrada
mcpServersdel plugin. - HTTP (docker, opcional/roadmap): multi-tenant vía cabeceras
X-Odoo-Url/Db/Login+ secretoBearer, resuelto portenancy.from_headers.
Principios de diseño¶
- Una sola superficie de herramientas entre versiones — quien llama usa nombres modernos.
- Fallar con remediación —
CompatErrorexplica qué cambiar; los campos no disponibles degradan a advertencias, no a fallos duros. - Instalación base ligera — los deps opcionales (cache/metrics/otel) nunca bloquean el arranque.
- Sin secretos en logs ni en disco.