MewCP Cal.com MCP
Servidor MCP de Cal.com alojado, sin estado y multiinquilino que permite a los asistentes de IA gestionar programación, reservas y disponibilidad de calendario a través de Cal.com.
Documentación
Programación de calendario, reservas y disponibilidad para agentes de IA
Un servidor de Protocolo de Contexto de Modelo (MCP) que expone la API v2 de Cal.com para gestionar tipos de eventos, reservas, horarios, disponibilidad y membresía de organizaciones.
Resumen
El servidor MewCP Cal MCP proporciona acceso programático a una cuenta de programación de Cal.com:
- Leer y crear tipos de eventos, e inspeccionar el perfil del usuario autenticado
- Crear, recuperar, reprogramar, confirmar, cancelar y marcar reservas como ausentes
- Gestionar horarios de disponibilidad y consultar franjas horarias abiertas y horas ocupadas
- Listar membresías de organizaciones y formularios de enrutamiento
Perfecto para:
- Automatizar flujos de trabajo de reserva y reprogramación de reuniones
- Crear asistentes de programación que muestren franjas abiertas y horas ocupadas
- Gestionar recursos de programación de equipos y organizaciones de forma programática
Herramientas
Perfil
get_my_profile — Obtener el perfil del usuario autenticado de Cal.com
Obtener el perfil del usuario autenticado de Cal.com
Entradas:
No inputs.
Esquema de salida data:
{
id?: number | null;
username?: string | null;
email?: string | null;
name?: string | null;
timeZone?: string | null;
weekStart?: string | null;
locale?: string | null;
timeFormat?: number | null;
defaultScheduleId?: number | null;
organizationId?: number | null;
organization?: object | null;
avatarUrl?: string | null;
bio?: string | null;
// additional upstream fields may be present
}
Tipos de eventos
get_event_types — Listar todos los tipos de eventos para el usuario
Listar todos los tipos de eventos para el usuario
Entradas:
No inputs.
Esquema de salida data:
{
count: number;
event_types: {
id?: number | null;
title?: string | null;
slug?: string | null;
lengthInMinutes?: number | null;
length?: number | null;
description?: string | null;
hidden?: boolean | null;
ownerId?: number | null;
// additional upstream fields may be present
}[];
// additional upstream fields may be present
}
get_event_type — Obtener un tipo de evento específico por ID
Obtener un tipo de evento específico por ID
Entradas:
- `event_type_id` (integer, required) — The event type ID: the numeric Cal.com identifier of the event type to retrieve, as an integer (e.g. 123456). Required — the call fails with a validation error if omitted.
Esquema de salida data:
{
id?: number | null;
title?: string | null;
slug?: string | null;
lengthInMinutes?: number | null;
length?: number | null;
description?: string | null;
hidden?: boolean | null;
ownerId?: number | null;
// additional upstream fields may be present
}
create_event_type — Crear un nuevo tipo de evento
Crear un nuevo tipo de evento
Entradas:
- `title` (string, required) — Title of the event type: the display name for the new event type, as a plain non-empty string (e.g. '30 Minute Meeting'). Required — the call fails with a validation error if omitted or blank.
Esquema de salida data:
{
id?: number | null;
title?: string | null;
slug?: string | null;
lengthInMinutes?: number | null;
length?: number | null;
description?: string | null;
hidden?: boolean | null;
ownerId?: number | null;
// additional upstream fields may be present
}
Reservas
get_bookings — Obtener todas las reservas del usuario
Obtener todas las reservas del usuario
Entradas:
No inputs.
Esquema de salida data:
{
count: number;
bookings: {
id?: number | null;
uid?: string | null;
title?: string | null;
description?: string | null;
status?: string | null;
start?: string | null;
end?: string | null;
duration?: number | null;
eventTypeId?: number | null;
meetingUrl?: string | null;
location?: string | null;
absentHost?: boolean | null;
cancellationReason?: string | null;
rescheduledFromUid?: string | null;
rescheduledToUid?: string | null;
attendees?: {
name?: string | null;
email?: string | null;
timeZone?: string | null;
phoneNumber?: string | null;
language?: string | null;
absent?: boolean | null;
}[] | null;
hosts?: object[] | null;
// additional upstream fields may be present
}[];
// additional upstream fields may be present
}
get_booking — Obtener una reserva específica por ID
Obtener una reserva específica por ID
Entradas:
- `booking_id` (string, required) — The booking ID to retrieve, as a plain string (e.g. '12345'). Required.
Esquema de salida data:
{
id?: number | null;
uid?: string | null;
title?: string | null;
description?: string | null;
status?: string | null;
start?: string | null;
end?: string | null;
duration?: number | null;
eventTypeId?: number | null;
meetingUrl?: string | null;
location?: string | null;
absentHost?: boolean | null;
cancellationReason?: string | null;
rescheduledFromUid?: string | null;
rescheduledToUid?: string | null;
attendees?: {
name?: string | null;
email?: string | null;
timeZone?: string | null;
phoneNumber?: string | null;
language?: string | null;
absent?: boolean | null;
}[] | null;
hosts?: object[] | null;
// additional upstream fields may be present
}
create_booking — Crear una nueva reserva
Crear una nueva reserva
Entradas:
- `event_type_id` (integer, required) — Event type ID to book, as an integer (e.g. 42). Required.
- `start` (string, required) — Booking start datetime in ISO 8601 / RFC 3339 UTC format (e.g. '2024-08-13T09:00:00Z'). Required.
- `attendee_name` (string, required) — Attendee full name as a plain string (e.g. 'Ada Lovelace'). Required.
- `attendee_email` (string, required) — Attendee email address as a plain string (e.g. 'ada@example.com'). Required.
Esquema de salida data:
{
id?: number | null;
uid?: string | null;
title?: string | null;
description?: string | null;
status?: string | null;
start?: string | null;
end?: string | null;
duration?: number | null;
eventTypeId?: number | null;
meetingUrl?: string | null;
location?: string | null;
absentHost?: boolean | null;
cancellationReason?: string | null;
rescheduledFromUid?: string | null;
rescheduledToUid?: string | null;
attendees?: {
name?: string | null;
email?: string | null;
timeZone?: string | null;
phoneNumber?: string | null;
language?: string | null;
absent?: boolean | null;
}[] | null;
hosts?: object[] | null;
// additional upstream fields may be present
}
cancel_booking — Cancelar una reserva (DESTRUCTIVO, requiere confirmación explícita del usuario)
DESTRUCTIVO — REQUIERE CONFIRMACIÓN EXPLÍCITA DEL USUARIO ANTES DE LLAMAR. Cancelar una reserva. Cancela permanentemente la reserva identificada por booking_id, liberando su franja horaria y notificando al anfitrión y a cada asistente. Esta acción es irreversible: la reserva cancelada y su franja confirmada no se pueden recuperar. NUNCA llame a esta herramienta de forma autónoma o como parte de un flujo automatizado. DEBE detenerse, decirle al usuario exactamente qué reserva se cancelará y que es permanente, y esperar su confirmación escrita explícita antes de continuar. La respuesta incluye el estado de la reserva antes de la cancelación.
Entradas:
- `booking_id` (string, required) — The booking ID to cancel, as a plain string (e.g. '12345'). Required.
Esquema de salida data:
{
before?: {
id?: number | null;
uid?: string | null;
title?: string | null;
description?: string | null;
status?: string | null;
start?: string | null;
end?: string | null;
duration?: number | null;
eventTypeId?: number | null;
meetingUrl?: string | null;
location?: string | null;
absentHost?: boolean | null;
cancellationReason?: string | null;
rescheduledFromUid?: string | null;
rescheduledToUid?: string | null;
attendees?: {
name?: string | null;
email?: string | null;
timeZone?: string | null;
phoneNumber?: string | null;
language?: string | null;
absent?: boolean | null;
}[] | null;
hosts?: object[] | null;
} | null;
after?: { /* same shape as `before` */ } | null;
// additional upstream fields may be present
}
reschedule_booking — Reprogramar una reserva existente
Reprogramar una reserva existente. Solo se cambian los campos que proporcione; los demás conservan su valor actual. NOTA: esto sobrescribe las horas de inicio y fin actuales; el estado original no se almacena después de la llamada. La respuesta incluye tanto el estado anterior como el posterior para que tenga un registro completo de lo que cambió.
Entradas:
- `booking_id` (string, required) — The booking ID to reschedule, as a plain string (e.g. '12345'). Required.
- `start` (string, required) — New start time in ISO 8601 / RFC 3339 UTC format (e.g. '2024-08-13T09:00:00Z'). Required.
- `end` (string, required) — New end time in ISO 8601 / RFC 3339 UTC format (e.g. '2024-08-13T09:30:00Z'). Required.
Esquema de salida data:
{
before?: {
id?: number | null;
uid?: string | null;
title?: string | null;
description?: string | null;
status?: string | null;
start?: string | null;
end?: string | null;
duration?: number | null;
eventTypeId?: number | null;
meetingUrl?: string | null;
location?: string | null;
absentHost?: boolean | null;
cancellationReason?: string | null;
rescheduledFromUid?: string | null;
rescheduledToUid?: string | null;
attendees?: {
name?: string | null;
email?: string | null;
timeZone?: string | null;
phoneNumber?: string | null;
language?: string | null;
absent?: boolean | null;
}[] | null;
hosts?: object[] | null;
} | null;
after?: { /* same shape as `before` */ } | null;
// additional upstream fields may be present
}
confirm_booking — Confirmar una reserva pendiente
Confirmar una reserva pendiente. Solo se cambian los campos que proporcione; los demás conservan su valor actual. NOTA: esto sobrescribe el estado actual de la reserva; el estado original no se almacena después de la llamada. La respuesta incluye tanto el estado anterior como el posterior para que tenga un registro completo de lo que cambió.
Entradas:
- `booking_id` (string, required) — ID of the pending booking to confirm, as a plain string (e.g. '12345'). Required.
Esquema de salida data:
{
before?: {
id?: number | null;
uid?: string | null;
title?: string | null;
description?: string | null;
status?: string | null;
start?: string | null;
end?: string | null;
duration?: number | null;
eventTypeId?: number | null;
meetingUrl?: string | null;
location?: string | null;
absentHost?: boolean | null;
cancellationReason?: string | null;
rescheduledFromUid?: string | null;
rescheduledToUid?: string | null;
attendees?: {
name?: string | null;
email?: string | null;
timeZone?: string | null;
phoneNumber?: string | null;
language?: string | null;
absent?: boolean | null;
}[] | null;
hosts?: object[] | null;
} | null;
after?: { /* same shape as `before` */ } | null;
// additional upstream fields may be present
}
mark_booking_absent — Marcar una reserva como ausente
Marcar una reserva como ausente. Solo se cambian los campos que proporcione; los demás conservan su valor actual. NOTA: esto sobrescribe el estado de asistencia actual de la reserva; el estado original no se almacena después de la llamada. La respuesta incluye tanto el estado anterior como el posterior para que tenga un registro completo de lo que cambió.
Entradas:
- `booking_id` (string, required) — ID of the booking to mark as absent, as a plain string (e.g. '12345'). Required.
Esquema de salida data:
{
before?: {
id?: number | null;
uid?: string | null;
title?: string | null;
description?: string | null;
status?: string | null;
start?: string | null;
end?: string | null;
duration?: number | null;
eventTypeId?: number | null;
meetingUrl?: string | null;
location?: string | null;
absentHost?: boolean | null;
cancellationReason?: string | null;
rescheduledFromUid?: string | null;
rescheduledToUid?: string | null;
attendees?: {
name?: string | null;
email?: string | null;
timeZone?: string | null;
phoneNumber?: string | null;
language?: string | null;
absent?: boolean | null;
}[] | null;
hosts?: object[] | null;
} | null;
after?: { /* same shape as `before` */ } | null;
// additional upstream fields may be present
}
Horarios
get_schedules — Obtener todos los horarios del usuario
Obtener todos los horarios del usuario
Entradas:
No inputs.
Esquema de salida data:
{
count: number;
schedules: {
id?: number | null;
ownerId?: number | null;
name?: string | null;
timeZone?: string | null;
isDefault?: boolean | null;
availability?: {
days?: string[] | null;
startTime?: string | null;
endTime?: string | null;
}[] | null;
overrides?: object[] | null;
// additional upstream fields may be present
}[];
// additional upstream fields may be present
}
get_schedule — Obtener un horario específico por ID
Obtener un horario específico por ID
Entradas:
- `schedule_id` (string, required) — The schedule ID identifying the schedule to retrieve. Plain string containing the Cal.com numeric schedule identifier (for example "12345"). Required — the call fails with a validation error if omitted or blank.
Esquema de salida data:
{
id?: number | null;
ownerId?: number | null;
name?: string | null;
timeZone?: string | null;
isDefault?: boolean | null;
availability?: {
days?: string[] | null;
startTime?: string | null;
endTime?: string | null;
}[] | null;
overrides?: object[] | null;
// additional upstream fields may be present
}
get_default_schedule — Obtener el horario predeterminado
Obtener el horario predeterminado
Entradas:
No inputs.
Esquema de salida data:
{
id?: number | null;
ownerId?: number | null;
name?: string | null;
timeZone?: string | null;
isDefault?: boolean | null;
availability?: {
days?: string[] | null;
startTime?: string | null;
endTime?: string | null;
}[] | null;
overrides?: object[] | null;
// additional upstream fields may be present
}
create_schedule — Crear un nuevo horario
Crear un nuevo horario
Entradas:
- `name` (string, required) — Name of the schedule to create, as shown in Cal.com. Plain free-text string (for example "Working Hours"). Required — the call fails with a validation error if omitted or blank.
Esquema de salida data:
{
id?: number | null;
ownerId?: number | null;
name?: string | null;
timeZone?: string | null;
isDefault?: boolean | null;
availability?: {
days?: string[] | null;
startTime?: string | null;
endTime?: string | null;
}[] | null;
overrides?: object[] | null;
// additional upstream fields may be present
}
Disponibilidad
get_availability — Obtener franjas horarias disponibles
Obtener franjas horarias disponibles
Entradas:
- `date` (string, required) — Calendar day to look up available slots for, as a plain string in YYYY-MM-DD format (ISO 8601 calendar date). Required — there is no default, and the call fails with VALIDATION_ERROR if it is omitted or not in YYYY-MM-DD format.
Esquema de salida data:
{
date?: string | null;
timeZone?: string | null;
count: number;
slots: {
start?: string | null;
end?: string | null;
time?: string | null;
attendees?: number | null;
bookingUid?: string | null;
// additional upstream fields may be present
}[];
// additional upstream fields may be present
}
get_busy_times — Obtener horas ocupadas de los calendarios
Obtener horas ocupadas de los calendarios
Entradas:
No inputs.
Esquema de salida data:
{
count: number;
busy_times: {
start?: string | null;
end?: string | null;
source?: string | null;
title?: string | null;
// additional upstream fields may be present
}[];
// additional upstream fields may be present
}
Organizaciones
get_org_memberships — Obtener membresías de organizaciones
Obtener membresías de organizaciones
Entradas:
No inputs.
Esquema de salida data:
{
count: number;
memberships: {
id?: number | null;
userId?: number | null;
teamId?: number | null;
organizationId?: number | null;
role?: string | null;
accepted?: boolean | null;
disableImpersonation?: boolean | null;
user?: {
id?: number | null;
email?: string | null;
username?: string | null;
name?: string | null;
} | null;
// additional upstream fields may be present
}[];
// additional upstream fields may be present
}
get_org_routing_forms — Obtener formularios de enrutamiento de organizaciones
Obtener formularios de enrutamiento de organizaciones
Entradas:
No inputs.
Esquema de salida data:
{
count: number;
routing_forms: {
id?: string | null;
name?: string | null;
description?: string | null;
disabled?: boolean | null;
position?: number | null;
userId?: number | null;
teamId?: number | null;
routes?: any;
fields?: any;
createdAt?: string | null;
updatedAt?: string | null;
// additional upstream fields may be present
}[];
// additional upstream fields may be present
}
Referencia de parámetros de la API
Sobre de respuesta
Cada herramienta devuelve el mismo sobre de nivel superior. Solo data varía según la herramienta.
// Success
{
"success": true,
"statusCode": 200,
"retriable": false,
"retry_after_seconds": null,
"error": null,
"data": { ... }
}
// Error
{
"success": false,
"statusCode": 400,
"retriable": false,
"retry_after_seconds": null,
"error": { "code": "VALIDATION_ERROR", "message": "description", "details": {} },
"data": null
}
retriable—truecuando es seguro reintentar (límite de velocidad, error de red, 503).falsepara errores de validación y autenticación.retry_after_seconds— segundos a esperar antes de reintentar; presente solo cuandoretriableestruey el upstream especifica un retraso.error.code— cadena legible por máquina:VALIDATION_ERROR,AUTH_ERROR,UPSTREAM_ERROR,SERVER_ERROR.
Autenticación
Este servidor utiliza autenticación estática de clave API. Agregue su clave API de Cal.com a su cuenta de MewCP como el campo de credencial api_key. El servidor la envía upstream a la API v2 de Cal.com como:
Authorization: Bearer <api_key>
cal-api-version: 2024-06-11
Formatos de recursos
ID de reserva:
Plain string
Example: 12345
ID de tipo de evento:
Integer
Example: 123456
Fecha y hora:
ISO 8601 / RFC 3339 UTC
Example: 2024-08-13T09:00:00Z
Fecha de calendario:
YYYY-MM-DD (ISO 8601 calendar date)
Example: 2024-08-13
Obtención de su clave API de Cal.com
Pasos
- Vaya a Configuración de Cal.com → Desarrollador → Claves API
- Abra la sección Claves API de su configuración de desarrollador
- Haga clic en Agregar (o Crear) para generar una nueva clave API
- Copie la clave generada: solo la verá una vez
Solución de problemas
Encabezados faltantes o no válidos
- Causa: clave API no proporcionada en los encabezados de la solicitud o formato incorrecto
- Solución:
- Verifique que los encabezados
Authorization: Bearer YOUR_API_KEYyX-Mewcp-Credential-Id: CREDENTIAL-IDestén presentes - Compruebe que la clave API esté activa en su cuenta de MewCP
- Verifique que los encabezados
Créditos insuficientes
- Causa: las llamadas a la API han superado sus límites de solicitud
- Solución:
- Consulte el uso de créditos en su panel de Curious Layer
- Actualice a un plan de pago o agregue créditos para límites más altos
- Contacte al soporte para ajustes de crédito
Credencial no conectada
- Causa: no hay ninguna credencial de Cal.com vinculada a su cuenta
- Solución:
- Vaya a Credenciales en su panel de MewCP
- Agregue su clave API de Cal.com (estática) en el campo de credencial
api_key - Reintente la solicitud con el encabezado
X-Mewcp-Credential-Idcorrecto
Carga útil de solicitud malformada
- Causa: la carga útil JSON no es válida o faltan campos obligatorios
- Solución:
- Valide la sintaxis JSON antes de enviar
- Asegúrese de que todos los parámetros de herramienta obligatorios estén incluidos
- Compruebe que los tipos de parámetros coincidan con los valores esperados
Servidor no encontrado
- Causa: nombre de servidor incorrecto en el endpoint de la API
- Solución:
- Verifique el formato del endpoint:
{server-name}/mcp/{tool-name} - Use el nombre de servidor correcto de la documentación
- Compruebe los servidores disponibles en su cuenta de Curious Layer
- Verifique el formato del endpoint:
Error de la API de Cal.com
- Causa: la API de Cal.com upstream devolvió un error
- Solución:
- Consulte el estado del servicio de Cal.com en Página de estado de Cal.com
- Verifique que su credencial tenga los permisos necesarios
- Revise el mensaje de error para obtener detalles específicos
Recursos
- Documentación de la API de Cal.com — Referencia oficial de la API
- Referencia de la API de Cal.com — Referencia completa de endpoints
- Documentación de FastMCP — Especificación de FastMCP
- Credenciales de FastMCP — Paquete de Credenciales de FastMCP para el manejo de credenciales