# Servidor MCP de RRHH

Conecta tu asistente de IA al fichaje de la jornada y a las ausencias: herramientas, operaciones, scopes, permisos y lo que solo se hace en la aplicación.

El servidor MCP de RRHH (`utilia-rrhh`) conecta tu asistente de IA con el fichaje de la jornada y las ausencias de UTILIA OS: fichar, consultar y corregir el registro, «Equipo hoy», horarios, festivos, incidencias, documentos de la jornada, vacaciones y permisos. Hace lo mismo que la aplicación, con los mismos permisos y la misma regla, salvo lo que deja constancia legal y las descargas de documentos, que se hacen en la aplicación.

| Dato | Valor |
| - | - |
| Dirección | `https://os.utilia.ai/api/mcp/rrhh` |
| Nombre en «Conecta tu IA» | RRHH |
| Metadatos de descubrimiento | `GET /.well-known/mcp-rrhh.json` |
| Scopes | `hr:*`, más los del plan, los avisos y los tickets propios |

## Cómo se conecta

Se conecta igual que los demás servidores: desde [Conecta tu IA](https://os.utilia.ai/dashboard/settings/connect-ai) autorizas tu cliente MCP con OAuth o generas una clave personal para este servidor. El proceso completo está en [Primeros pasos con MCP](https://os.utilia.ai/docs/developers/mcp/quickstart). Cada token se emite para `/api/mcp/rrhh` y solo sirve ahí.

## Qué comprueba en cada operación

**Qué comprueba el servidor de RRHH**

1. **RRHH en el plan** (Tu organización): Las horas imputadas piden además Gestión de proyectos. Si no: el servidor no se anuncia y se rechaza; ningún permiso lo abre.
2. **Scope de la operación** (El token): Una escritura nunca se ejecuta con un scope de lectura. Si no: INSUFFICIENT_SCOPE con el scope que falta.
3. **Permiso de la operación** (Tu usuario): Es el mismo permiso que pide la pantalla equivalente. Si no: PERMISSION_DENIED con el permiso que falta.
4. **Tu alcance** (Las filas): Toda la empresa, tu departamento, tus personas o solo lo tuyo. Si no: la persona o la ausencia no se ven, como en la aplicación.

Cada operación valida sus datos con las mismas reglas que la aplicación y llama al mismo servicio: el asistente no puede hacer nada que tu usuario no pueda hacer en la pantalla, ni ver una fila que tu alcance no te deja ver.

## Herramientas

| Herramienta | Para qué sirve |
| - | - |
| `attendance` | El fichaje: tu jornada, tus correcciones y documentos, «Equipo hoy», revisar el registro de otras personas y administrar horarios, ajustes, festivos, incidencias, datos laborales e informes de jornada. |
| `leave_management` | Ausencias: las tuyas, las de tu equipo, los justificantes, los días de vacaciones de cada persona y los ajustes de ausencias. |
| `notifications` | Tus avisos y por qué canal te llega cada tipo. Los de RRHH salen en la categoría «RRHH». |
| `org_plan` | El plan de tu organización. |
| `my_tickets` | Reportar y seguir lo tuyo con el soporte de UTILIA. |

## Scopes

Son siete, separados por lo que hacen: leer, actuar sobre lo tuyo, decidir sobre lo de otras personas y administrar. La columna de la derecha es el texto que ve la persona en la [pantalla de consentimiento](https://os.utilia.ai/docs/developers/oauth/consent-screen).

| Scope | Lo que consiente la persona |
| - | - |
| `hr:attendance:view` | Ver tus fichajes, y los de tu equipo si tu permiso lo alcanza, con sus horarios, festivos e incidencias |
| `hr:attendance:clock` | Fichar tu jornada, pedir que se corrija tu registro y responder a las correcciones |
| `hr:attendance:manage` | Administrar horarios, ajustes, festivos, incidencias, datos laborales e informes de jornada (incluye corregir el registro de jornada y sacar informes del equipo) |
| `hr:leave:view` | Ver tus ausencias, y las de tu equipo si tu permiso lo alcanza (pueden incluir datos de salud) |
| `hr:leave:request` | Pedir, cambiar y cancelar tus ausencias y responder a las que te propongan |
| `hr:leave:approve` | Aprobar o rechazar las ausencias de otras personas, registrarlas en su nombre y pedir sus justificantes |
| `hr:leave:manage` | Gestionar los días de vacaciones de cada persona y los ajustes de ausencias |

Los conjuntos `hr:read`, `hr:write` y `hr:full` están en [Scopes y recursos](https://os.utilia.ai/docs/developers/oauth/scopes-and-resources#conjuntos). Pide `hr:leave:view` solo si tu integración necesita ausencias: sin él, nada de lo que devuelve `attendance` lleva el tipo de una ausencia.

## `attendance`: tu jornada

El sujeto es siempre el dueño del token.

| Operación | Qué hace | Permiso | Scope |
| - | - | - | - |
| `clock_in`, `clock_out` | Ficha la entrada o la salida. | `ATTENDANCE_CHECK_IN_OUT` | `hr:attendance:clock` |
| `break_start`, `break_end` | Empieza la pausa o vuelve de ella. | `ATTENDANCE_BREAK` | `hr:attendance:clock` |
| `status` | Si estás trabajando o en pausa, desde cuándo y cuánto llevas hoy. | `ATTENDANCE_VIEW` | `hr:attendance:view` |
| `history` | Tus jornadas, con cada fichaje, sus incidencias (`label`) y, en lo que corrigió otra persona, quién fue (`correctedBy`). | `ATTENDANCE_VIEW` | `hr:attendance:view` |
| `summary` | Tus horas de la semana, el mes, el trimestre o el año frente a tu horario. | `ATTENDANCE_VIEW_SUMMARY` | `hr:attendance:view` |
| `my_policy` | Tu horario de hoy y de dónde sale. | `ATTENDANCE_VIEW` | `hr:attendance:view` |
| `corrections_my` | Tus peticiones de corrección; las pendientes dicen quién las revisa (`reviewer`). | `ATTENDANCE_VIEW` | `hr:attendance:view` |
| `correction_request` | Pide que se corrija un día: `date`, `kind`, `entries` y `reason`. | `ATTENDANCE_VIEW` | `hr:attendance:clock` |
| `correction_cancel` | Retira una petición tuya pendiente. | `ATTENDANCE_VIEW` | `hr:attendance:clock` |
| `record_acknowledge` | Responde a una corrección de tu registro: `AGREED` («Estoy conforme») o `DISAGREED` con una nota. | `ATTENDANCE_VIEW` | `hr:attendance:clock` |
| `statements_my`, `statement_acknowledge` | Tus resúmenes mensuales (los datos, no el PDF) y el acuse de recibo. | `ATTENDANCE_VIEW_SUMMARY` | `hr:attendance:view` / `hr:attendance:clock` |
| `working_conditions_my` | Tu información escrita sobre la jornada. | `ATTENDANCE_VIEW` | `hr:attendance:view` |
| `working_conditions_request`, `working_conditions_acknowledge` | Pedirla y acusar su recibo. | `ATTENDANCE_VIEW` | `hr:attendance:clock` |
| `protocol_get` | El protocolo del registro de jornada publicado, en texto. | `ATTENDANCE_VIEW` o `ATTENDANCE_MANAGE_POLICIES` | `hr:attendance:view` |
| `time_vs_logged` | Tus horas fichadas frente a las imputadas en Gestión de proyectos. | `ATTENDANCE_VIEW` y `DEV_ISSUES_VIEW` | `hr:attendance:view` |
| `overtime_annual` | Tus horas extraordinarias del año frente al tope, mes a mes (`year`). | `ATTENDANCE_VIEW` o `ATTENDANCE_VIEW_SUMMARY` | `hr:attendance:view` |
| `overtime_monthly_statement` | Los datos de tu resumen del mes (`year`, `month`): cada día, sus horas y los totales. El documento se descarga en la aplicación. | `ATTENDANCE_VIEW` o `ATTENDANCE_VIEW_SUMMARY` | `hr:attendance:view` |
| `effective_calendar_my` | Qué se esperaba de cada día de un rango (`startDate`, `endDate`) y qué pasó: festivo, día libre, ausencia o jornada con su diferencia. | `ATTENDANCE_VIEW` | `hr:attendance:view` |

Al fichar desde un asistente, el método lo pone el servidor (`API`) y la ubicación que mandes no se guarda ni cuenta como dentro de la zona. Si tu horario pide la ubicación, o limita los métodos sin incluir este, el fichaje se rechaza con `ATTENDANCE_CHANNEL_NOT_ALLOWED` y la pista de fichar desde la aplicación.

## `attendance`: el equipo y el registro de otras personas

| Operación | Qué hace | Permiso | Scope |
| - | - | - | - |
| `team_day` | «Equipo hoy» de un día (`date`): quién trabaja, está en pausa, ha terminado, falta o no trabaja. | `ATTENDANCE_VIEW_TEAM` o `ATTENDANCE_VIEW_ALL` | `hr:attendance:view` |
| `team_list`, `team_user_history` | Jornadas de las personas que alcanzas, con filtros. | `ATTENDANCE_VIEW_TEAM` o `ATTENDANCE_VIEW_ALL` | `hr:attendance:view` |
| `effective_calendar_user` | El mismo calendario de cada día para una persona que alcanzas (`userId`). | `ATTENDANCE_VIEW_TEAM` o `ATTENDANCE_VIEW_ALL` | `hr:attendance:view` |
| `overtime_annual`, `overtime_monthly_statement` con `userId` | Las horas extraordinarias y el resumen del mes de una persona que alcanzas. | Los mismos, y alcance sobre ella con `ATTENDANCE_VIEW_TEAM` o `ATTENDANCE_VIEW_ALL` | `hr:attendance:view` |
| `corrections_list`, `correction_get` | Las peticiones de corrección que te tocan y su detalle. | `ATTENDANCE_CORRECT` (el detalle, también `ATTENDANCE_VIEW` para la tuya) | `hr:attendance:view` |
| `correction_apply` | Aplica una petición; si cambias lo propuesto, `note` es obligatoria. | `ATTENDANCE_CORRECT` | `hr:attendance:manage` |
| `correction_reject` | La rechaza con `note`. | `ATTENDANCE_CORRECT` | `hr:attendance:manage` |
| `disagreements_list` | Las respuestas «No estoy de acuerdo» a una corrección. | `ATTENDANCE_CORRECT` | `hr:attendance:view` |
| `log_correct`, `log_manual_create` | Corrige un fichaje o añade uno que falta, con `reason`. | `ATTENDANCE_CORRECT` | `hr:attendance:manage` |
| `session_validate` | Valida una jornada. | `ATTENDANCE_VALIDATE` | `hr:attendance:manage` |
| `anomalies_list` | Incidencias, por grupo (`urgent` u `other`) y por persona, con su rótulo y los recuentos. | `ATTENDANCE_VIEW_ANOMALIES` | `hr:attendance:view` |
| `anomalies_resolve` | Da por buena una incidencia con una nota. La jornada queda completada si no le queda ninguna. | `ATTENDANCE_RESOLVE_ANOMALIES` | `hr:attendance:manage` |
| `statements_list` | Resúmenes mensuales de otras personas. | `ATTENDANCE_VIEW_ALL`, `ATTENDANCE_VIEW_TEAM` o `ATTENDANCE_EXPORT` | `hr:attendance:view` |
| `overtime_adjustments_list` | Horas extraordinarias de fuerza mayor o compensadas con descanso. | `ATTENDANCE_CORRECT` | `hr:attendance:view` |
| `overtime_adjustment_create` | Registra uno de esos ajustes; nunca más horas de las que constan. Exige `confirm: true`. | `ATTENDANCE_CORRECT` | `hr:attendance:manage` |

Nadie corrige, valida ni ajusta su propio registro, tampoco por MCP. Las incidencias de la lista del equipo no llevan coordenadas: las de ubicación dicen a qué distancia se fichó de la zona permitida.

El motivo de una corrección y la nota de un desacuerdo forman parte del registro de jornada: los ven también la representación legal de la plantilla y la Inspección de Trabajo. Que tu asistente no escriba datos de salud en ellos.

## `attendance`: administración

| Operación | Qué hace | Permiso | Scope |
| - | - | - | - |
| `policies_list`, `policies_get` | Horarios. | `ATTENDANCE_MANAGE_POLICIES` o `ATTENDANCE_VIEW_POLICIES` | `hr:attendance:view` |
| `policies_create`, `policies_update`, `policies_delete`, `policies_create_override`, `policies_remove_override` | Crear, cambiar y quitar horarios y sus excepciones por persona. | `ATTENDANCE_MANAGE_POLICIES` | `hr:attendance:manage` |
| `schedules_list` | Periodos de un horario (verano, Navidad). | `ATTENDANCE_VIEW_POLICIES` o `ATTENDANCE_MANAGE_POLICIES` | `hr:attendance:view` |
| `schedules_validate` | Ensaya un horario sin guardarlo y devuelve lo que se saldría de un mínimo. | `ATTENDANCE_VIEW_POLICIES` o `ATTENDANCE_MANAGE_POLICIES` | `hr:attendance:view` |
| `schedules_create`, `schedules_update` | Crea o cambia un periodo. | `ATTENDANCE_MANAGE_POLICIES` | `hr:attendance:manage` |
| `schedules_delete` | Quita un periodo: lo borra si no ha empezado y lo cierra ayer si ya empezó. Exige `confirm: true`. | `ATTENDANCE_MANAGE_POLICIES` | `hr:attendance:manage` |
| `settings_get` | Ajustes del fichaje de la empresa. | `ATTENDANCE_MANAGE_POLICIES`, `ATTENDANCE_VIEW_POLICIES` o `ATTENDANCE_MANAGE_HOLIDAYS` | `hr:attendance:view` |
| `settings_update` | Cambia los ajustes que mandes en `settings`. | `ATTENDANCE_MANAGE_POLICIES` o `ATTENDANCE_MANAGE_HOLIDAYS` | `hr:attendance:manage` |
| `setup_checks` | Lo que falta por configurar en RRHH, en cifras: quién no puede fichar, quién no tiene fecha de incorporación y más. Cada cifra cuenta solo a quien alcanzas; si no te toca, `null`. | Cualquiera de los permisos de Ajustes › RRHH (horarios, festivos, días por persona, informes o código QR) | `hr:attendance:view` o `hr:leave:view` |
| `holidays_*` | Festivos y calendario laboral: ver [RRHH: festivos y calendario laboral](https://os.utilia.ai/docs/developers/mcp/reference#rrhh-festivos-y-calendario-laboral). | `ATTENDANCE_MANAGE_HOLIDAYS` | `view` / `manage` |
| `qr_generate` | Genera el código de un punto de fichaje QR. | `ATTENDANCE_GENERATE_QR` | `hr:attendance:manage` |
| `export` | Saca el registro de jornada de un periodo y devuelve el identificador del fichero. | `ATTENDANCE_EXPORT` | `hr:attendance:manage` |
| `export_logs`, `export_audit` | Historial de informes sacados y su detalle. | `ATTENDANCE_EXPORT` | `hr:attendance:view` |
| `working_conditions_list` | Información escrita entregada a la plantilla. | `ATTENDANCE_MANAGE_POLICIES` o `ATTENDANCE_VIEW_ALL` | `hr:attendance:view` |
| `employment_get` | Datos laborales de una persona, con el mismo recorte de campos que su ficha. | `ATTENDANCE_VIEW`, `ATTENDANCE_VIEW_TEAM`, `ATTENDANCE_VIEW_ALL`, `ATTENDANCE_MANAGE_POLICIES` o `SETTINGS_USERS_EDIT` | `hr:attendance:view` |
| `employment_update` | Cambia sus datos laborales. | `ATTENDANCE_MANAGE_POLICIES` o `SETTINGS_USERS_EDIT` | `hr:attendance:manage` |
| `employment_settlement` | Cálculo de las vacaciones pendientes de liquidar. | `LEAVE_MANAGE_BALANCES` o `SETTINGS_USERS_EDIT` | `hr:attendance:view` o `hr:leave:view` |
| `integrity_status` | Estado de la comprobación del registro: fechas del último sello y de la comprobación, y su resultado. | `ATTENDANCE_EXPORT` o `ATTENDANCE_VIEW_ALL` | `hr:attendance:view` |

Por MCP, cambiar festivos, cargar el año, elegir su ámbito, resolver incidencias, generar el código QR y sacar informes de jornada (y consultar su historial) exigen el permiso con alcance «Todo». Si no, responden `FORBIDDEN` con `details.errorCode: PERMISSION_DENIED`, aunque en la aplicación tu alcance te deje hacerlo con tu departamento.

En `settings_update`:

- `holidayAutoLoad` lo cambia quien gestiona horarios o festivos de toda la empresa; el resto de claves, solo quien gestiona horarios de toda la empresa.
- El alcance de los responsables (`departmentScopeIncludesChildren`) no se cambia por aquí: se rechaza con `VALIDATION`, porque cambia lo que ve y aprueba cada responsable de la empresa.
- El día desde el que la empresa cuenta el máximo de horas ordinarias al día (`dailyOrdinaryMaxFrom`) no lo cambia nadie: `settings_get` lo devuelve y `settings_update` lo rechaza con `VALIDATION`.
- La política de desconexión solo admite un documento ya subido desde Ajustes › RRHH › Recordatorios y desconexión (`disconnectionPolicyFileId`), o `null` para quitarla. `settings_get` la devuelve en `disconnectionPolicyFile`.

## `leave_management`

| Operación | Qué hace | Permiso | Scope |
| - | - | - | - |
| `types` | Tipos de ausencia, con si se piden o se comunican. | Cualquiera de ver o pedir ausencias, aprobar o gestionar días | `hr:leave:view` |
| `requests_my_list`, `balances_my`, `request_get` | Tus ausencias, tus días y el detalle de una ausencia. | `LEAVE_VIEW_OWN` o `LEAVE_REQUEST_OWN` (el detalle, también los de equipo) | `hr:leave:view` |
| `request_preview` | Cuántos días te costaría una ausencia (`type`, `startDate`, `endDate`), con el reparto por año y los avisos. No pide nada. | `LEAVE_REQUEST_OWN` | `hr:leave:view` |
| `request_create`, `request_update` | Pide o cambia una ausencia tuya. | `LEAVE_REQUEST_OWN` | `hr:leave:request` |
| `request_cancel` | Cancela una ausencia. La de otra persona exige `hr:leave:approve` en el token. | `LEAVE_REQUEST_OWN` o `LEAVE_APPROVE` | `hr:leave:request` o `hr:leave:approve` |
| `agreement_respond` | Responde a una ausencia que te han propuesto; si no estás de acuerdo, con una nota. | `LEAVE_REQUEST_OWN` | `hr:leave:request` |
| `adjust_end` | Cambia el fin de una ausencia comunicada. La de otra persona exige `hr:leave:manage` en el token. | `LEAVE_REQUEST_OWN` o `LEAVE_MANAGE_BALANCES` | `hr:leave:request` o `hr:leave:manage` |
| `justification_provide` | Aporta a tu ausencia un justificante ya subido (`fileId`). | `LEAVE_REQUEST_OWN` | `hr:leave:request` |
| `expiry_notices_list` | Avisos formales de que unos días van a caducar. | `LEAVE_VIEW_OWN`, `LEAVE_REQUEST_OWN`, `LEAVE_MANAGE_BALANCES` o `LEAVE_VIEW_ALL` | `hr:leave:view` |
| `request_agenda` | Lo que coincide con una ausencia en otros módulos («Antes de irte»). En una tuya que se pide, cuántas invitaciones del Calendario quedan por responder (`declineInvitations.count`). | `LEAVE_VIEW_OWN`, `LEAVE_APPROVE`, `LEAVE_VIEW_TEAM` o `LEAVE_VIEW_ALL` | `hr:leave:view` |
| `agenda_decline_invitations` | «Avisar de que no estaré»: responde «No asistiré» a tus invitaciones de los días de esa ausencia que quedan por delante; cada organizador recibe la respuesta. Exige `confirm: true` y el Calendario en el plan. | `LEAVE_REQUEST_OWN` | `hr:leave:request` |
| `team_calendar` | Calendario de ausencias del equipo. | `LEAVE_VIEW_TEAM`, `LEAVE_APPROVE` o `LEAVE_VIEW_ALL` | `hr:leave:view` |
| `requests_list`, `pending_approvals` | Ausencias del equipo y las que esperan tu decisión. | `LEAVE_VIEW_ALL` o `LEAVE_VIEW_TEAM`; las pendientes, `LEAVE_APPROVE` | `hr:leave:view` |
| `request_approve`, `request_reject` y sus lotes `_many` | Decide sobre las solicitudes (hasta 50 en `items`). Las comunicadas no se aprueban ni se rechazan. | `LEAVE_APPROVE` | `hr:leave:approve` |
| `request_for_user` | Registra una ausencia en nombre de otra persona. En un tipo que se pide, crea una propuesta que la persona acepta o no. | `LEAVE_APPROVE` o `LEAVE_MANAGE_BALANCES` | `hr:leave:approve` o `hr:leave:manage` |
| `justification_request`, `justification_accept` | Pide o acepta el justificante de una ausencia. | `LEAVE_APPROVE` o `LEAVE_MANAGE_BALANCES` | `hr:leave:approve` o `hr:leave:manage` |
| `balances_summary`, `balances_get_user` | Días de la plantilla y de una persona. | `LEAVE_MANAGE_BALANCES`; los de una persona, también `LEAVE_VIEW_ALL` o `LEAVE_VIEW_TEAM` | `hr:leave:view` |
| `balances_workforce` | Una fila por persona con sus días, también quien todavía no tiene ninguno asignado. | `LEAVE_MANAGE_BALANCES` | `hr:leave:view` |
| `reclassification_review` | Ausencias de «Asuntos propios» u «Otra ausencia» desde el 30 de junio de 2023 que conviene revisar por si son otro permiso. | `LEAVE_MANAGE_BALANCES` | `hr:leave:view` |
| `request_reclassify` | Corrige el tipo de una ausencia aprobada o pendiente, con `type` y un motivo (`reason`) que queda en su historial. Los días se mueven desde los que ya contó la ausencia. | `LEAVE_MANAGE_BALANCES` | `hr:leave:manage` |
| `policy_propagation_preview`, `policy_propagation_apply` | Llevar los días de vacaciones de un horario (`policyId`) a toda su plantilla: primero a cuántas personas llega; después, con `confirm: true`, se aplica. Solo cambia los días totales. | `LEAVE_MANAGE_BALANCES` | `hr:leave:view` / `hr:leave:manage` |
| `employer_limit` | Aplaza o limita un permiso por necesidades de la empresa, con motivo y otras fechas. Exige `confirm: true`. | `LEAVE_MANAGE_BALANCES` | `hr:leave:manage` |
| `carryover_lift_expiry` | Quita la caducidad a unos días protegidos por una baja. Exige `confirm: true`. | `LEAVE_MANAGE_BALANCES` | `hr:leave:manage` |
| `balance_adjust`, `balances_adjust_bulk`, `balances_initialize`, `proration_recalculate` | Ajusta los días de una o varias personas, prepara el año o recalcula la parte proporcional de una incorporación. | `LEAVE_MANAGE_BALANCES` | `hr:leave:manage` |
| `settings_get`, `settings_update` | Ajustes de ausencias de la empresa. | `LEAVE_MANAGE_BALANCES` | `hr:leave:view` / `hr:leave:manage` |

Cancelar la ausencia de otra persona con solo «Ver todas las ausencias» se puede en la aplicación, pero no por MCP: ese permiso no autoriza un scope de escritura de ausencias.

## Ausencias comunicadas y datos de salud

**Una ausencia que se pide y una que se comunica**

### Se pide (Vacaciones, asuntos propios)

Queda pendiente hasta que alguien con LEAVE_APPROVE la aprueba o la rechaza.

### Se comunica (Bajas y permisos que se avisan)

Queda registrada al momento: no se aprueba ni se rechaza. Llega con status APPROVED y statusLabel «Comunicada».

- **Lee `statusLabel`, no `status`**, para hablar de una ausencia. Trae el rótulo de la pantalla: «Comunicada», «Hasta nuevo aviso», «Registrada», «Pendiente de tu conformidad», «Propuesta enviada», «Aplazada por la empresa», «Limitada por la empresa» o «Falta el justificante». Una comunicada nunca se describe como aprobada.
- **El tipo de una ausencia ajena puede llegar como `null`.** El servidor lo quita si tu usuario no puede verlo, como en la pantalla: de una ausencia comunicada, solo lo ve quien gestiona RRHH; quien supervisa ve «Ausencia».
- **Sin `hr:leave:view` en el token**, `team_day` dice «Ausencia» en todas, `employment_settlement` devuelve la cifra sin el detalle de los días (`lotsHidden: true`), `export` sale sin ningún tipo de ausencia, `overtime_monthly_statement` y `effective_calendar_*` dicen «Ausencia» en cada día (también en los tuyos) y `request_reclassify` no devuelve el tipo que tenía la ausencia (`typeHidden: true`).
- **Los filtros** ya no ofrecen `PARTIALLY_APPROVED`; `DRAFT` es una propuesta pendiente de la conformidad de la persona, y hay un filtro `justificationStatus`.

## Lo que se hace en la aplicación

Estas funciones no tienen operación, a propósito:

| Función | Motivo |
| - | - |
| Descargar documentos: resumen mensual y ZIP del mes, información escrita, protocolo, «Descargar mi registro», liquidación y calendario laboral | El servidor devuelve datos, no documentos. |
| Redactar, cambiar y publicar el protocolo | Deja constancia de la consulta a la representación. |
| Registro de jornada de la representación, su registro de accesos y sus informes de horas extraordinarias | Exige la concesión expresa y que consulte la persona representante. |
| Enlaces para la Inspección | Se crean en una sesión propia, nunca desde una integración. |
| Paquetes de permisos de RRHH | Se dan en Ajustes › Usuarios. Por MCP, `team_management` da permisos sueltos y responde `PERMISSION_BUNDLE_ONLY` con el de la representación. |
| Subir un justificante, el pacto de horas complementarias o la política de desconexión | Son ficheros que se suben en la aplicación. Un justificante ya subido se aporta con `justification_provide`. |
| Marcar como leído un aviso formal de vacaciones | Prueba que lo leyó la persona; un asistente no puede acreditarlo. |
| Ajuste de la liquidación, sugerencia del ámbito de festivos, calendario laboral, informe de días perdidos y limpieza de festivos de otros ámbitos | Se revisan en pantalla antes de guardarse. |

## Ejemplo: una operación que pide confirmación

```json
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "tools/call",
  "params": {
    "name": "attendance",
    "arguments": {
      "operation": "schedules_delete",
      "policyId": "cmpolicy0001",
      "scheduleId": "cmschedule0001"
    }
  }
}
```

Sin `confirm: true`, la herramienta no toca nada y responde:

```json
{
  "error": {
    "code": "VALIDATION",
    "message": "Quitar un periodo lo borra si no ha empezado y lo cierra ayer si ya empezó. Pasa confirm:true para confirmarlo.",
    "details": { "field": "confirm", "action": "Repite schedules_delete con confirm:true" },
    "retryable": true,
    "hint": "Repite la llamada con confirm:true cuando la persona lo haya confirmado."
  }
}
```

Repite la llamada con `"confirm": true` cuando la persona lo haya confirmado. Las otras que lo exigen son `overtime_adjustment_create`, `employer_limit`, `carryover_lift_expiry`, `agenda_decline_invitations` y `policy_propagation_apply`.

## Festivos del Calendario y buscar un hueco

Están en el servidor del CRM (`utilia-crm`), con el Calendario en el plan, y los detalla [Calendario: festivos, disponibilidad y buscar un hueco](https://os.utilia.ai/docs/developers/mcp/reference#calendario-festivos-disponibilidad-y-buscar-un-hueco):

- **`calendar_events_workflow`**: `list_holidays` (los festivos de la empresa en un rango, con su procedencia) y `find_free_slots` (las primeras franjas en que todas las personas están libres y dentro de su jornada, sin decir por qué otras no valen).
- **`organization_settings`**: `get_calendar_holidays_scope`, `suggest_calendar_holidays_scope` y `update_calendar_holidays_scope`, la comunidad de los festivos de una empresa sin RRHH. Con RRHH en el plan, la escritura responde `CONFLICT` con `details.errorCode: HOLIDAY_SCOPE_MANAGED_IN_ATTENDANCE`: la comunidad se elige aquí, con `attendance` (`holidays_set_scope`).

La matriz «Mi equipo» del Calendario y el desglose de cada día no tienen operación: usa `get_availability` en `utilia-crm` y, en este servidor, `leave_management` (`team_calendar`).

## Si tu integración llamaba desde el CRM

Hasta el 20 de octubre de 2026, el fichaje y las ausencias también se servían desde `utilia-crm` (`workplace` con las operaciones `attendance_*` y una copia de `leave_management`). Ya solo se autorizan con scopes `hr:*`, que no viajan en una conexión del CRM:

- **Las escrituras** no se ejecutan: responden `errorCode: MOVED_TO_RRHH` con la herramienta y la operación que las sustituyen en `utilia-rrhh`.
- **Las lecturas** siguen respondiendo a las conexiones que ya existían durante 30 días desde el cambio, con el aviso `_notices.deprecatedOperation`, sin el tipo de ninguna ausencia, sin textos libres ni justificantes y con los días sin su detalle. Después también responden `MOVED_TO_RRHH`.

Conecta `utilia-rrhh` y pide sus scopes `hr:*`: las operaciones se llaman igual, sin el prefijo `attendance_` en `attendance`.

## Siguiente paso

La guía de uso de las pantallas que espeja este servidor está en [RRHH](https://os.utilia.ai/docs/guides/hr/time-tracking).

- [Scopes y recursos](https://os.utilia.ai/docs/developers/oauth/scopes-and-resources): Qué scopes puede llevar un token del servidor de RRHH.
- [Conector de RRHH](https://os.utilia.ai/docs/guides/connect-ai/hr): Lo que hace tu asistente en los directorios de Claude y ChatGPT.
