Next.js
Use FullCalendar WebMCP with Next.js App Router client components, server actions, and SSR-safe registration of calendar tools.
Use the hook in a Client Component. The package entry includes 'use client'. Module load does not touch window or document, so SSR stays safe. Your repository can call Server Actions or Route Handlers.
This guide uses FullCalendar React v6 import paths (@fullcalendar/daygrid). For v7, import plugins from @fullcalendar/react/daygrid and type the ref as CalendarRef.
App Router
"use client";
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import { useCallback, useRef, useState } from "react";
import {
useFullCalendarWebMCP,
type CalendarEvent,
type CalendarEventRepository,
} from "@protocoltooling/fullcalendar";
import {
fetchEventsAction,
createEventAction,
updateEventAction,
deleteEventAction,
} from "./actions";
export function CalendarClient({
initialEvents,
}: {
initialEvents: CalendarEvent[];
}) {
const calendarRef = useRef<FullCalendar>(null);
const [events, setEvents] = useState<CalendarEvent[]>(initialEvents);
const repository: CalendarEventRepository = {
list: (query) => fetchEventsAction(query),
get: async (id) => {
const all = await fetchEventsAction();
return all.find((event) => event.id === id) ?? null;
},
create: (input) => createEventAction(input),
update: (id, input) => updateEventAction(id, input),
delete: (id) => deleteEventAction(id),
};
const refreshEvents = useCallback(async () => {
setEvents(await fetchEventsAction());
}, []);
useFullCalendarWebMCP({
calendarRef,
events: repository,
onEventsChanged: refreshEvents,
});
return (
<FullCalendar
ref={calendarRef}
plugins={[dayGridPlugin]}
initialView="dayGridMonth"
events={events.map((event) => ({
...event,
end: event.end ?? undefined,
}))}
/>
);
}
Server page:
import { CalendarClient } from "./calendar-client";
import { fetchEventsAction } from "./actions";
export default async function CalendarPage() {
const events = await fetchEventsAction();
return <CalendarClient initialEvents={events} />;
}
For the shared golden path, see Quickstart.