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

  1. 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.
  2. 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.
  3. Guarda el secreto en KORDIA_API_KEY y la URL en KORDIA_MCP_URL. Configura en tu cliente un servidor HTTP remoto con esa URL y Authorization: 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: initialize negocia una de las tres versiones 2025 (fallback 2025-11-25); después pueden enviar notifications/initialized, tools/list y tools/call.
  • Clientes 2026: usa server/discover y metadatos por petición. MCP-Protocol-Version debe coincidir con params._meta["io.modelcontextprotocol/protocolVersion"]; MCP-Method, con el método; y para tools/call, MCP-Name, con el nombre de herramienta. Se requieren también io.modelcontextprotocol/clientInfo (name/version) y io.modelcontextprotocol/clientCapabilities en _meta. Las respuestas incluyen resultType: "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.