MewCP Cal.com MCP

Servidor MCP Cal.com hospedado, sem estado e multilocatário permite que assistentes de IA gerenciem agendamentos, reservas e disponibilidade de calendário através do Cal.com.

Documentação

Agendamento de calendário, reservas e disponibilidade para agentes de IA

Um servidor Model Context Protocol (MCP) que expõe a API v2 do Cal.com para gerenciar tipos de eventos, reservas, agendas, disponibilidade e associações de organização.

Visão Geral

O MewCP Cal MCP Server fornece acesso programático a uma conta de agendamento do Cal.com:

  • Ler e criar tipos de eventos, e inspecionar o perfil do usuário autenticado
  • Criar, recuperar, reagendar, confirmar, cancelar e marcar reservas como ausentes
  • Gerenciar agendas de disponibilidade e consultar horários livres e períodos ocupados
  • Listar associações de organização e formulários de roteamento

Perfeito para:

  • Automatizar fluxos de trabalho de agendamento e reagendamento de reuniões
  • Construir assistentes de agendamento que exibem horários livres e períodos ocupados
  • Gerenciar recursos de agendamento de equipes e organizações programaticamente

Ferramentas

Perfil

get_my_profile — Obter o perfil do usuário autenticado do Cal.com

Obter o perfil do usuário autenticado do Cal.com

Entradas:

No inputs.

Esquema de saída 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 os tipos de eventos do usuário

Listar todos os tipos de eventos do usuário

Entradas:

No inputs.

Esquema de saída 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 — Obter um tipo de evento específico por ID

Obter um 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 saída 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 — Criar um novo tipo de evento

Criar um novo 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 saída 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 — Obter todas as reservas do usuário

Obter todas as reservas do usuário

Entradas:

No inputs.

Esquema de saída 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 — Obter uma reserva específica por ID

Obter uma 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 saída 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 — Criar uma nova reserva

Criar uma nova 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 saída 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 uma reserva (DESTRUTIVO, requer confirmação explícita do usuário)

DESTRUTIVO — REQUER CONFIRMAÇÃO EXPLÍCITA DO USUÁRIO ANTES DE CHAMAR. Cancelar uma reserva. Cancela permanentemente a reserva identificada por booking_id, liberando seu horário e notificando o anfitrião e todos os participantes. Esta ação é irreversível — a reserva cancelada e seu horário confirmado não podem ser recuperados. NUNCA chame esta ferramenta de forma autônoma ou como parte de um fluxo automatizado. Você DEVE parar, informar ao usuário exatamente qual reserva será cancelada e que isso é permanente, e aguardar a confirmação escrita explícita antes de prosseguir. A resposta inclui o estado da reserva antes do cancelamento.

Entradas:

- `booking_id` (string, required) — The booking ID to cancel, as a plain string (e.g. '12345'). Required.

Esquema de saída 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 — Reagendar uma reserva existente

Reagendar uma reserva existente. Apenas os campos que você fornecer são alterados — os demais mantêm seu valor atual. OBSERVAÇÃO: isso sobrescreve os horários de início e término atuais — o estado original não é armazenado após a chamada. A resposta inclui tanto o estado anterior quanto o posterior, para que você tenha um registro completo do que mudou.

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 saída 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 uma reserva pendente

Confirmar uma reserva pendente. Apenas os campos que você fornecer são alterados — os demais mantêm seu valor atual. OBSERVAÇÃO: isso sobrescreve o status atual da reserva — o estado original não é armazenado após a chamada. A resposta inclui tanto o estado anterior quanto o posterior, para que você tenha um registro completo do que mudou.

Entradas:

- `booking_id` (string, required) — ID of the pending booking to confirm, as a plain string (e.g. '12345'). Required.

Esquema de saída 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 uma reserva como ausente

Marcar uma reserva como ausente. Apenas os campos que você fornecer são alterados — os demais mantêm seu valor atual. OBSERVAÇÃO: isso sobrescreve o estado atual de comparecimento da reserva — o estado original não é armazenado após a chamada. A resposta inclui tanto o estado anterior quanto o posterior, para que você tenha um registro completo do que mudou.

Entradas:

- `booking_id` (string, required) — ID of the booking to mark as absent, as a plain string (e.g. '12345'). Required.

Esquema de saída 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
}

Agendas

get_schedules — Obter todas as agendas do usuário

Obter todas as agendas do usuário

Entradas:

No inputs.

Esquema de saída 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 — Obter uma agenda específica por ID

