Skip to content
FullCalendar WebMCP
Esc
↑↓navigate↵open⌘Jpreview
On this page

Custom Event Models

Map bookings, sessions, and other domain entities to CalendarEvent, and expose optional read-only metadata to agents.

Most apps store appointments, bookings, or sessions—not a generic CalendarEvent. Your repository is the translation layer.

See Security for metadata exposure guidance.

Map your domain

import type { CalendarEvent, CreateCalendarEventInput } from "@protocoltooling/fullcalendar";

interface Appointment {
  appointmentId: string;
  patientName: string;
  startTime: string;
  endTime: string;
  clinicRoom: string;
}

function toCalendarEvent(app: Appointment): CalendarEvent {
  return {
    id: app.appointmentId,
    title: app.patientName,
    start: app.startTime,
    end: app.endTime,
    allDay: false,
  };
}

function toCreatePayload(input: CreateCalendarEventInput, clinicRoom: string) {
  return {
    patientName: input.title,
    startTime: input.start,
    endTime: input.end ?? input.start,
    clinicRoom,
  };
}

Use those helpers inside list / get / create / update / delete. Capture host context (clinicRoom, userId, tenant ids) in a factory or closure—agents never need those as tool inputs unless you choose to expose them via metadata.

const repository = useMemo(
  () => createAppointmentRepository(clinicRoom, doctorId),
  [clinicRoom, doctorId],
);

useFullCalendarWebMCP({
  calendarRef,
  events: repository,
  onEventsChanged: refetchAppointments,
});

Metadata

Add metadata when agents need context beyond id, title, start, end, and allDay. You choose exactly what is exposed.

Metadata is read-only through FullCalendar WebMCP. Create and update tool schemas reject it.

Protocol Tooling never exposes FullCalendar extendedProps automatically. Project a deliberate subset from your domain model:

function toCalendarEvent(app: Appointment): CalendarEvent {
  return {
    id: app.appointmentId,
    title: app.patientName,
    start: app.startTime,
    end: app.endTime,
    allDay: false,
    metadata: {
      location: app.clinicRoom,
    },
  };
}

Omit anything agents should not see (notes, billing codes, tenant ids). Private fields stay on your domain entity.

See CalendarEvent for the type definition.

Was this page helpful?