@protocoltooling/fullcalendar 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Add WebMCP calendar tools to an existing FullCalendar React app.
4
4
 
5
- Created by Roberto Nevarez. FullCalendar WebMCP exposes structured browser tools without replacing your calendar UI, backend, database, or application state.
5
+ FullCalendar WebMCP exposes structured browser tools without replacing your calendar UI, backend, database, or application state.
6
6
 
7
7
  [Live demo](https://protocoltooling.com/demo) · [Documentation](https://protocoltooling.com/integrations/fullcalendar) · [WebMCP Challenge notes](./CHALLENGE.md)
8
8
 
package/dist/index.js CHANGED
@@ -12,17 +12,17 @@ var emptySchema = {
12
12
  var stableEventIdProperty = {
13
13
  type: "string",
14
14
  minLength: 1,
15
- description: "Stable id of the persisted event. Obtain from calendar_list_events, calendar_get_event, or a prior create/update result. Never substitute an event title."
15
+ description: "Stable id from calendar_list_events, prior tool results, or host. Never substitute title for id."
16
16
  };
17
17
  var queryStartProperty = {
18
18
  type: "string",
19
19
  format: "date-time",
20
- description: "Inclusive lower bound for filtering persisted events (ISO 8601 date-time with explicit offset). Omit to include events from any earlier time."
20
+ description: "Inclusive filter lower bound (ISO 8601 with offset). Omit for no lower limit."
21
21
  };
22
22
  var queryEndProperty = {
23
23
  type: "string",
24
24
  format: "date-time",
25
- description: "Exclusive upper bound for filtering persisted events (ISO 8601 date-time with explicit offset). For one calendar day, set end to the start of the following day. Omit for no upper limit."
25
+ description: "Exclusive filter upper bound (ISO 8601 with offset). One day: following day start. Omit for no limit."
26
26
  };
27
27
  var queryTextProperty = {
28
28
  type: "string",
@@ -41,7 +41,7 @@ var updateEventTitleProperty = {
41
41
  var createEventStartProperty = {
42
42
  type: "string",
43
43
  format: "date-time",
44
- description: "Inclusive event start as ISO 8601 date-time with an explicit offset (e.g. 2026-09-02T14:00:00-06:00). Resolve relative times with calendar_get_context first."
44
+ description: "Inclusive event start (ISO 8601 with offset). Resolve relative times via calendar_get_context first."
45
45
  };
46
46
  var updateEventStartProperty = {
47
47
  type: "string",
@@ -75,7 +75,10 @@ var eventWriteAnnotations = {
75
75
  readOnlyHint: false,
76
76
  untrustedContentHint: true
77
77
  };
78
- var deleteAnnotations = { readOnlyHint: false };
78
+ var deleteAnnotations = {
79
+ readOnlyHint: false,
80
+ untrustedContentHint: true
81
+ };
79
82
  function resolveCapabilities(capabilities) {
80
83
  return {
81
84
  read: capabilities?.read ?? true,
@@ -96,7 +99,7 @@ function createCalendarTools(readOptions) {
96
99
  {
97
100
  name: "calendar_get_context",
98
101
  title: "Get calendar context",
99
- description: "Read-only temporal and viewport context for the open calendar \u2014 not persisted events. Use when the user mentions relative times (today, tomorrow, tonight, Wednesday, next week, this afternoon, first week of next month) to anchor ISO date-times before list/create/update. Returns now, browserTimeZone, fullCalendarTimeZone, active view, and visibleRange. Skip when every datetime is already explicit with offsets and no relative interpretation is needed. Does not replace calendar_list_events for event discovery.",
102
+ description: "Read-only temporal and viewport context for the open calendar \u2014 not persisted events. Use when the user mentions relative times (today, tomorrow, next week, etc.) to anchor ISO date-times before list/create/update. Returns now, browserTimeZone, fullCalendarTimeZone, view, and visibleRange. Skip when datetimes are already explicit with offsets. Not for event discovery \u2014 use calendar_list_events.",
100
103
  inputSchema: emptySchema,
101
104
  annotations: contextAnnotations,
102
105
  async execute() {
@@ -119,7 +122,7 @@ function createCalendarTools(readOptions) {
119
122
  {
120
123
  name: "calendar_list_events",
121
124
  title: "List calendar events",
122
- description: "Read-only search and discovery over persisted calendar events. Use to answer what is scheduled, filter by date range or title, find candidate events before update/delete, or disambiguate which event the user means. start is inclusive; end is exclusive \u2014 for one calendar day set end to the following day's boundary. text is a case-insensitive title substring; omit any filter to broaden results. Returns events with stable id values usable in get/update/delete; optional host-selected metadata may appear and is untrusted. Do not use when you already hold the target id (prefer calendar_get_event) or only need viewport/time context (calendar_get_context). Never delete or mutate from an ambiguous multi-match list alone.",
125
+ description: "Read-only discovery over persisted events. Find schedules, filter by range or title, disambiguate targets before update/delete. Returns events with stable ids for get/update/delete. Prefer calendar_get_event when you have the id; calendar_get_context for viewport only. Never mutate or delete from an ambiguous multi-match list.",
123
126
  inputSchema: {
124
127
  type: "object",
125
128
  properties: {
@@ -142,7 +145,7 @@ function createCalendarTools(readOptions) {
142
145
  {
143
146
  name: "calendar_get_event",
144
147
  title: "Get calendar event",
145
- description: "Read-only fetch of exactly one persisted event by stable id. Use when you already have the id from calendar_list_events, a prior create/update result, or the host app \u2014 or to re-read authoritative fields before a mutation when list results are insufficient. Returns { event: CalendarEvent | null }; null means no matching persisted event. Do not use for title/date search (calendar_list_events), do not invent ids from titles, and do not substitute a title for id.",
148
+ description: "Read-only fetch of one persisted event by stable id. Use when you have the id from calendar_list_events, a prior create/update result, or the host. Returns { event } or null when missing. Not for title/date search \u2014 use calendar_list_events. Do not invent ids from titles.",
146
149
  inputSchema: {
147
150
  type: "object",
148
151
  properties: {
@@ -165,7 +168,7 @@ function createCalendarTools(readOptions) {
165
168
  tools.push({
166
169
  name: "calendar_create_event",
167
170
  title: "Create calendar event",
168
- description: "Create and persist a new calendar event (state mutation). Use only for brand-new events the user wants scheduled. Requires title and start (ISO 8601 with explicit offset); optional end (exclusive, ISO 8601 or null) and allDay. Resolve relative times via calendar_get_context first. Returns the persisted event including host-assigned id. Metadata cannot be supplied. Do not use to modify, reschedule, or rename an existing event \u2014 use calendar_update_event.",
171
+ description: "Create and persist a new event. Requires title and start (ISO 8601 with offset); optional end and allDay. Resolve relative times via calendar_get_context first. Returns persisted event with host-assigned id. Metadata cannot be supplied. Not for modifying existing events \u2014 use calendar_update_event.",
169
172
  inputSchema: {
170
173
  type: "object",
171
174
  properties: {
@@ -192,7 +195,7 @@ function createCalendarTools(readOptions) {
192
195
  tools.push({
193
196
  name: "calendar_update_event",
194
197
  title: "Update calendar event",
195
- description: "Persisted partial update of exactly one existing event (state mutation). Requires stable id plus at least one of title, start, end, allDay; omitted fields stay unchanged. Host-selected metadata is preserved and cannot be written here. When the user names an event without an id, find it with calendar_list_events first; calendar_get_event is optional if the list row already has sufficient detail. Use for reschedule, rename, time/end changes, or all-day toggles \u2014 not for creating a duplicate or deleting (calendar_create_event / calendar_delete_event).",
198
+ description: "Partial update of one existing event by stable id. Requires id plus at least one of title, start, end, allDay; omitted fields unchanged. Host metadata preserved, not writable. Without id, find via calendar_list_events first. For reschedule/rename/time changes \u2014 not create (calendar_create_event) or delete (calendar_delete_event).",
196
199
  inputSchema: {
197
200
  type: "object",
198
201
  properties: {
@@ -221,7 +224,7 @@ function createCalendarTools(readOptions) {
221
224
  tools.push({
222
225
  name: "calendar_delete_event",
223
226
  title: "Delete calendar event",
224
- description: "Permanently delete exactly one persisted calendar event (destructive state mutation). Requires stable id \u2014 obtain via calendar_list_events after disambiguating natural-language references; never pass a title as id and never delete from an ambiguous multi-match list. Use only when the user intends removal/cancellation, not to move, rename, shorten, or otherwise edit (calendar_update_event). Returns { deleted: true, event } where event is the deleted resource snapshot read immediately before removal.",
227
+ description: "Permanently delete one persisted event by stable id. Obtain id via calendar_list_events after disambiguation; never use title as id or delete from ambiguous lists. For removal only \u2014 not edit/reschedule (calendar_update_event). Returns { deleted: true, event } pre-delete snapshot.",
225
228
  inputSchema: {
226
229
  type: "object",
227
230
  properties: {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tool-definitions.ts","../src/register-tools.ts","../src/use-fullcalendar-webmcp.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/// <reference types=\"webmcp-types\" />\n\nimport type {\n CalendarEvent,\n CreateCalendarEventInput,\n FullCalendarWebMCPCapabilities,\n FullCalendarWebMCPOptions,\n UpdateCalendarEventInput,\n} from \"./types\";\n\ntype OptionsReader = () => FullCalendarWebMCPOptions;\n\nconst emptySchema = {\n type: \"object\",\n properties: {},\n additionalProperties: false,\n} as const;\n\nconst stableEventIdProperty = {\n type: \"string\",\n minLength: 1,\n description:\n \"Stable id of the persisted event. Obtain from calendar_list_events, calendar_get_event, or a prior create/update result. Never substitute an event title.\",\n} as const;\n\nconst queryStartProperty = {\n type: \"string\",\n format: \"date-time\",\n description:\n \"Inclusive lower bound for filtering persisted events (ISO 8601 date-time with explicit offset). Omit to include events from any earlier time.\",\n} as const;\n\nconst queryEndProperty = {\n type: \"string\",\n format: \"date-time\",\n description:\n \"Exclusive upper bound for filtering persisted events (ISO 8601 date-time with explicit offset). For one calendar day, set end to the start of the following day. Omit for no upper limit.\",\n} as const;\n\nconst queryTextProperty = {\n type: \"string\",\n description:\n \"Case-insensitive substring matched against event titles. Omit to skip title filtering.\",\n} as const;\n\nconst createEventTitleProperty = {\n type: \"string\",\n minLength: 1,\n description: \"Display title for the new event.\",\n} as const;\n\nconst updateEventTitleProperty = {\n type: \"string\",\n minLength: 1,\n description: \"New display title. Omit to leave the current title unchanged.\",\n} as const;\n\nconst createEventStartProperty = {\n type: \"string\",\n format: \"date-time\",\n description:\n \"Inclusive event start as ISO 8601 date-time with an explicit offset (e.g. 2026-09-02T14:00:00-06:00). Resolve relative times with calendar_get_context first.\",\n} as const;\n\nconst updateEventStartProperty = {\n type: \"string\",\n format: \"date-time\",\n description:\n \"New inclusive event start (ISO 8601 with explicit offset). Omit to leave the current start unchanged.\",\n} as const;\n\nconst createEventEndProperty = {\n type: [\"string\", \"null\"],\n format: \"date-time\",\n description:\n \"Exclusive event end as ISO 8601 date-time with explicit offset, or null for open-ended. Omit on create to use host defaults.\",\n} as const;\n\nconst updateEventEndProperty = {\n type: [\"string\", \"null\"],\n format: \"date-time\",\n description:\n \"New exclusive event end (ISO 8601 with explicit offset) or null. Omit to leave the current end unchanged.\",\n} as const;\n\nconst createAllDayProperty = {\n type: \"boolean\",\n description:\n \"Whether the event spans full calendar days without clock times. Defaults to false when omitted.\",\n} as const;\n\nconst updateAllDayProperty = {\n type: \"boolean\",\n description: \"Whether the event is all-day. Omit to leave unchanged.\",\n} as const;\n\n/** Library-generated viewport/time context — not user-authored event content. */\nconst contextAnnotations: WebMCP.ToolAnnotations = { readOnlyHint: true };\n\n/** Persisted event reads may include user-controlled titles and host metadata. */\nconst eventReadAnnotations: WebMCP.ToolAnnotations = {\n readOnlyHint: true,\n untrustedContentHint: true,\n};\n\n/** Mutations that return persisted event records with user-controlled fields. */\nconst eventWriteAnnotations: WebMCP.ToolAnnotations = {\n readOnlyHint: false,\n untrustedContentHint: true,\n};\n\n/** Destructive mutation with a minimal structured confirmation payload. */\nconst deleteAnnotations: WebMCP.ToolAnnotations = { readOnlyHint: false };\n\nexport function resolveCapabilities(\n capabilities?: FullCalendarWebMCPCapabilities,\n): Required<FullCalendarWebMCPCapabilities> {\n return {\n read: capabilities?.read ?? true,\n create: capabilities?.create ?? true,\n update: capabilities?.update ?? true,\n delete: capabilities?.delete ?? true,\n };\n}\n\n/**\n * WebMCP imperative execute steps always pass ToolExecuteCallbackOptions with a\n * fresh AbortSignal. Some agent shims still call execute(input) with one argument.\n * Never require-destructure options; forward signal when present.\n */\nfunction executionSignal(\n executeOptions: WebMCP.ToolExecuteCallbackOptions | undefined,\n): AbortSignal | undefined {\n return executeOptions?.signal;\n}\n\n/** JSON-clone so delete snapshots cannot mutate repository-owned objects. */\nfunction cloneEvent(event: CalendarEvent): CalendarEvent {\n return JSON.parse(JSON.stringify(event)) as CalendarEvent;\n}\n\nexport function createCalendarTools(\n readOptions: OptionsReader,\n): WebMCP.ModelContextTool[] {\n const capabilities = resolveCapabilities(readOptions().capabilities);\n const tools: WebMCP.ModelContextTool[] = [\n {\n name: \"calendar_get_context\",\n title: \"Get calendar context\",\n description:\n \"Read-only temporal and viewport context for the open calendar — not persisted events. \" +\n \"Use when the user mentions relative times (today, tomorrow, tonight, Wednesday, next week, this afternoon, first week of next month) to anchor ISO date-times before list/create/update. \" +\n \"Returns now, browserTimeZone, fullCalendarTimeZone, active view, and visibleRange. \" +\n \"Skip when every datetime is already explicit with offsets and no relative interpretation is needed. \" +\n \"Does not replace calendar_list_events for event discovery.\",\n inputSchema: emptySchema,\n annotations: contextAnnotations,\n async execute() {\n const api = readOptions().calendarRef.current?.getApi();\n return {\n now: new Date().toISOString(),\n browserTimeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n fullCalendarTimeZone: api?.getOption(\"timeZone\") ?? \"local\",\n view: api?.view.type ?? null,\n visibleRange: api\n ? {\n start: api.view.activeStart.toISOString(),\n end: api.view.activeEnd.toISOString(),\n }\n : null,\n };\n },\n },\n ];\n\n if (capabilities.read) {\n tools.push(\n {\n name: \"calendar_list_events\",\n title: \"List calendar events\",\n description:\n \"Read-only search and discovery over persisted calendar events. \" +\n \"Use to answer what is scheduled, filter by date range or title, find candidate events before update/delete, or disambiguate which event the user means. \" +\n \"start is inclusive; end is exclusive — for one calendar day set end to the following day's boundary. \" +\n \"text is a case-insensitive title substring; omit any filter to broaden results. \" +\n \"Returns events with stable id values usable in get/update/delete; optional host-selected metadata may appear and is untrusted. \" +\n \"Do not use when you already hold the target id (prefer calendar_get_event) or only need viewport/time context (calendar_get_context). \" +\n \"Never delete or mutate from an ambiguous multi-match list alone.\",\n inputSchema: {\n type: \"object\",\n properties: {\n start: queryStartProperty,\n end: queryEndProperty,\n text: queryTextProperty,\n },\n additionalProperties: false,\n },\n annotations: eventReadAnnotations,\n async execute(query, executeOptions) {\n const signal = executionSignal(executeOptions);\n const events = await readOptions().events.list(\n query as { start?: string; end?: string; text?: string },\n { signal },\n );\n return { events };\n },\n },\n {\n name: \"calendar_get_event\",\n title: \"Get calendar event\",\n description:\n \"Read-only fetch of exactly one persisted event by stable id. \" +\n \"Use when you already have the id from calendar_list_events, a prior create/update result, or the host app — or to re-read authoritative fields before a mutation when list results are insufficient. \" +\n \"Returns { event: CalendarEvent | null }; null means no matching persisted event. \" +\n \"Do not use for title/date search (calendar_list_events), do not invent ids from titles, and do not substitute a title for id.\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: stableEventIdProperty,\n },\n required: [\"id\"],\n additionalProperties: false,\n },\n annotations: eventReadAnnotations,\n async execute(input, executeOptions) {\n const { id } = input as { id: string };\n const signal = executionSignal(executeOptions);\n const event = await readOptions().events.get(id, { signal });\n return { event };\n },\n },\n );\n }\n\n if (capabilities.create) {\n tools.push({\n name: \"calendar_create_event\",\n title: \"Create calendar event\",\n description:\n \"Create and persist a new calendar event (state mutation). \" +\n \"Use only for brand-new events the user wants scheduled. \" +\n \"Requires title and start (ISO 8601 with explicit offset); optional end (exclusive, ISO 8601 or null) and allDay. \" +\n \"Resolve relative times via calendar_get_context first. \" +\n \"Returns the persisted event including host-assigned id. Metadata cannot be supplied. \" +\n \"Do not use to modify, reschedule, or rename an existing event — use calendar_update_event.\",\n inputSchema: {\n type: \"object\",\n properties: {\n title: createEventTitleProperty,\n start: createEventStartProperty,\n end: createEventEndProperty,\n allDay: createAllDayProperty,\n },\n required: [\"title\", \"start\"],\n additionalProperties: false,\n },\n annotations: eventWriteAnnotations,\n async execute(rawInput, executeOptions) {\n const input = rawInput as unknown as CreateCalendarEventInput;\n const signal = executionSignal(executeOptions);\n const options = readOptions();\n const event = await options.events.create(input, { signal });\n await options.onEventsChanged();\n return { event };\n },\n });\n }\n\n if (capabilities.update) {\n tools.push({\n name: \"calendar_update_event\",\n title: \"Update calendar event\",\n description:\n \"Persisted partial update of exactly one existing event (state mutation). \" +\n \"Requires stable id plus at least one of title, start, end, allDay; omitted fields stay unchanged. \" +\n \"Host-selected metadata is preserved and cannot be written here. \" +\n \"When the user names an event without an id, find it with calendar_list_events first; calendar_get_event is optional if the list row already has sufficient detail. \" +\n \"Use for reschedule, rename, time/end changes, or all-day toggles — not for creating a duplicate or deleting (calendar_create_event / calendar_delete_event).\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: stableEventIdProperty,\n title: updateEventTitleProperty,\n start: updateEventStartProperty,\n end: updateEventEndProperty,\n allDay: updateAllDayProperty,\n },\n required: [\"id\"],\n minProperties: 2,\n additionalProperties: false,\n },\n annotations: eventWriteAnnotations,\n async execute(rawInput, executeOptions) {\n const { id, ...input } = rawInput as unknown as UpdateCalendarEventInput & {\n id: string;\n };\n const signal = executionSignal(executeOptions);\n const options = readOptions();\n const event = await options.events.update(id, input, { signal });\n await options.onEventsChanged();\n return { event };\n },\n });\n }\n\n if (capabilities.delete) {\n tools.push({\n name: \"calendar_delete_event\",\n title: \"Delete calendar event\",\n description:\n \"Permanently delete exactly one persisted calendar event (destructive state mutation). \" +\n \"Requires stable id — obtain via calendar_list_events after disambiguating natural-language references; never pass a title as id and never delete from an ambiguous multi-match list. \" +\n \"Use only when the user intends removal/cancellation, not to move, rename, shorten, or otherwise edit (calendar_update_event). \" +\n \"Returns { deleted: true, event } where event is the deleted resource snapshot read immediately before removal.\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: stableEventIdProperty,\n },\n required: [\"id\"],\n additionalProperties: false,\n },\n annotations: deleteAnnotations,\n async execute(input, executeOptions) {\n const { id } = input as { id: string };\n const signal = executionSignal(executeOptions);\n const options = readOptions();\n const existing = await options.events.get(id, { signal });\n if (existing === null) {\n throw new Error(`Event ${id} was not found.`);\n }\n const snapshot = cloneEvent(existing);\n await options.events.delete(id, { signal });\n await options.onEventsChanged();\n return { deleted: true, event: snapshot };\n },\n });\n }\n\n return tools;\n}\n","import { createCalendarTools } from \"./tool-definitions\";\nimport type { FullCalendarWebMCPOptions } from \"./types\";\n\nconst RUNTIME_POLL_INTERVAL_MS = 250;\n\nexport function registerCalendarToolsWhenAvailable(\n readOptions: () => FullCalendarWebMCPOptions,\n lifecycleSignal: AbortSignal,\n) {\n let retryTimer: number | undefined;\n\n const register = async () => {\n if (lifecycleSignal.aborted) return;\n\n const modelContext = document.modelContext;\n if (!modelContext) {\n retryTimer = window.setTimeout(register, RUNTIME_POLL_INTERVAL_MS);\n return;\n }\n\n const registration = new AbortController();\n const unregister = () => registration.abort(lifecycleSignal.reason);\n lifecycleSignal.addEventListener(\"abort\", unregister, { once: true });\n\n try {\n await Promise.all(\n createCalendarTools(readOptions).map((tool) =>\n modelContext.registerTool(tool, { signal: registration.signal }),\n ),\n );\n } catch (error) {\n registration.abort();\n if (!lifecycleSignal.aborted) {\n readOptions().onRegistrationError?.(error);\n }\n }\n };\n\n void register();\n\n lifecycleSignal.addEventListener(\n \"abort\",\n () => {\n if (retryTimer !== undefined) window.clearTimeout(retryTimer);\n },\n { once: true },\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport { registerCalendarToolsWhenAvailable } from \"./register-tools\";\nimport type { FullCalendarWebMCPOptions } from \"./types\";\n\n/**\n * Primary React hook integrating FullCalendar with the browser WebMCP model context.\n *\n * Provides safe client-side registration, unmount cleanup, and continuous\n * binding to host persistence callbacks without re-registering tools across renders.\n */\nexport function useFullCalendarWebMCP(options: FullCalendarWebMCPOptions): void {\n const latestOptions = useRef(options);\n latestOptions.current = options;\n\n useEffect(() => {\n const lifecycle = new AbortController();\n registerCalendarToolsWhenAvailable(\n () => latestOptions.current,\n lifecycle.signal,\n );\n return () => lifecycle.abort();\n }, []);\n}\n"]}
1
+ {"version":3,"sources":["../src/tool-definitions.ts","../src/register-tools.ts","../src/use-fullcalendar-webmcp.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/// <reference types=\"webmcp-types\" />\n\nimport type {\n CalendarEvent,\n CreateCalendarEventInput,\n FullCalendarWebMCPCapabilities,\n FullCalendarWebMCPOptions,\n UpdateCalendarEventInput,\n} from \"./types\";\n\ntype OptionsReader = () => FullCalendarWebMCPOptions;\n\nconst emptySchema = {\n type: \"object\",\n properties: {},\n additionalProperties: false,\n} as const;\n\nconst stableEventIdProperty = {\n type: \"string\",\n minLength: 1,\n description:\n \"Stable id from calendar_list_events, prior tool results, or host. Never substitute title for id.\",\n} as const;\n\nconst queryStartProperty = {\n type: \"string\",\n format: \"date-time\",\n description:\n \"Inclusive filter lower bound (ISO 8601 with offset). Omit for no lower limit.\",\n} as const;\n\nconst queryEndProperty = {\n type: \"string\",\n format: \"date-time\",\n description:\n \"Exclusive filter upper bound (ISO 8601 with offset). One day: following day start. Omit for no limit.\",\n} as const;\n\nconst queryTextProperty = {\n type: \"string\",\n description:\n \"Case-insensitive substring matched against event titles. Omit to skip title filtering.\",\n} as const;\n\nconst createEventTitleProperty = {\n type: \"string\",\n minLength: 1,\n description: \"Display title for the new event.\",\n} as const;\n\nconst updateEventTitleProperty = {\n type: \"string\",\n minLength: 1,\n description: \"New display title. Omit to leave the current title unchanged.\",\n} as const;\n\nconst createEventStartProperty = {\n type: \"string\",\n format: \"date-time\",\n description:\n \"Inclusive event start (ISO 8601 with offset). Resolve relative times via calendar_get_context first.\",\n} as const;\n\nconst updateEventStartProperty = {\n type: \"string\",\n format: \"date-time\",\n description:\n \"New inclusive event start (ISO 8601 with explicit offset). Omit to leave the current start unchanged.\",\n} as const;\n\nconst createEventEndProperty = {\n type: [\"string\", \"null\"],\n format: \"date-time\",\n description:\n \"Exclusive event end as ISO 8601 date-time with explicit offset, or null for open-ended. Omit on create to use host defaults.\",\n} as const;\n\nconst updateEventEndProperty = {\n type: [\"string\", \"null\"],\n format: \"date-time\",\n description:\n \"New exclusive event end (ISO 8601 with explicit offset) or null. Omit to leave the current end unchanged.\",\n} as const;\n\nconst createAllDayProperty = {\n type: \"boolean\",\n description:\n \"Whether the event spans full calendar days without clock times. Defaults to false when omitted.\",\n} as const;\n\nconst updateAllDayProperty = {\n type: \"boolean\",\n description: \"Whether the event is all-day. Omit to leave unchanged.\",\n} as const;\n\n/** Library-generated viewport/time context — not user-authored event content. */\nconst contextAnnotations: WebMCP.ToolAnnotations = { readOnlyHint: true };\n\n/** Persisted event reads may include user-controlled titles and host metadata. */\nconst eventReadAnnotations: WebMCP.ToolAnnotations = {\n readOnlyHint: true,\n untrustedContentHint: true,\n};\n\n/** Mutations that return persisted event records with user-controlled fields. */\nconst eventWriteAnnotations: WebMCP.ToolAnnotations = {\n readOnlyHint: false,\n untrustedContentHint: true,\n};\n\n/** Delete returns a pre-removal snapshot with user-controlled fields. */\nconst deleteAnnotations: WebMCP.ToolAnnotations = {\n readOnlyHint: false,\n untrustedContentHint: true,\n};\n\nexport function resolveCapabilities(\n capabilities?: FullCalendarWebMCPCapabilities,\n): Required<FullCalendarWebMCPCapabilities> {\n return {\n read: capabilities?.read ?? true,\n create: capabilities?.create ?? true,\n update: capabilities?.update ?? true,\n delete: capabilities?.delete ?? true,\n };\n}\n\n/**\n * WebMCP imperative execute steps always pass ToolExecuteCallbackOptions with a\n * fresh AbortSignal. Some agent shims still call execute(input) with one argument.\n * Never require-destructure options; forward signal when present.\n */\nfunction executionSignal(\n executeOptions: WebMCP.ToolExecuteCallbackOptions | undefined,\n): AbortSignal | undefined {\n return executeOptions?.signal;\n}\n\n/** JSON-clone so delete snapshots cannot mutate repository-owned objects. */\nfunction cloneEvent(event: CalendarEvent): CalendarEvent {\n return JSON.parse(JSON.stringify(event)) as CalendarEvent;\n}\n\nexport function createCalendarTools(\n readOptions: OptionsReader,\n): WebMCP.ModelContextTool[] {\n const capabilities = resolveCapabilities(readOptions().capabilities);\n const tools: WebMCP.ModelContextTool[] = [\n {\n name: \"calendar_get_context\",\n title: \"Get calendar context\",\n description:\n \"Read-only temporal and viewport context for the open calendar — not persisted events. \" +\n \"Use when the user mentions relative times (today, tomorrow, next week, etc.) to anchor ISO date-times before list/create/update. \" +\n \"Returns now, browserTimeZone, fullCalendarTimeZone, view, and visibleRange. \" +\n \"Skip when datetimes are already explicit with offsets. Not for event discovery — use calendar_list_events.\",\n inputSchema: emptySchema,\n annotations: contextAnnotations,\n async execute() {\n const api = readOptions().calendarRef.current?.getApi();\n return {\n now: new Date().toISOString(),\n browserTimeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n fullCalendarTimeZone: api?.getOption(\"timeZone\") ?? \"local\",\n view: api?.view.type ?? null,\n visibleRange: api\n ? {\n start: api.view.activeStart.toISOString(),\n end: api.view.activeEnd.toISOString(),\n }\n : null,\n };\n },\n },\n ];\n\n if (capabilities.read) {\n tools.push(\n {\n name: \"calendar_list_events\",\n title: \"List calendar events\",\n description:\n \"Read-only discovery over persisted events. Find schedules, filter by range or title, disambiguate targets before update/delete. \" +\n \"Returns events with stable ids for get/update/delete. Prefer calendar_get_event when you have the id; calendar_get_context for viewport only. \" +\n \"Never mutate or delete from an ambiguous multi-match list.\",\n inputSchema: {\n type: \"object\",\n properties: {\n start: queryStartProperty,\n end: queryEndProperty,\n text: queryTextProperty,\n },\n additionalProperties: false,\n },\n annotations: eventReadAnnotations,\n async execute(query, executeOptions) {\n const signal = executionSignal(executeOptions);\n const events = await readOptions().events.list(\n query as { start?: string; end?: string; text?: string },\n { signal },\n );\n return { events };\n },\n },\n {\n name: \"calendar_get_event\",\n title: \"Get calendar event\",\n description:\n \"Read-only fetch of one persisted event by stable id. \" +\n \"Use when you have the id from calendar_list_events, a prior create/update result, or the host. \" +\n \"Returns { event } or null when missing. Not for title/date search — use calendar_list_events. Do not invent ids from titles.\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: stableEventIdProperty,\n },\n required: [\"id\"],\n additionalProperties: false,\n },\n annotations: eventReadAnnotations,\n async execute(input, executeOptions) {\n const { id } = input as { id: string };\n const signal = executionSignal(executeOptions);\n const event = await readOptions().events.get(id, { signal });\n return { event };\n },\n },\n );\n }\n\n if (capabilities.create) {\n tools.push({\n name: \"calendar_create_event\",\n title: \"Create calendar event\",\n description:\n \"Create and persist a new event. Requires title and start (ISO 8601 with offset); optional end and allDay. \" +\n \"Resolve relative times via calendar_get_context first. Returns persisted event with host-assigned id. Metadata cannot be supplied. \" +\n \"Not for modifying existing events — use calendar_update_event.\",\n inputSchema: {\n type: \"object\",\n properties: {\n title: createEventTitleProperty,\n start: createEventStartProperty,\n end: createEventEndProperty,\n allDay: createAllDayProperty,\n },\n required: [\"title\", \"start\"],\n additionalProperties: false,\n },\n annotations: eventWriteAnnotations,\n async execute(rawInput, executeOptions) {\n const input = rawInput as unknown as CreateCalendarEventInput;\n const signal = executionSignal(executeOptions);\n const options = readOptions();\n const event = await options.events.create(input, { signal });\n await options.onEventsChanged();\n return { event };\n },\n });\n }\n\n if (capabilities.update) {\n tools.push({\n name: \"calendar_update_event\",\n title: \"Update calendar event\",\n description:\n \"Partial update of one existing event by stable id. Requires id plus at least one of title, start, end, allDay; omitted fields unchanged. \" +\n \"Host metadata preserved, not writable. Without id, find via calendar_list_events first. \" +\n \"For reschedule/rename/time changes — not create (calendar_create_event) or delete (calendar_delete_event).\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: stableEventIdProperty,\n title: updateEventTitleProperty,\n start: updateEventStartProperty,\n end: updateEventEndProperty,\n allDay: updateAllDayProperty,\n },\n required: [\"id\"],\n minProperties: 2,\n additionalProperties: false,\n },\n annotations: eventWriteAnnotations,\n async execute(rawInput, executeOptions) {\n const { id, ...input } = rawInput as unknown as UpdateCalendarEventInput & {\n id: string;\n };\n const signal = executionSignal(executeOptions);\n const options = readOptions();\n const event = await options.events.update(id, input, { signal });\n await options.onEventsChanged();\n return { event };\n },\n });\n }\n\n if (capabilities.delete) {\n tools.push({\n name: \"calendar_delete_event\",\n title: \"Delete calendar event\",\n description:\n \"Permanently delete one persisted event by stable id. Obtain id via calendar_list_events after disambiguation; never use title as id or delete from ambiguous lists. \" +\n \"For removal only — not edit/reschedule (calendar_update_event). Returns { deleted: true, event } pre-delete snapshot.\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: stableEventIdProperty,\n },\n required: [\"id\"],\n additionalProperties: false,\n },\n annotations: deleteAnnotations,\n async execute(input, executeOptions) {\n const { id } = input as { id: string };\n const signal = executionSignal(executeOptions);\n const options = readOptions();\n const existing = await options.events.get(id, { signal });\n if (existing === null) {\n throw new Error(`Event ${id} was not found.`);\n }\n const snapshot = cloneEvent(existing);\n await options.events.delete(id, { signal });\n await options.onEventsChanged();\n return { deleted: true, event: snapshot };\n },\n });\n }\n\n return tools;\n}\n","import { createCalendarTools } from \"./tool-definitions\";\nimport type { FullCalendarWebMCPOptions } from \"./types\";\n\nconst RUNTIME_POLL_INTERVAL_MS = 250;\n\nexport function registerCalendarToolsWhenAvailable(\n readOptions: () => FullCalendarWebMCPOptions,\n lifecycleSignal: AbortSignal,\n) {\n let retryTimer: number | undefined;\n\n const register = async () => {\n if (lifecycleSignal.aborted) return;\n\n const modelContext = document.modelContext;\n if (!modelContext) {\n retryTimer = window.setTimeout(register, RUNTIME_POLL_INTERVAL_MS);\n return;\n }\n\n const registration = new AbortController();\n const unregister = () => registration.abort(lifecycleSignal.reason);\n lifecycleSignal.addEventListener(\"abort\", unregister, { once: true });\n\n try {\n await Promise.all(\n createCalendarTools(readOptions).map((tool) =>\n modelContext.registerTool(tool, { signal: registration.signal }),\n ),\n );\n } catch (error) {\n registration.abort();\n if (!lifecycleSignal.aborted) {\n readOptions().onRegistrationError?.(error);\n }\n }\n };\n\n void register();\n\n lifecycleSignal.addEventListener(\n \"abort\",\n () => {\n if (retryTimer !== undefined) window.clearTimeout(retryTimer);\n },\n { once: true },\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport { registerCalendarToolsWhenAvailable } from \"./register-tools\";\nimport type { FullCalendarWebMCPOptions } from \"./types\";\n\n/**\n * Primary React hook integrating FullCalendar with the browser WebMCP model context.\n *\n * Provides safe client-side registration, unmount cleanup, and continuous\n * binding to host persistence callbacks without re-registering tools across renders.\n */\nexport function useFullCalendarWebMCP(options: FullCalendarWebMCPOptions): void {\n const latestOptions = useRef(options);\n latestOptions.current = options;\n\n useEffect(() => {\n const lifecycle = new AbortController();\n registerCalendarToolsWhenAvailable(\n () => latestOptions.current,\n lifecycle.signal,\n );\n return () => lifecycle.abort();\n }, []);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protocoltooling/fullcalendar",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Add WebMCP tools to FullCalendar React applications.",
5
5
  "author": "Roberto Nevarez",
6
6
  "publishConfig": {