Bug: client.fetchTodos is not a function — tsdav 2.3.0 doesn't export fetchTodos
Environment
dav-mcp version: 3.0.7 (latest on npm)
tsdav version (bundled): 2.3.0 (git-pinned to PhilflowIO/tsdav#master)
- Node: 24.15.0
- macOS 26.4.1 (arm64)
- iCloud Reminders via CalDAV
Symptom
Every call to list_todos or todo_query tools fails with:
client.fetchTodos is not a function
Verified by grep "exports.fetchTodos" tsdav.cjs → 0 matches in the bundled tsdav build (tsdav v2.3.0 from PhilflowIO/tsdav#master).
Root cause
Source code calls a method that the bundled tsdav doesn't expose:
src/tools/todos/list-todos.js:24 → const todos = await client.fetchTodos({ calendar });
src/tools/todos/todo-query.js:60 → const calendarTodos = await client.fetchTodos({ calendar });
The bundled tsdav only exports fetchCalendars, fetchCalendarObjects, calendarQuery, calendarMultiGet. There is no fetchTodos.
Notably, todo-query.js already contains a comment acknowledging tsdav doesn't support server-side VTODO filtering:
// Client-side filtering (tsdav doesn't support server-side VTODO filtering yet)
— so the author appears to have known about the limitation but still relied on a non-existent fetchTodos shortcut.
Reproduction
npm install -g dav-mcp@3.0.7
# Configure with any iCloud / CalDAV account
# Through any MCP client (Claude Desktop, OpenClaw, etc.):
# call tool list_todos { calendar_url: "..." }
# → throws "client.fetchTodos is not a function"
Proposed fix
Replace client.fetchTodos({ calendar }) with client.fetchCalendarObjects({ calendar }) + a client-side VTODO filter — this is the same pattern todo-query.js already uses for status/summary/time filtering.
src/tools/todos/list-todos.js:
- const calendar = { url: validated.calendar_url };
- const todos = await client.fetchTodos({ calendar });
+ const calendar = { url: validated.calendar_url };
+ const allObjects = await client.fetchCalendarObjects({ calendar });
+ const todos = allObjects.filter(obj => obj.data && obj.data.includes('BEGIN:VTODO'));
src/tools/todos/todo-query.js:
- const calendarTodos = await client.fetchTodos({ calendar });
+ const allObjects = await client.fetchCalendarObjects({ calendar });
+ const calendarTodos = allObjects.filter(obj => obj.data && obj.data.includes('BEGIN:VTODO'));
Tested locally
Applied the patch on Mac mini; node --check passes; iCloud Reminders MCP calls now return VTODO objects correctly. Happy to submit a PR if welcome.
Trade-offs of this fix
fetchCalendarObjects returns all calendar objects (VEVENT + VTODO + VJOURNAL). For small calendars overhead is negligible. For very large calendars this is slower than a hypothetical native VTODO query — but tsdav doesn't expose that yet anyway.
- Filter
obj.data.includes('BEGIN:VTODO') is precise: VEVENT/VJOURNAL have different component names, no false positives.
Alternative
If tsdav later adds proper VTODO support (e.g., client.calendarQuery({ calendar, comp: 'VTODO' })), the fix can be tightened to a server-side query.
Bug:
client.fetchTodos is not a function— tsdav 2.3.0 doesn't exportfetchTodosEnvironment
dav-mcpversion: 3.0.7 (latest on npm)tsdavversion (bundled): 2.3.0 (git-pinned toPhilflowIO/tsdav#master)Symptom
Every call to
list_todosortodo_querytools fails with:Verified by
grep "exports.fetchTodos" tsdav.cjs→ 0 matches in the bundledtsdavbuild (tsdav v2.3.0 fromPhilflowIO/tsdav#master).Root cause
Source code calls a method that the bundled
tsdavdoesn't expose:src/tools/todos/list-todos.js:24→const todos = await client.fetchTodos({ calendar });src/tools/todos/todo-query.js:60→const calendarTodos = await client.fetchTodos({ calendar });The bundled
tsdavonly exportsfetchCalendars,fetchCalendarObjects,calendarQuery,calendarMultiGet. There is nofetchTodos.Notably,
todo-query.jsalready contains a comment acknowledging tsdav doesn't support server-side VTODO filtering:// Client-side filtering (tsdav doesn't support server-side VTODO filtering yet)— so the author appears to have known about the limitation but still relied on a non-existent
fetchTodosshortcut.Reproduction
Proposed fix
Replace
client.fetchTodos({ calendar })withclient.fetchCalendarObjects({ calendar })+ a client-side VTODO filter — this is the same patterntodo-query.jsalready uses for status/summary/time filtering.src/tools/todos/list-todos.js:src/tools/todos/todo-query.js:Tested locally
Applied the patch on Mac mini; node
--checkpasses; iCloud Reminders MCP calls now return VTODO objects correctly. Happy to submit a PR if welcome.Trade-offs of this fix
fetchCalendarObjectsreturns all calendar objects (VEVENT + VTODO + VJOURNAL). For small calendars overhead is negligible. For very large calendars this is slower than a hypothetical native VTODO query — buttsdavdoesn't expose that yet anyway.obj.data.includes('BEGIN:VTODO')is precise: VEVENT/VJOURNAL have different component names, no false positives.Alternative
If
tsdavlater adds proper VTODO support (e.g.,client.calendarQuery({ calendar, comp: 'VTODO' })), the fix can be tightened to a server-side query.