Obter uma agenda específica 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 saída 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 — Obter a agenda padrão

Obter a agenda padrão

Entradas:

No inputs.

Esquema de saída 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 — Criar uma nova agenda

Criar uma nova agenda

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 saída 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
}

Disponibilidade

get_availability — Obter horários disponíveis

Obter horários disponíveis

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 saída 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 — Obter períodos ocupados dos calendários

Obter períodos ocupados dos calendários

Entradas:

No inputs.

Esquema de saída 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
}

Organizações

get_org_memberships — Obter associações de organização

Obter associações de organização

Entradas:

No inputs.

Esquema de saída 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 — Obter formulários de roteamento da organização

Obter formulários de roteamento da organização

Entradas:

No inputs.

Esquema de saída 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
}

Referência de Parâmetros da API

Envelope de Resposta

Toda ferramenta retorna o mesmo envelope de nível superior. Apenas data varia por ferramenta.

// 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 — true quando é seguro tentar novamente (limite de taxa, erro de rede, 503). false para erros de validação e autenticação.
  • retry_after_seconds — segundos para aguardar antes de tentar novamente; presente apenas quando retriable é true e o serviço upstream especifica um atraso.
  • error.code — string legível por máquina: VALIDATION_ERROR, AUTH_ERROR, UPSTREAM_ERROR, SERVER_ERROR.
Autenticação

Este servidor usa autenticação estática por chave de API. Adicione sua chave de API do Cal.com à sua conta MewCP como o campo de credencial api_key. O servidor a envia upstream para a API v2 do Cal.com como:

Authorization: Bearer <api_key>
cal-api-version: 2024-06-11
Formatos de Recursos

ID da reserva:

Plain string
Example: 12345

ID do tipo de evento:

Integer
Example: 123456

Data e hora:

ISO 8601 / RFC 3339 UTC
Example: 2024-08-13T09:00:00Z

Data do calendário:

YYYY-MM-DD (ISO 8601 calendar date)
Example: 2024-08-13

Obtendo Sua Chave de API do Cal.com

Etapas
  1. Acesse Configurações do Cal.com → Desenvolvedor → Chaves de API
  2. Abra a seção Chaves de API nas suas configurações de desenvolvedor
  3. Clique em Adicionar (ou Criar) para gerar uma nova chave de API
  4. Copie a chave gerada — você só a verá uma vez

Solução de Problemas

Cabeçalhos Ausentes ou Inválidos
  • Causa: Chave de API não fornecida nos cabeçalhos da solicitação ou formato incorreto
  • Solução:
    1. Verifique se os cabeçalhos Authorization: Bearer YOUR_API_KEY e X-Mewcp-Credential-Id: CREDENTIAL-ID estão presentes
    2. Confirme se a chave de API está ativa na sua conta MewCP
Créditos Insuficientes
  • Causa: As chamadas de API excederam seus limites de solicitação
  • Solução:
    1. Verifique o uso de créditos no seu painel do Curious Layer
    2. Faça upgrade para um plano pago ou adicione créditos para limites maiores
    3. Entre em contato com o suporte para ajustes de créditos
Credencial Não Conectada
  • Causa: Nenhuma credencial do Cal.com vinculada à sua conta
  • Solução:
    1. Acesse Credenciais no seu painel do MewCP
    2. Adicione sua chave de API do Cal.com (estática) no campo de credencial api_key
    3. Tente novamente a solicitação com o cabeçalho X-Mewcp-Credential-Id correto
Payload de Solicitação Malformado
  • Causa: O payload JSON é inválido ou está faltando campos obrigatórios
  • Solução:
    1. Valide a sintaxe JSON antes de enviar
    2. Garanta que todos os parâmetros obrigatórios da ferramenta estejam incluídos
    3. Verifique se os tipos dos parâmetros correspondem aos valores esperados
Servidor Não Encontrado
  • Causa: Nome incorreto do servidor no endpoint da API
  • Solução:
    1. Verifique o formato do endpoint: {server-name}/mcp/{tool-name}
    2. Use o nome correto do servidor conforme a documentação
    3. Verifique os servidores disponíveis na sua conta do Curious Layer
Erro da API do Cal.com
  • Causa: A API upstream do Cal.com retornou um erro
  • Solução:
    1. Verifique o status do serviço do Cal.com na Página de Status do Cal.com
    2. Confirme se sua credencial tem as permissões necessárias
    3. Revise a mensagem de erro para obter detalhes específicos

Recursos