Conectar Kordia por MCP
URL remota: https://app.example.com/mcp (sustituye el dominio). Transporte HTTP JSON sin estado, solo POST; no hay sesiones, SSE persistente ni peticiones iniciadas por el servidor. REST y MCP comparten operaciones y reglas de dominio.
Configuración del cliente
- Necesitas Pro con estado
active; se comprueba en cada petición, también para discovery y listado de herramientas. Starter permite usar la API REST, pero no MCP. Una bajada a Starter deshabilita MCP inmediatamente sin revocar la clave REST. - En el menú de usuario, abre API keys y MCP y despliega Conectar un agente por MCP. Ahí puedes copiar la URL de tu instancia. Crea una clave seleccionando los permisos mínimos; el token se muestra una vez. Las claves antiguas no ganan permisos automáticamente.
- Guarda el secreto en
KORDIA_API_KEYy la URL enKORDIA_MCP_URL. Configura en tu cliente un servidor HTTP remoto con esa URL yAuthorization: Bearer <valor de KORDIA_API_KEY>. Usa el mecanismo de secretos/env del cliente; la sintaxis de interpolación depende del cliente. No copies el token en configuración versionada.
No es OAuth: el Bearer es una API key de organización. También se admite X-API-Key. No hacen falta credenciales de cuenta personal ni un servidor local intermediario.
El cliente debe poder alcanzar la URL: una IP privada de desarrollo solo funciona desde esa red o una VPN con acceso. Los agentes alojados en la nube necesitan una instancia accesible por HTTPS. El cliente debe permitir Bearer token o cabeceras personalizadas; un conector que exija OAuth no es compatible con esta autenticación.
Cabeceras:
Authorization: Bearer <KORDIA_API_KEY>
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2025-11-25
Ejemplo con variables de entorno ya configuradas, sin imprimir la clave:
curl --fail-with-body "$KORDIA_MCP_URL" \
-H "Authorization: Bearer $KORDIA_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2025-11-25' \
--data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"my-integration","version":"1.0"}}}'
Versiones y transporte
Se admiten 2026-07-28, 2025-11-25, 2025-06-18 y 2025-03-26. Sin cabecera de versión se utiliza compatibilidad 2025-03-26.
- Clientes 2025:
initializenegocia una de las tres versiones 2025 (fallback2025-11-25); después pueden enviarnotifications/initialized,tools/listytools/call. - Clientes 2026: usa
server/discovery metadatos por petición.MCP-Protocol-Versiondebe coincidir conparams._meta["io.modelcontextprotocol/protocolVersion"];MCP-Method, con el método; y paratools/call,MCP-Name, con el nombre de herramienta. Se requieren tambiénio.modelcontextprotocol/clientInfo(name/version) yio.modelcontextprotocol/clientCapabilitiesen_meta. Las respuestas incluyenresultType: "complete".
Ejemplo de cuerpo 2026 para listar herramientas (cabeceras MCP-Protocol-Version: 2026-07-28 y MCP-Method: tools/list):
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"my-integration","version":"1.0"},"io.modelcontextprotocol/clientCapabilities":{}}}}
tools/list devuelve las 12 herramientas y sus esquemas; no acepta cursor. El listado no concede permisos: cada llamada comprueba scopes. ping está disponible. Las notificaciones sin ID reciben 202 sin cuerpo; GET/DELETE reciben 405. No hay soporte de lotes JSON-RPC.
Herramientas
| Herramienta | Argumentos y propósito | Scope |
|---|---|---|
kordia_search |
entity: projects/resources/tags/assignments/contracts; limit, offset y filtros compatibles |
<entity>:read |
kordia_get |
entity singular y id; organization no necesita ID; include: "monthly_hours", from, to opcionales |
<colección>:read / organization:read |
kordia_report |
kind: project_hours/resource_hours/availability/tag_breakdown; id, year o from/to |
projects:read o resources:read |
kordia_plan_assignment |
project_id, fechas y daily_hours o total_hours; resource_id para reparto calculado |
assignments:read |
kordia_preview_contract_change |
operation: create/update/delete; atributos de contrato, id para update/delete |
contracts:read |
kordia_manage_project |
action: create/update/archive/unarchive/delete |
projects:write |
kordia_manage_resource |
action: create/update/delete |
resources:write |
kordia_manage_assignment |
action: create/update/delete |
assignments:write |
kordia_manage_contract |
action: create/update/delete |
contracts:write |
kordia_manage_tag |
action: create/update/delete |
tags:write |
kordia_update_organization |
name, default_annual_convention_hours |
organization:write + administrador actual |
kordia_manage_members |
action: list/invite/update_role/remove/revoke_invitation |
members:read para list; resto members:write, siempre administrador actual |
En operaciones administrativas, quien creó la clave debe seguir siendo administrador. invite recibe email y envía correo; update_role recibe ID de membresía y role (admin/member); remove usa ID de membresía y revoke_invitation ID de invitación. Se mantienen las protecciones del último administrador y de cambios sobre uno mismo.
Los atributos se envían directamente en arguments, no bajo attrs. Update/delete necesitan id; los campos omitidos se conservan. Usa tools/list para consultar los esquemas. La gestión personal de cuenta, checkout/facturación y borrado de organización permanecen en la UI: no se promete toda la UI por MCP.
Ejemplos de herramientas
Cuerpo compatible con 2025; en 2026 añade _meta a params y las cabeceras correspondientes:
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"kordia_plan_assignment","arguments":{"project_id":10,"start_date":"2026-06-01","end_date":"2026-06-30","total_hours":80,"query":"Ana","tag_ids":[3],"limit":20}}}
Sin resource_id, el autocompletado devuelve candidatos por disponibilidad (exact: false), no un optimizador global ni garantía de reparto viable. Admite query, tag_ids, limit y after_id; continúa enviando el next_after_id recibido como after_id. Puede haber next_after_id aunque candidates esté vacío: el filtrado de disponibilidad se realiza después de seleccionar la página.
Para previsualizar el reparto calculado, elimina filtros query/tag_ids/limit/after_id y añade resource_id. En modo total_hours, preview y escritura incluyen requested_total_hours, planned_total_hours, deviation_hours, tolerance_hours y exact; total_hours es un alias del total planificado. El planificador compartido con la UI admite una tolerancia de 0.01 horas, ajustando jornadas de dos decimales sin superar el total solicitado. Inspecciona la desviación antes de guardar y revisa también el resultado de escritura. El preview no reserva capacidad. Para guardar:
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"kordia_manage_assignment","arguments":{"action":"create","project_id":10,"resource_id":7,"start_date":"2026-06-01","end_date":"2026-06-30","total_hours":80,"cost_source":"contract_default"}}}
total_hours debe ser entero entre 1 y 14616 y puede generar varios segmentos. Alternativamente daily_hours admite 0.01–8 con hasta dos decimales; no envíes ambos. Para coste manual: cost_source: "manual_override", cost_per_hour: "50.00". Se revalidan contratos, capacidad, solapes, fechas y archivo al guardar.
Preview y resolución explícita de una actualización contractual:
{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"kordia_preview_contract_change","arguments":{"id":5,"operation":"update","daily_hours":4}}}
{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"kordia_manage_contract","arguments":{"action":"update","id":5,"daily_hours":4,"conflict_policy":"resolve","entry_ids":[42]}}}
Reemplaza entry_ids con conflictos actuales devueltos en data.conflicts. La política por defecto es reject, también al crear un sucesor. Resolver no permite modificar asignaciones no seleccionadas o archivadas ni forzar un borrado bloqueado; si la selección es insuficiente, se revierte toda la operación. Preview no guarda cambios. Los contratos usan daily_hours entero de 1 a 8; para crear, añade resource_id, start_date, end_date (puede ser null), annual_convention_hours y cost_per_hour según corresponda.
{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"kordia_report","arguments":{"kind":"availability","year":2026}}}
availability sin ID incluye todos los recursos; con id, uno. project_hours/tag_breakdown requieren ID de proyecto y resource_hours, ID de recurso. Usa year o el par from/to, no ambos.
Orígenes y errores
Clientes no navegador pueden omitir Origin. Si se envía, debe coincidir exactamente con un origen autorizado. Por defecto solo se confía en el origen público del endpoint. Los operadores pueden configurar una lista explícita mediante config :kordia, :mcp_trusted_origins, ["https://app.example.com"]; no es una variable de entorno automática ni una autorización CORS general. No desactives esta protección para resolver errores de cliente.
HTTP 401 indica clave inválida; 403 puede indicar suscripción o Origin no autorizado. Revisa también JSON-RPC error y result.isError, no solo el HTTP. Los éxitos de herramientas incluyen texto JSON y structuredContent; errores de dominio incluyen code, message y detalles cuando procede.
No hay idempotencia automática: no reintentes mutaciones a ciegas tras fallos de red. Consulta el estado y reconcilia primero. Para proyectos/recursos, external_id único por organización y entidad ayuda a detectar duplicados, pero no convierte una creación en upsert. Más detalles y rutas equivalentes: API REST.