MCP server for Kenotex ── expose local todo/event/habit/category/reminder CRUD + check-ins to any MCP-compatible LLM client (Claude Desktop, Cursor, Zed, OpenClaw, etc.)
Strong foundation with 22 well-named tools, comprehensive schemas, and detailed descriptions. Most tools follow verb_noun naming (create_todo, list_events, set_habit_check). Descriptions are substantive (100-400 chars typical), explaining WHAT, WHEN, and prerequisites. Input schemas are complete with types and constraints (enums for priority/filter, minima/maxima for numeric fields). However, output schemas are not documented, LLMs cannot see what fields to expect from responses. Error handling is present but generic (KenotexClientError with code/message/status); recovery guidance is minimal. Tool composition is excellent (single responsibility, proper chaining via IDs). No security issues detected (no secrets in params, token injection via server-side lookup). Habit tools are exceptionally detailed with complex cadence logic well-documented.
Attach a reminder N minutes before a todo's deadline or an event's start. Creates the DB row and schedules an OS notification.
Mark a todo complete. For recurring parents, completes the next uncompleted instance.
Create a new todo category.
Create a calendar event in Kenotex. `recurrence` supports 'daily' | 'weekly:mon,wed' | 'monthly:15' | 'yearly' | 'none'. 'after:*' is NOT supported for events.
Create a check-in habit in Kenotex — a routine the user ticks off. DAILY by default (optionally multi-dose: up to 6 dose times a day, each checked separately — medication doses, drinking water, stretching). Pass `cadence` to make it an INTERVAL habit instead: Q times every N days, N times per week(s), or N times per calendar month(s) — 'water the plants every 3 days', 'stretch twice every 5 days', 'run twice a week', 'deworm the cat twice a month'. For one-off tasks or fixed-weekday / fixed-day-of-month schedules (weekly:mon, monthly:15, after:*) use create_todo with a recurrence. Habits take no category.
Output schemas not documented. LLMs cannot see what fields responses contain (e.g., does list_todos return total_count? pagination cursor? category details?). This forces agents to guess field names and risks failed downstream tool calls.
Error handling lacks recovery guidance. KenotexClientError returns code/message/status but does not tell LLMs what to do next (retry? ask user? call a discovery tool?). E.g., 'categoryId not found' should suggest 'Call list_categories() first.'
Destructive tools (delete_event, delete_habit, delete_todo) lack confirmation or dry-run support. Agents can permanently delete data without a safety gate. Consider adding a 'confirm' parameter or a separate 'preview_delete' tool.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 66 | 2026-07-28+ | v2 |
Create a todo in Kenotex. Use when the user wants to add, remember, or track a task. A categoryId is REQUIRED — fetch one via list_categories (or create_category) first.
Delete an event. Recurring parents materialize past occurrences then delete.
PERMANENTLY delete a habit and all its check records. Irreversible.
Delete a todo. Recurring parents also remove all child instances.
Fetch a specific event by id. Accepts real event ids or virtual occurrence ids (`{parent}__occ__{yyyy-MM-dd}`).
Fetch a specific habit by id. `times` returns as [{id, time}] objects — pass a slot's `id` as `slotId` when checking a dose of a multi-dose habit. Interval habits also carry `cadence` and `currentPeriod` ({start,end,dueDay,doneCount,quota,done}) — use `currentPeriod.done` for 'is this period satisfied'.
Fetch a specific todo by id.
List all todo categories in Kenotex. Useful before `create_todo` so the LLM can pick a valid categoryId.
List calendar events in a date range. Virtual recurring occurrences are expanded.
List a habit's raw check records, optionally within an inclusive date range. Each record carries checkDate 'yyyy-MM-dd' and slotId (null for single-dose and interval habits). Use to answer history questions or compute streaks — for daily habits a day counts toward a streak only when EVERY dose is checked; for interval habits read currentPeriod / currentStreak from get_habit instead of recomputing period progress from raw rows.
List all check-in habits with computed fields (doseCount, isMultiDose, times incl. stable slot ids, endDate, remindersEnabled, currentStreak, checkedToday, todayDoneCount, plus cadence / isIntervalHabit / currentPeriod {start,end,dueDay,doneCount,quota,done} — currentPeriod is null for daily habits). Answers 'did I check in today?' / 'what's my streak?' / 'am I done for this period?' (read currentPeriod.done — checkedToday only says whether TODAY was ticked). Call this (or get_habit) to discover slot ids before set_habit_check on a multi-dose habit.
List todos with optional filter and limit.
Remove a reminder by id and cancel its OS notification.
Set a habit's check state for a date: checked=true marks it done, checked=false removes the check. Idempotent — safe to repeat. `date` defaults to today when omitted (only pass a date to back-fill a past day). Single-dose habits take NO slotId. Multi-dose habits: pass a `slotId` (a times[].id from get_habit / list_habits) to check one dose, or omit it to check ALL of today's doses at once. INTERVAL habits (cadence) are checked per calendar day: no slotId; `date` must be a checkable day — from the cadence startDate up to today (or endDate if earlier), never in the future (422 on date). The response's doneCount / fullyDone are calendar-day facts — for 'is this period satisfied' read currentPeriod.done from get_habit.
Partially update an event. Cannot update virtual occurrences — modify parent or create exception.
Partially update a habit. `times` FULLY REPLACES the dose schedule (array of "HH:mm", up to 6; existing slots keep their ids by position). `times: null` or `[]` resets to a single daily dose. `endDate: null` explicitly clears the end date. `cadence` is tri-state: an object switches / retunes the interval cadence (the period anchor `startDate` is kept — sending a different one is a 422 on cadence.startDate); `cadence: null` turns the habit back into a plain daily habit (anchor kept, so switching back later keeps the same period boundaries); omitted = untouched. An interval cadence combined with 2+ dose times (new or existing) is a 422 on times. Omitted fields keep existing values.
Partially update a todo. Null values explicitly clear fields; omit fields to keep existing values.
Tool annotations missing. No readOnlyHint, destructiveHint, or idempotentHint declared in tool definitions. This prevents MCP clients from applying appropriate safety policies (e.g., warning before destructive ops).
Pagination not implemented for list tools. list_todos accepts a limit (max 1000) but no offset/cursor. list_events, list_habits, list_habit_checks have no pagination at all. Large result sets risk context window exhaustion.