Errores
Las fallas llegan por dos canales distintos, y la distinción importa: uno es una solicitud rota, el otro es algo que el modelo debe leer y a lo que debe reaccionar.
Errores de tool
Todo aquello sobre lo que el llamador puede actuar — validación, no encontrado, scope o permiso insuficiente, un error del endpoint — vuelve como una respuesta JSON-RPC exitosa cuyo resultado está marcado isError, llevando el envoltorio de error de la propia API como texto:
{ "jsonrpc": "2.0", "id": 2, "result": {
"isError": true,
"content": [{ "type": "text",
"text": "{ \"error\": { \"code\": \"NOT_FOUND\", \"message\": \"Payable not found.\" } }" }]
} }
El vocabulario de code es el de la API, sin cambios. Los que más vas a encontrar:
code | Cuándo |
|---|---|
VALIDATION_ERROR | El cuerpo falló la validación del endpoint; details.issues[] nombra cada campo. También cuando los argumentos de la tool (id, filtros) no coinciden con su schema — incluso limit, cursor, sort_by o fields dentro de filters, que son argumentos nombrados. |
BAD_REQUEST | Filtro, operador o nombre de fields desconocido. |
NOT_FOUND | No existe ese registro, o es de otro workspace. |
CONFLICT | Duplicidad, o un registro todavía en uso. |
UNPROCESSABLE_ENTITY | Regla de negocio — borrar una categoría que tiene hijas, liquidar un título sin cuenta. |
SECURITY_BLOCKED | La pestaña Seguridad bloqueó la acción en este canal. |
RATE_LIMITED | Se acabó el presupuesto de la API para esta persona en la organización — ver Límite de solicitudes. |
Y los cuatro que agrega el propio MCP, porque son sobre autorización, no sobre el recurso:
code | Quién lo resuelve |
|---|---|
insufficient_scope | El scope del token no alcanza la tool: el recurso no está en el token, falta acceso de escritura a él, o la tool mueve dinero y el token no trae el recurso de dinero (o all). Usa un token que alcance el recurso con el acceso pedido — por el flujo OAuth el acceso hoy es solo de lectura; un token personal puede traer escritura. |
insufficient_permission | Un admin de la organización, concediendo el permiso que nombra el error. |
workspace_access_denied | El workspace_id no es uno que la persona alcanza (o no existe). Un admin concede el workspace a la persona, o el agente pasa otro, de finance_workspaces_list. |
membership_inactive | Incluir a la persona del token en la organización o reactivarla — ningún permiso arregla una membresía que no existe o está inactiva. |
Están separados a propósito: cuatro conversaciones distintas, con personas distintas. Un error único diría "no puedes" sin decir a quién pedirlo. Ver Autenticación.
Hay también workspace_required: la llamada no trajo workspace_id y la conexión no tiene workspace predeterminado — la persona alcanza varios. El agente llama a finance_workspaces_list y repite la llamada con uno de los id. Ver Autenticación → El workspace.
Y los de la confirmación de tools destructivas — en todos ellos, no se modificó nada:
code | Cuándo |
|---|---|
confirmation_required | Tool destructiva llamada por un cliente que no puede confirmar: era 2025, o 2026-07-28 sin elicitation de formulario. |
USER_DECLINED | En la era 2026-07-28, la persona rechazó o canceló la confirmación. |
confirmation_replayed | La confirmación reenviada ya ejecutó la tool una vez. Llama de nuevo sin requestState para volver a preguntar. |
confirmation_unavailable | El servidor no pudo garantizar la confirmación en ese momento. Inténtalo más tarde. |
input_required no es un error
En la era 2026-07-28, el primer tools/call de una tool destructiva puede volver resultType: "input_required" con un pedido de confirmación a la persona. Es el flujo normal, no una falla: el cliente muestra la pregunta y reenvía la misma llamada con la respuesta. Ver Confirmación de tools destructivas.
Errores de protocolo
Un mensaje malformado recibe un objeto de error JSON-RPC, no un resultado:
| Código | Significado |
|---|---|
-32700 | Parse error — el cuerpo no es JSON válido |
-32600 | Invalid request — no es un objeto JSON-RPC, o es un array (el batching no está soportado) |
-32601 | Method not found |
-32602 | Invalid params — tool, prompt o argumento inexistente, name ausente; en la era 2026-07-28, también resource no encontrado |
-32002 | Resource no encontrado — solo en la era 2025 (la 2026-07-28 usa -32602) |
-32603 | Internal error — falla inesperada al ejecutar la tool |
-32020 | Header mismatch — en la 2026-07-28, un encabezado MCP-Protocol-Version, Mcp-Method o Mcp-Name que no coincide con el cuerpo (HTTP 400) |
-32022 | Unsupported protocol version — la versión pedida no está soportada; data.supported lista las que sí (HTTP 400) |
Errores de transporte
Los rechazos que ocurren antes de leer el mensaje JSON-RPC son respuestas HTTP comunes: token ausente, inválido o emitido para otro recurso, workspace predeterminado (X-Workspace-Id / ?workspace_id=) de otra organización, Origin fuera de la allowlist, límite de solicitudes del protocolo, Cuenta Kobana no disponible para validar el token (503), cuerpo por encima de 14 MB (413, con el error JSON-RPC -32600 Request body too large (limit 14680064 bytes) e id: null). Están listados en Autenticación → Modos de falla.
Por qué isError y no error JSON-RPC
Un 404 en un título no es un defecto del cliente MCP — es información sobre el mundo, y el modelo del otro lado la necesita para corregirse. Enterrarla en un error de protocolo haría que el cliente la tratara como falla de transporte, escondiera el texto y, en el mejor caso, reintentara idéntico. Por eso la regla: si el llamador puede actuar, es resultado; si la solicitud está rota, es error.
Observabilidad
Cada tools/call escribe una línea estructurada con la tool, el workspace, la persona, el tipo de token (oauth o personal), el estado y la duración. Las escrituras quedan registradas con el canal mcp y con la persona del token, así que lo que hizo un agente aparece junto a lo que hizo una persona, en las mismas pantallas.