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
}
  • retriabletrue cuando es seguro reintentar (límite de velocidad, error de red, 503). false para errores de validación y autenticación.
  • retry_after_seconds — segundos a esperar antes de reintentar; presente solo cuando retriable es true y 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
  1. Vaya a Configuración de Cal.com → Desarrollador → Claves API
  2. Abra la sección Claves API de su configuración de desarrollador
  3. Haga clic en Agregar (o Crear) para generar una nueva clave API
  4. 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:
    1. Verifique que los encabezados Authorization: Bearer YOUR_API_KEY y X-Mewcp-Credential-Id: CREDENTIAL-ID estén presentes
    2. Compruebe que la clave API esté activa en su cuenta de MewCP
Créditos insuficientes
  • Causa: las llamadas a la API han superado sus límites de solicitud
  • Solución:
    1. Consulte el uso de créditos en su panel de Curious Layer
    2. Actualice a un plan de pago o agregue créditos para límites más altos
    3. 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:
    1. Vaya a Credenciales en su panel de MewCP
    2. Agregue su clave API de Cal.com (estática) en el campo de credencial api_key
    3. Reintente la solicitud con el encabezado X-Mewcp-Credential-Id correcto
Carga útil de solicitud malformada
  • Causa: la carga útil JSON no es válida o faltan campos obligatorios
  • Solución:
    1. Valide la sintaxis JSON antes de enviar
    2. Asegúrese de que todos los parámetros de herramienta obligatorios estén incluidos
    3. 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:
    1. Verifique el formato del endpoint: {server-name}/mcp/{tool-name}
    2. Use el nombre de servidor correcto de la documentación
    3. Compruebe los servidores disponibles en su cuenta de Curious Layer
Error de la API de Cal.com
  • Causa: la API de Cal.com upstream devolvió un error
  • Solución:
    1. Consulte el estado del servicio de Cal.com en Página de estado de Cal.com
    2. Verifique que su credencial tenga los permisos necesarios
    3. Revise el mensaje de error para obtener detalles específicos

Recursos