From 5ed8cc801a4d2ddb544f595cd304b9401188bfa0 Mon Sep 17 00:00:00 2001 From: seisyo58 <33082636+seisyo58@users.noreply.github.com> Date: Fri, 8 May 2026 13:09:31 +0900 Subject: [PATCH 1/2] feat: support event checklists (#1) --- src/tools/event-crud-tools.ts | 42 +++++++++++++++++++++++++++++++++++ src/tools/event-tools.ts | 2 ++ src/types/timetree.ts | 28 ++++++++++++++++++++--- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/tools/event-crud-tools.ts b/src/tools/event-crud-tools.ts index 1cdda63..a152d1c 100644 --- a/src/tools/event-crud-tools.ts +++ b/src/tools/event-crud-tools.ts @@ -26,6 +26,10 @@ export const CreateEventInputSchema = z.object({ note: z.string().optional().describe('Event notes/description'), location: z.string().optional().describe('Event location'), url: z.string().optional().describe('Related URL'), + checklist: z.array(z.object({ + checked: z.boolean().default(false).describe('Whether the checklist item is checked'), + title: z.string().min(1).describe('Checklist item title'), + })).optional().describe('Checklist items to attach to the event'), }); export function createCreateEventTool(apiClient: TimeTreeAPIClient) { @@ -94,6 +98,18 @@ export function createCreateEventTool(apiClient: TimeTreeAPIClient) { type: 'string', description: 'Related URL', }, + checklist: { + type: 'array', + description: 'Checklist items to attach to the event', + items: { + type: 'object', + properties: { + checked: { type: 'boolean', description: 'Whether the item is checked' }, + title: { type: 'string', description: 'Checklist item title' }, + }, + required: ['title'], + }, + }, }, required: ['calendar_id', 'title', 'start_at', 'end_at'], }, @@ -117,6 +133,9 @@ export function createCreateEventTool(apiClient: TimeTreeAPIClient) { recurrences: [], alerts: [], file_uuids: [], + attachment: input.checklist + ? { checklist: input.checklist, virtual_user_attendees: [] } + : undefined, }); // Format event for output @@ -135,6 +154,7 @@ export function createCreateEventTool(apiClient: TimeTreeAPIClient) { note: event.note || null, url: event.url || null, category: event.category || null, + checklist: event.attachment?.checklist || null, created_at: event.created_at ? new Date(event.created_at).toISOString() : null, updated_at: event.updated_at ? new Date(event.updated_at).toISOString() : null, }; @@ -257,6 +277,10 @@ export const UpdateEventInputSchema = z.object({ note: z.string().optional().describe('New event notes'), location: z.string().optional().describe('New event location'), url: z.string().optional().describe('New related URL'), + checklist: z.array(z.object({ + checked: z.boolean().default(false).describe('Whether the checklist item is checked'), + title: z.string().min(1).describe('Checklist item title'), + })).optional().describe('Replace the event checklist items'), }); export function createUpdateEventTool(apiClient: TimeTreeAPIClient) { @@ -326,6 +350,18 @@ export function createUpdateEventTool(apiClient: TimeTreeAPIClient) { type: 'string', description: 'New related URL', }, + checklist: { + type: 'array', + description: 'Replace the event checklist items. Use [] to clear the checklist.', + items: { + type: 'object', + properties: { + checked: { type: 'boolean', description: 'Whether the item is checked' }, + title: { type: 'string', description: 'Checklist item title' }, + }, + required: ['title'], + }, + }, }, required: ['calendar_id', 'event_uuid'], }, @@ -352,6 +388,11 @@ export function createUpdateEventTool(apiClient: TimeTreeAPIClient) { note: input.note, location: input.location, url: input.url, + attachment: input.checklist === undefined + ? undefined + : input.checklist.length === 0 + ? null + : { checklist: input.checklist }, } ); @@ -371,6 +412,7 @@ export function createUpdateEventTool(apiClient: TimeTreeAPIClient) { note: event.note || null, url: event.url || null, category: event.category || null, + checklist: event.attachment?.checklist || null, updated_at: event.updated_at ? new Date(event.updated_at).toISOString() : null, }; diff --git a/src/tools/event-tools.ts b/src/tools/event-tools.ts index 329053b..567e429 100644 --- a/src/tools/event-tools.ts +++ b/src/tools/event-tools.ts @@ -104,6 +104,7 @@ export function createGetEventsTool(apiClient: TimeTreeAPIClient) { updated_at: event.updated_at ? new Date(event.updated_at).toISOString() : null, has_alerts: event.alerts && event.alerts.length > 0, has_recurrence: event.recurrences && event.recurrences.length > 0, + checklist: event.attachment?.checklist || null, })); const result = { @@ -256,6 +257,7 @@ export function createGetUpdatedEventsTool(apiClient: TimeTreeAPIClient) { updated_at: event.updated_at ? new Date(event.updated_at).toISOString() : null, has_alerts: event.alerts && event.alerts.length > 0, has_recurrence: event.recurrences && event.recurrences.length > 0, + checklist: event.attachment?.checklist || null, })); const result = { diff --git a/src/types/timetree.ts b/src/types/timetree.ts index 37856c9..2b95bbf 100644 --- a/src/types/timetree.ts +++ b/src/types/timetree.ts @@ -54,6 +54,12 @@ export const EventSchema = z.object({ attendees: z.array(z.number()).optional(), recurrences: z.array(z.any()).optional(), alerts: z.array(z.any()).optional(), + attachment: z.object({ + checklist: z.array(z.object({ + checked: z.boolean().default(false), + title: z.string().min(1), + }).passthrough()).default([]), + }).passthrough().optional().nullable(), created_at: z.number().optional(), updated_at: z.number().optional(), // Allow additional fields but ignore them @@ -110,7 +116,11 @@ export const CreateEventInputSchema = z.object({ alerts: z.array(z.any()).default([]), file_uuids: z.array(z.string()).default([]), attachment: z.object({ - url: z.string().url(), + url: z.string().url().optional(), + checklist: z.array(z.object({ + checked: z.boolean().default(false), + title: z.string().min(1), + }).passthrough()).default([]), virtual_user_attendees: z.array(z.any()).default([]), }).optional(), }).passthrough(); @@ -138,9 +148,13 @@ export const UpdateEventInputSchema = z.object({ alerts: z.array(z.any()).optional(), file_uuids: z.array(z.string()).optional(), attachment: z.object({ - url: z.string().url(), + url: z.string().url().optional(), + checklist: z.array(z.object({ + checked: z.boolean().default(false), + title: z.string().min(1), + }).passthrough()).optional(), virtual_user_attendees: z.array(z.any()).optional(), - }).optional(), + }).optional().nullable(), }).passthrough(); export type UpdateEventInput = z.infer; @@ -183,6 +197,10 @@ export const CreateEventToolInputSchema = z.object({ note: z.string().optional(), location: z.string().optional(), url: z.string().optional(), + checklist: z.array(z.object({ + checked: z.boolean().default(false), + title: z.string().min(1), + }).passthrough()).optional(), }).passthrough(); export type CreateEventToolInput = z.infer; @@ -204,6 +222,10 @@ export const UpdateEventToolInputSchema = z.object({ note: z.string().optional(), location: z.string().optional(), url: z.string().optional(), + checklist: z.array(z.object({ + checked: z.boolean().default(false), + title: z.string().min(1), + }).passthrough()).optional(), }).passthrough(); export type UpdateEventToolInput = z.infer; From 82c7cdf4b218be40f74be2f4aee8140cd468a1d3 Mon Sep 17 00:00:00 2001 From: seisyo58 <33082636+seisyo58@users.noreply.github.com> Date: Sun, 10 May 2026 06:20:54 +0900 Subject: [PATCH 2/2] docs: mention checklist support in tool descriptions (#2) --- src/tools/event-crud-tools.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tools/event-crud-tools.ts b/src/tools/event-crud-tools.ts index a152d1c..76a75fd 100644 --- a/src/tools/event-crud-tools.ts +++ b/src/tools/event-crud-tools.ts @@ -39,7 +39,8 @@ export function createCreateEventTool(apiClient: TimeTreeAPIClient) { 'Create a new event in a TimeTree calendar. Requires CSRF token (automatically managed). ' + 'Returns the created event with UUID. ' + 'Label colors (label_id 1-10): 1=Emerald green, 2=Modern cyan, 3=Deep sky blue, 4=Pastel brown, ' + - '5=Midnight black, 6=Apple red, 7=French rose, 8=Coral pink, 9=Bright orange, 10=Soft violet.', + '5=Midnight black, 6=Apple red, 7=French rose, 8=Coral pink, 9=Bright orange, 10=Soft violet. ' + + 'Supports attaching checklist items.', inputSchema: { type: 'object', properties: { @@ -290,7 +291,8 @@ export function createUpdateEventTool(apiClient: TimeTreeAPIClient) { 'Update an existing event in a TimeTree calendar. Only provide the fields you want to change. ' + 'Requires CSRF token (automatically managed). Returns the updated event. ' + 'Label colors (label_id 1-10): 1=Emerald green, 2=Modern cyan, 3=Deep sky blue, 4=Pastel brown, ' + - '5=Midnight black, 6=Apple red, 7=French rose, 8=Coral pink, 9=Bright orange, 10=Soft violet.', + '5=Midnight black, 6=Apple red, 7=French rose, 8=Coral pink, 9=Bright orange, 10=Soft violet. ' + + 'Supports attaching checklist items.', inputSchema: { type: 'object', properties: {