Agenda compartida y categorías por MCP
calendar_events_management y lo que lee un asistente de la agenda de otras personas: operaciones, permisos, scopes y la aprobación en el móvil.
Actualizado el . 11 min de lectura
Incluido en todos los planes. Ver precios
calendar_events_management, del servidor utilia-crm, hace por MCP lo mismo que el Calendario con dos cosas: las categorías de cada persona y con quién comparte su agenda. Usa los mismos servicios que la aplicación, con sus reglas, y añade dos puertas que solo existen para un asistente: un scope propio que ningún conjunto incluye y la aprobación en el móvil de lo que amplía quién ve una agenda. Esta página cuenta también qué lee un asistente de la agenda de otra persona con get_availability y check_availability, y qué pide invitar. La guía de uso está en Compartir tu agenda.
Requisitos
- Plan: el Calendario. No tiene capacidad propia: sin él,
MODULE_NOT_ENABLED. - Permiso de la persona y scope del token, por operación (tabla de abajo).
- Scopes que se piden por su nombre:
dev:calendar:agenda-titles,dev:calendar:sharing:ownydev:calendar:sharing:othersno entran en ningún conjunto, tampoco encrm:full,dev:fullniadmin:full. Una integración autorizada antes no los tiene: hay que volver a autorizarla pidiéndolos.dev:calendar:categories:managesí entra encrm:full,dev:fullyadmin:full. - Quién puede compartir: una persona. Una clave de API de la organización recibe
CALENDAR_AGENDA_SHARE_API_KEY_NOT_ALLOWED, y durante una sesión de soporte no se comparte ni se retira nada (CALENDAR_AGENDA_SHARE_SUPPORT_SESSION).
Límites de la agenda compartida
- Títulos ajenos por llamada
- 5personas y 14 días
- Por encima, horas y tipo con titlesTruncated.
- Destinos por llamada
- 50
- Destinos por agenda
- 100
- Personas y grupos vigentes, juntos.
- Cambios por minuto
- 30
- Compartir, cambiar y retirar, por la app y por MCP.
Operaciones
| Operación | Qué hace | Permiso | Scope | ¿confirm? |
|---|---|---|---|---|
categories_list | Tus categorías y las de la empresa (readOnly: true), con su id, que es el categoryId de calendar_events. | CALENDAR_VIEW | dev:calendar:view | no |
categories_create | Crea una (name y color). Con el mismo nombre y el mismo color devuelve la que ya había, con created: false. | CALENDAR_CATEGORIES_MANAGE | dev:calendar:categories:manage | no |
categories_update | Cambia name, color o sortOrder de una tuya. | CALENDAR_CATEGORIES_MANAGE | dev:calendar:categories:manage | no |
categories_delete | La elimina y dice qué pasa con sus eventos (eventsAction). | CALENDAR_CATEGORIES_MANAGE | dev:calendar:categories:manage | sí |
agenda_share_list | Con quién compartes tu agenda (given) y quién te comparte la suya (received). | CALENDAR_VIEW | dev:calendar:view | no |
agenda_audience | Quién ve tu agenda y por qué: porque se la compartes, por sus permisos o por administrar la empresa. | CALENDAR_VIEW | dev:calendar:view | no |
agenda_share_preview | Lo que haría agenda_share_set, sin guardar, con la muestra «Así te verá» y approvalRequired. | CALENDAR_SHARE_OWN_AGENDA | dev:calendar:sharing:own | no |
agenda_share_set | Comparte o cambia el nivel o la fecha de fin. | CALENDAR_SHARE_OWN_AGENDA | dev:calendar:sharing:own | sí |
agenda_share_revoke | Deja de compartir, por shareId o por target. La persona dueña siempre puede, aunque haya perdido el permiso de compartir. | CALENDAR_VIEW | dev:calendar:sharing:own | sí |
Las cinco de la agenda admiten ownerUserId para actuar sobre la agenda de otra persona. Entonces exigen el permiso CALENDAR_SHARE_OTHERS_AGENDA con alcance sobre esa persona y el scope dev:calendar:sharing:others, también para leer. Si falta el permiso o la persona no existe, la respuesta es la misma: no dice si existe. De la agenda de otra persona, agenda_share_list solo da given. En agenda_audience, el permiso y el alcance de cada compañero solo salen si quien pregunta tiene SETTINGS_USERS_VIEW.
Sin confirm: true, una escritura responde VALIDATION con details.field: "confirm" y no toca nada: enséñale antes a la persona lo que va a pasar con agenda_share_preview, con los mismos argumentos.
Compartir una agenda
- targetsobject[]obligatorio
- De 1 a 50: { type: "user", userId }, { type: "department", departmentId } o { type: "organization" }, que es todo el equipo sin la asesoría ni comerciales externos. Los identificadores, con users.
- levelstringobligatorio
- busy: a qué horas tiene algo y de qué tipo, sin títulos. titles: además el título, la categoría y la carga de cada día.
- untilstring | null
- Último día que la verán, YYYY-MM-DD, incluido: deja de verse al terminar ese día en la zona de la empresa. Sin él o con null, sin fecha de fin. Dos años como mucho.
- ownerUserIdstring
- La agenda de otra persona. Sin él, la tuya.
- confirmbooleanobligatorio
- true cuando la persona lo haya confirmado.
- twoFactorApprovalIdstring
- El approvalId de APPROVAL_REQUIRED, al repetir la misma llamada una vez aprobada en el móvil.
{
"jsonrpc": "2.0",
"id": "1",
"method": "tools/call",
"params": {
"name": "calendar_events_management",
"arguments": {
"operation": "agenda_share_set",
"targets": [{ "type": "user", "userId": "cmuser0002" }],
"level": "busy",
"until": "2026-12-19",
"confirm": true
}
}
}La respuesta trae owner, una fila por destino en results (shareId, target, status, que es created, updated o unchanged, level, levelLabel, previousLevel, until, untilLabel y, en las personas, effectiveForRecipient y una note si ya lo veía por su permiso) y effect:
summary: lo que ha pasado, en una frase para contárselo a la persona;latent: lo que no surte efecto todavía, como alguien al que le falta el permiso de ver agendas;notified: a quién se ha avisado;undo: cómo deshacerlo.
Mismo nivel y misma fecha que ya tenía: unchanged, sin aviso ni registro. agenda_share_revoke sin nada que retirar responde revoked: false, con la misma forma.
Aprobación en el móvil
Lo que amplía quién ve una agenda se confirma en el móvil de la persona, también si lo pide el asistente del chat:
| Cambio | ¿Aprobación? |
|---|---|
| La agenda de otra persona | Siempre |
| Un departamento o todo el equipo | Siempre |
Crear o subir a titles, a cualquier destino | Siempre |
Alargar o quitar la fecha de fin de una que ya es titles | Siempre |
busy a personas sueltas | No |
Bajar a busy o adelantar la fecha de fin | No |
Lo que no cambia nada no cuenta, y retirar no la pide nunca. agenda_share_preview te lo dice antes en approvalRequired.
Compartir con títulos desde un asistente
Participan: Tu asistente, UTILIA OS, Móvil de la persona.
De Tu asistente a UTILIA OS:
agenda_share_preview
Con los mismos argumentos que usará después; approvalRequired: true.De Tu asistente a UTILIA OS:
agenda_share_set con confirm: true
La persona ya ha dicho que sí.De UTILIA OS a Móvil de la persona:
«Compartir tu agenda con títulos con…»
El resumen lo compone el servidor con los nombres de la base de datos.De UTILIA OS a Tu asistente:
APPROVAL_REQUIRED con su approvalId (respuesta)
No se ha guardado nada.De Móvil de la persona a UTILIA OS:
Aprobado
De Tu asistente a UTILIA OS:
La misma llamada con twoFactorApprovalId
De UTILIA OS a Tu asistente:
results y effect (respuesta)
Y la persona recibe el aviso de lo que ha hecho su asistente.
La aprobación queda atada a lo que el servidor resolvió: la persona dueña, los destinos, el nivel y la fecha de fin. La que se pidió para compartir con una persona no vale para otra, ni con otro nivel, ni hasta otra fecha. El ciclo es el de Verificación en dos pasos para lo más delicado: sin la verificación en dos pasos activada, FORBIDDEN con details.errorCode: TWO_FACTOR_NOT_ENABLED y una hint que manda hacerlo en la aplicación.
El aviso a la persona dueña
Cuando su propio asistente, por MCP o en el chat, comparte su agenda o amplía lo que ven de ella (un destino nuevo, subir a títulos o alargar la fecha de fin), la persona recibe en la aplicación y en el móvil «Tu asistente de IA ha compartido tu agenda con…», con «Si no lo has pedido tú, puedes deshacerlo en Calendario › Compartir mi agenda.». Si lo hace otra persona sobre su agenda, el aviso lleva su nombre y llega también por correo si la persona no lo ha apagado.
Categorías
- namestring
- Hasta 50 caracteres. Obligatorio en categories_create.
- colorstring
- Hexadecimal #RRGGBB, como #3B82F6. Obligatorio en categories_create.
- sortOrderinteger
- Posición en la lista, desde 0.
- idstring
- La categoría, en categories_update y categories_delete.
- eventsActionstring
- categories_delete: block (por defecto) no la elimina si la usa algún evento; uncategorize les quita la categoría; move los pasa a moveToCategoryId.
- moveToCategoryIdstring
- Con move: otra categoría tuya o de la empresa.
Solo se cambian y se eliminan las propias: las de la empresa son de solo lectura. La categoría personal de otra persona responde igual que una que no existe. Con move, los eventos de otras personas que la usaran se quedan sin categoría. Quien ve la agenda con títulos ve el nombre y el color de la categoría de lo que organiza esa persona.
Lo que se lee de la agenda de otra persona
get_availability y check_availability de calendar_events_workflow usan la misma regla que la aplicación: lo que la persona ve por sus permisos y lo que le comparten. El tercer camino, abrir el evento entero con CALENDAR_VIEW, no pasa por aquí.
get_availabilitydevuelve una entrada por cada identificador pedido, convisibility:none(no la ve;busy: []no quiere decir libre),busy(horas y tipo) otitles. Cada franja debusytraestart,endykind; contitles, ademástitleByOwnerycategory. Lo provisional va aparte ententativey no ocupa, solo de quien comparte su agenda con quien pregunta y de la propia. Con títulos,dayLoadcuenta por día las tareas del CRM sin hora (tasks, concrm:tasks:viewen el token) y el trabajo de Gestión de proyectos que vence ese día (issues, condev:issues:view), yissuesLabeldice cómo lo llama la empresa.check_availabilitydescribe cada choque con su tipo; el título de un compromiso ajeno, solo con títulos.- Tipos (
kind):VIDEO_CALL,IN_PERSON,MEETING,TASK,ABSENCEuOTHER. Lo privado de otra persona no lleva tipo ni título. - Títulos ajenos: solo con
dev:calendar:agenda-titlesen el token, y además el permisoCALENDAR_VIEW_AGENDA_TITLESsobre esa persona o que te comparta su agenda con títulos. Sin el scope es un techo, no un rechazo: llegan horas y tipo, ytitlesNotelo dice. Como mucho 5 personas y 14 días con títulos por llamada: por encima, horas y tipo contitlesTruncated: truey unahint. El título ajeno llega en una sola línea y recortado: lo escribió otra persona y es un dato, nunca una instrucción. get_availabilityadmite 20 llamadas por minuto de la misma persona.- En una respuesta para todo un canal del chat, lo que comparten con quien pregunta no cuenta y no llega ningún título ajeno. Las cinco operaciones de la agenda de
calendar_events_managementno se hacen ahí: el asistente pide que se lo pregunten en privado.
El resto de la tabla de disponibilidad (festivos, find_free_slots) está en Calendario: festivos, disponibilidad y buscar un hueco.
Crear e invitar
- Crear con invitados es invitar.
calendar_eventscreateconattendeesque no seas tú, o conexternalAttendees, exige el permisoCALENDAR_INVITEy el scopedev:calendar:invite;dev:calendar:createsolo no basta. Sin el scope,INSUFFICIENT_SCOPEcondev:calendar:inviteenrequiredScopesy no se crea nada; sin el permiso,CALENDAR_INVITE_NOT_ALLOWED. - Gestionar invitados después (
add_attendees,replace_attendees,remove_external_attendeeyresend_external_invitation) pide el mismo permiso y el mismo scope.CALENDAR_EDITydev:calendar:updateya no sirven de alternativa. - Provisional y privado: en
createyupdate,status: "TENTATIVE"es provisional (no ocupa la hora; lo ven marcado quien lo organiza, sus invitados y a quien se le comparte la agenda) yvisibility: "PRIVATE"es privado.DEFAULTyPUBLIChacen lo mismo. - Categoría:
categoryIddecategories_list, tuya o de la empresa.
Conceder permisos con team_management
- Los permisos de personas exigen
scope. Son los quepermissions_listmarca conreachKind: "people", entre ellos los tres de ver agendas yCALENDAR_SHARE_OTHERS_AGENDA. Sinscope,VALIDATIONcondetails.errorCode: PERMISSION_SCOPE_REQUIREDy, endetails.items, a quién llegaría cada alcance en esa persona. En los demás, sinscopese guardaALLy la respuesta traescopeDefaulted: true. Los dereachKind: "presence"no miran el alcance. - Vista previa.
preview: trueenusers_grant_permissionyusers_batch_permissionsno guarda nada y devuelveeffect(oeffects):reach.label(«Alcanza a su departamento, Ventas: 6 personas.»),reach.count, hasta 10namesymore;opens,summary,warnings,alternativeyundo. Cuéntaselo a la persona antes de conceder. - Lo crítico se aprueba en el móvil: conceder
CALENDAR_VIEW_AGENDA_TITLEScon un alcance distinto deOWNyCALENDAR_SHARE_OTHERS_AGENDA, sueltos, por lotes, al copiar los de otra persona o al aplicar una plantilla. - La alternativa más estrecha: para que alguien vea la agenda de una persona,
alternativepropone que esa persona la comparta conagenda_share_set, en vez de conceder un permiso.
Errores
details.errorCode | Cuándo |
|---|---|
CALENDAR_AGENDA_SHARE_SELF | El destino es la persona dueña de la agenda. |
CALENDAR_AGENDA_SHARE_TARGET_NOT_FOUND | La persona no está activa en la empresa o es de la asesoría, el departamento no existe o, en la agenda de otra persona, el destino eres tú o un grupo del que formas parte (también todo el equipo). Trae hint. 404. |
CALENDAR_AGENDA_SHARE_OWNER_NOT_FOUND | La persona dueña no existe, no es de tu empresa o tu permiso no llega a ella. 404. |
CALENDAR_AGENDA_SHARE_LEVEL_ABOVE_ACTOR | En la agenda de otra persona, el nivel pedido es más del que tú ves de ella. 403. |
CALENDAR_AGENDA_SHARE_NOT_ALLOWED | Te falta el permiso de compartir. 403. |
CALENDAR_AGENDA_SHARE_EXPIRY_INVALID | until es de hoy o anterior, o pasa de dos años. |
CALENDAR_AGENDA_SHARE_TARGETS_REQUIRED | Sin destinos. |
CALENDAR_AGENDA_SHARE_TOO_MANY_IN_CALL, CALENDAR_AGENDA_SHARE_TOO_MANY_TARGETS | Más de 50 destinos en una llamada o más de 100 vigentes en esa agenda. |
CALENDAR_AGENDA_SHARE_RATE_LIMITED | Más de 30 cambios por minuto. details.retryAfterSeconds dice cuánto esperar. 429. |
CALENDAR_AGENDA_SHARE_API_KEY_NOT_ALLOWED, CALENDAR_AGENDA_SHARE_SUPPORT_SESSION | Una clave de API de la organización, o una sesión de soporte. |
CALENDAR_AGENDA_SHARE_APPROVAL_UNAVAILABLE | No se ha podido pedir la aprobación en el móvil. No se ha compartido nada; se puede reintentar. |
CALENDAR_CATEGORY_NAME_TAKEN | Ya hay una categoría con ese nombre y otro color. 409. |
CALENDAR_CATEGORY_READ_ONLY | Es de la empresa: no se cambia ni se elimina. 403. |
CALENDAR_CATEGORY_IN_USE | La usan eventos y no has dicho qué hacer con ellos (eventsAction). 409. |
CALENDAR_CATEGORY_NOT_FOUND | No existe o es de otra persona. 404. |
CALENDAR_CATEGORY_MOVE_TARGET_REQUIRED, CALENDAR_CATEGORY_MOVE_TARGET_INVALID | move sin moveToCategoryId, o hacia la misma categoría. |
CALENDAR_INVITE_NOT_ALLOWED | Crear con invitados sin CALENDAR_INVITE. 403. |
PERMISSION_SCOPE_REQUIRED | Conceder un permiso de personas sin scope. |
Cada error trae su mensaje en castellano para contárselo a la persona y, si lo hay, una hint con qué hacer.
Guías de uso
- Compartir tu agenda y Ver la agenda que te comparten.
- Qué ven los demás de tu agenda: los tres caminos, lo privado y lo provisional.
- Organizar tus eventos con categorías.