Repository navigation
Expand MCP tools from 12 to 35+ with Plus subscription gating - #1
Conversation
- Add subscription status tracking to client.ts (hasPlus(), initialize()) - Pre-initialize client in server.ts for conditional tool registration - Add Plus-only tool gating for Rewards, Meals, and Photos domains New tools added: - Calendar: create_calendar_event, update_calendar_event, delete_calendar_event - Chores: update_chore, delete_chore - Lists: create_list, update_list, delete_list, create_list_item, update_list_item, delete_list_item - Misc: get_avatars, get_colors - Rewards (Plus): create_reward, update_reward, delete_reward, redeem_reward, unredeem_reward - Meals (Plus): 9 tools for categories, recipes, and meal sittings - Photos (Plus): get_albums Also adds: - openapi-typescript for type generation from OpenAPI spec - Generated types in src/api/generated-types.ts - Updated CLAUDE.md documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ESLint configuration (.eslintrc.cjs) - Add 31 unit tests for date utilities and error handling - Type subscriptionStatus with proper union type - Make formatErrorForMcp accept unknown for safer error handling - Extract resolveListId helper to reduce duplication in list tools - Fix lint error in dates.ts (const vs let) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- CI workflow: runs lint, typecheck, tests, and build on PRs and main - Tests against Node.js 18, 20, and 22 - Release workflow: creates GitHub releases on version tags (v*) - Auto-generates changelog from commits since last tag 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds subscription-aware client initialization and Plus gating; implements many new API endpoints (meals, lists, calendar events, chores, photos, rewards) and corresponding MCP tools; introduces ESLint config, CI/release workflows, OpenAPI type generation, tests for dates and error formatting, and error-handling signature changes. Changes
Sequence Diagram(s)sequenceDiagram
rect rgb(240,248,255)
participant Server as Server Startup
participant Client as SkylightClient
participant Auth as Auth Service
participant Registry as MCP Tool Registry
end
Server->>Client: initializeClient()
activate Client
Client->>Auth: login()
activate Auth
Auth-->>Client: { subscriptionStatus }
deactivate Auth
Client->>Client: store subscriptionStatus
deactivate Client
Server->>Client: hasPlus()
Client-->>Server: boolean
alt hasPlus = true
Server->>Registry: register base tools
Server->>Registry: register reward, meal, photo tools
else hasPlus = false
Server->>Registry: register base tools only
end
Server-->>Server: Log "Skylight MCP Server started (Plus: true/false)"
🎯 4 (Complex) | ⏱️ ~60 minutes
Pre-merge checks❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/api/client.ts (1)
70-81: Unsafe type assertion and missing subscription status for token-based auth users.Two confirmed concerns:
Line 78 - Unsafe type assertion: The API returns
subscription_statusas a genericstring, but the code blindly asserts it toSubscriptionStatus("plus" | "free" | "trial" | null) without validation. If the API returns an unexpected value, the type assertion silently passes and may cause incorrect behavior inhasPlus().Token-based auth limitation: Users who configure
SKYLIGHT_TOKENinstead of email/password skipperformLogin()entirely, leavingsubscriptionStatuspermanentlynull. SincehasPlus()only returnstruewhensubscriptionStatus === "plus", token-based auth users cannot access Plus features (rewards, meals, photos) regardless of their actual subscription.Add validation for the subscription status value before assignment, and provide a mechanism for token-based auth users to set their subscription status (either by fetching it from a separate API endpoint or storing it in configuration).
🧹 Nitpick comments (9)
.github/workflows/release.yml (1)
70-81: Consider more explicit prerelease detection.The current prerelease detection on Line 79 uses a simple check for hyphens in the tag name. While this works for common conventions (v1.0.0-beta, v1.0.0-rc1), it may produce false positives if your tags include hyphens for other reasons (e.g., date-based tags like v2025-01-15).
Alternative prerelease detection
If you want more explicit control, consider checking for specific prerelease identifiers:
draft: false - prerelease: ${{ contains(github.ref, '-') }} + prerelease: ${{ contains(github.ref, '-beta') || contains(github.ref, '-alpha') || contains(github.ref, '-rc') }}Or use a regex-based check in a previous step if you need more complex logic.
Optional: Pin actions to commit SHAs for enhanced security.
Currently, actions are pinned to major versions (
@v4,@v2). While this is a common practice, pinning to specific commit SHAs provides stronger security guarantees against potential supply chain attacks.Example with SHA pinning
- name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: fetch-depth: 0 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2Note: You would need to look up the specific SHA for the versions you want to use and update them periodically.
src/utils/dates.ts (1)
97-97: Good refactor: immutable binding.Changing from
lettoconstfor the destructured match groups is a good practice that prevents accidental reassignment.package.json (1)
19-19: Document or reconfigure the OpenAPI type generation setup.The
generate:typesscript assumes../skylight-api/exists as a sibling directory, but this isn't documented in the README. While the pre-generated types are committed so it doesn't block users or CI, contributors who need to regenerate types from the OpenAPI spec will encounter this undocumented dependency.Consider:
- Adding a section in the README documenting the type generation process and the skylight-api directory requirement
- Making the OpenAPI spec path configurable via an environment variable (e.g.,
OPENAPI_SPEC_PATH)- Clarifying whether the OpenAPI spec should be included or vendored in this repository
tests/errors.test.ts (1)
1-11: Good test coverage; consider addingParseErrortest.
ParseErroris imported (line 8) but not tested. Consider adding a test case for consistency with the other error classes.🔎 Suggested test case
describe("ParseError", () => { it("creates error with default message", () => { const error = new ParseError(); expect(error.message).toBe("Unexpected API response format"); expect(error.code).toBe("PARSE_ERROR"); expect(error.recoverable).toBe(false); }); });src/tools/misc.ts (1)
34-44: Consider extracting shared formatting logic.The attribute formatting logic (lines 34-44 and 90-100) is nearly identical between
get_avatarsandget_colors. This could be extracted into a helper function for maintainability.🔎 Example helper extraction
function formatResourceList<T extends { id: string; attributes: Record<string, unknown> }>( items: T[], labelFn: (item: T) => string ): string { return items .map((item) => { const parts = [labelFn(item)]; for (const [key, value] of Object.entries(item.attributes)) { if (value !== null && value !== undefined) { parts.push(` ${key}: ${value}`); } } return parts.join("\n"); }) .join("\n\n"); }Also applies to: 90-100
src/tools/lists.ts (4)
29-55: Consider improving name resolution when only listId is provided.When
listIdis provided withoutlistName, the function returns the ID as the name (line 35). This means confirmation messages like "Deleted list '123abc'" might be less user-friendly. Consider fetching the list name if needed for better UX, or document this behavior.
345-350: Consider validating that at least one update field is provided.If the user calls
update_listwithout providing any oflabel,kind, orcolor, an empty updates object is sent to the API. Consider returning an early error message if no updates are specified.🔎 Proposed fix
const updates: { label?: string; kind?: "shopping" | "to_do"; color?: string | null } = {}; if (label !== undefined) updates.label = label; if (kind !== undefined) updates.kind = kind; if (color !== undefined) updates.color = color; + if (Object.keys(updates).length === 0) { + return { + content: [{ type: "text" as const, text: "No updates provided. Specify at least one of: label, kind, or color." }], + isError: true, + }; + } + const updated = await updateList(resolved.id, updates);
495-503: Same consideration: validate that updates are provided.Similar to
update_list, if no update fields are specified, an empty updates object is sent. Consider early validation.
539-549: Consider including item details in deletion confirmation.The confirmation message "Deleted item from list" doesn't include the item ID or label. Including the
itemIdwould help users confirm the correct item was deleted.🔎 Proposed fix
- text: `Deleted item from list`, + text: `Deleted item (ID: ${itemId}) from list`,
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (29)
.eslintrc.cjs.github/workflows/ci.yml.github/workflows/release.ymlCLAUDE.mdpackage.jsonsrc/api/client.tssrc/api/endpoints/calendar.tssrc/api/endpoints/chores.tssrc/api/endpoints/lists.tssrc/api/endpoints/meals.tssrc/api/endpoints/misc.tssrc/api/endpoints/photos.tssrc/api/endpoints/rewards.tssrc/api/generated-types.tssrc/api/types.tssrc/server.tssrc/tools/calendar.tssrc/tools/chores.tssrc/tools/family.tssrc/tools/lists.tssrc/tools/meals.tssrc/tools/misc.tssrc/tools/photos.tssrc/tools/rewards.tssrc/tools/tasks.tssrc/utils/dates.tssrc/utils/errors.tstests/dates.test.tstests/errors.test.ts
🧰 Additional context used
🧬 Code graph analysis (18)
src/tools/tasks.ts (1)
src/utils/errors.ts (1)
formatErrorForMcp(75-117)
src/tools/misc.ts (2)
src/api/endpoints/misc.ts (2)
getAvatars(34-38)getColors(43-47)src/utils/errors.ts (1)
formatErrorForMcp(75-117)
src/api/endpoints/photos.ts (1)
src/api/client.ts (1)
getClient(244-249)
src/tools/photos.ts (2)
src/api/endpoints/photos.ts (1)
getAlbums(19-23)src/utils/errors.ts (1)
formatErrorForMcp(75-117)
tests/dates.test.ts (1)
src/utils/dates.ts (5)
getTodayDate(8-14)getDateOffset(19-26)parseDate(32-79)parseTime(85-109)formatDateForDisplay(114-121)
src/api/endpoints/misc.ts (1)
src/api/client.ts (1)
getClient(244-249)
src/api/endpoints/rewards.ts (2)
src/api/types.ts (4)
RewardResource(162-166)CreateRewardRequest(298-314)RewardResponse(334-334)UpdateRewardRequest(316-332)src/api/client.ts (2)
getClient(244-249)request(157-189)
src/api/endpoints/chores.ts (2)
src/api/types.ts (3)
ChoreResource(56-61)UpdateChoreRequest(289-295)ChoreResponse(180-180)src/api/client.ts (2)
getClient(244-249)request(157-189)
src/tools/family.ts (1)
src/utils/errors.ts (1)
formatErrorForMcp(75-117)
src/api/endpoints/calendar.ts (2)
src/api/types.ts (4)
CreateCalendarEventRequest(257-271)CalendarEventResource(140-144)CalendarEventResponse(286-286)UpdateCalendarEventRequest(273-284)src/api/client.ts (1)
getClient(244-249)
src/tools/rewards.ts (3)
src/utils/errors.ts (1)
formatErrorForMcp(75-117)src/api/endpoints/categories.ts (1)
findCategoryByName(32-40)src/api/endpoints/rewards.ts (5)
createReward(53-78)updateReward(92-125)deleteReward(130-135)redeemReward(140-151)unredeemReward(156-163)
src/api/endpoints/meals.ts (1)
src/api/client.ts (1)
getClient(244-249)
src/tools/lists.ts (2)
src/api/endpoints/lists.ts (8)
findListByName(46-50)findListByType(55-68)createList(73-91)updateList(96-112)deleteList(117-120)createListItem(125-145)updateListItem(150-167)deleteListItem(172-177)src/utils/errors.ts (1)
formatErrorForMcp(75-117)
src/server.ts (4)
src/api/client.ts (2)
initializeClient(255-259)hasPlus(222-224)src/tools/misc.ts (1)
registerMiscTools(6-118)src/tools/meals.ts (1)
registerMealTools(19-388)src/tools/photos.ts (1)
registerPhotoTools(6-51)
src/tools/calendar.ts (3)
src/utils/errors.ts (1)
formatErrorForMcp(75-117)src/config.ts (1)
getConfig(89-94)src/api/endpoints/calendar.ts (3)
createCalendarEvent(52-61)updateCalendarEvent(66-76)deleteCalendarEvent(81-86)
tests/errors.test.ts (1)
src/utils/errors.ts (6)
SkylightError(4-14)AuthenticationError(19-24)NotFoundError(39-44)RateLimitError(49-59)formatErrorForMcp(75-117)ConfigurationError(29-34)
src/api/endpoints/lists.ts (2)
src/api/types.ts (8)
ListResource(77-82)CreateListRequest(209-218)ListResponse(182-182)UpdateListRequest(220-229)ListItemResource(93-97)CreateListItemRequest(232-240)ListItemResponse(254-254)UpdateListItemRequest(242-252)src/api/client.ts (2)
getClient(244-249)request(157-189)
src/tools/chores.ts (5)
src/utils/errors.ts (1)
formatErrorForMcp(75-117)src/config.ts (1)
getConfig(89-94)src/api/endpoints/chores.ts (2)
updateChore(118-158)deleteChore(163-168)src/utils/dates.ts (2)
parseDate(32-79)parseTime(85-109)src/api/endpoints/categories.ts (1)
findCategoryByName(32-40)
🔇 Additional comments (66)
.github/workflows/release.yml (4)
1-10: LGTM! Standard release trigger and permissions.The workflow correctly triggers on semantic version tags and sets appropriate permissions for creating releases.
16-28: LGTM! Proper setup for release workflow.The checkout with
fetch-depth: 0correctly retrieves full git history needed for changelog generation, and the Node.js setup with caching is appropriate.
30-40: LGTM! Comprehensive quality gates before release.Running lint, typecheck, tests, and build ensures that only validated code is released. The workflow will correctly abort if any check fails.
42-44: LGTM! Correct version extraction.The shell parameter expansion correctly extracts the version number from the tag reference.
.github/workflows/ci.yml (1)
1-40: Solid CI setup with comprehensive checks.The workflow structure is well-designed with matrix testing across supported Node versions (18, 20, 22) and includes all essential quality gates (lint, typecheck, tests, build). The use of current action versions (@v4) and proper npm caching is appropriate.
tests/dates.test.ts (1)
1-142: Comprehensive test coverage for date utilities.The test suite is well-structured with:
- Proper use of fake timers with cleanup in afterEach hooks
- Coverage of edge cases (timezones, month/year boundaries, natural language parsing)
- Tests for both 12-hour and 24-hour time formats including midnight/noon edge cases
- Appropriate handling of unparseable inputs
.eslintrc.cjs (1)
1-23: Well-balanced ESLint configuration.The configuration follows TypeScript best practices:
- Appropriate rule severity (errors for unused vars, warnings for
anyand console usage)- Smart ignore pattern for unused parameters (
^_)- Correctly excludes generated files from linting
- Allows
console.errorandconsole.warnwhich are reasonable for a server applicationsrc/tools/tasks.ts (1)
71-71: Improved type safety in error handling.Removing the type assertion aligns with the updated
formatErrorForMcp(error: unknown)signature, allowing safer handling of non-Error values without forcing a cast.src/tools/family.ts (1)
94-94: Consistent error handling improvements.All three error handling sites have been updated to remove unnecessary type assertions, consistently applying the safer
formatErrorForMcp(error: unknown)pattern throughout the file.Also applies to: 144-144, 205-205
src/api/endpoints/photos.ts (1)
1-23: Clean Photos API endpoint implementation.The implementation follows the established patterns from other endpoint files:
- Consistent use of
getClient()- Well-typed interfaces with flexible index signatures
- Simple, focused function
The URL pattern
/api/frames/{frameId}/albumsappears to rely on the client's URL interpolation to substitute{frameId}. This is consistent with the patterns used across the API layer.src/tools/photos.ts (1)
6-51: LGTM! Clean implementation following established patterns.The tool registration, error handling with
formatErrorForMcp, and empty-state handling are well-implemented. The attribute formatting loop at lines 31-35 correctly filters out null/undefined values.src/server.ts (2)
25-27: Good approach: pre-initialization for subscription gating.Initializing the client before tool registration ensures Plus status is known at startup. Note that if
initializeClient()fails (e.g., network error, invalid token), the server will fail to start entirely. This is appropriate fail-fast behavior for an MCP server.
40-47: Verify: ShouldregisterMiscToolsbe Plus-gated?The PR description mentions "Plus-only — Misc: get_avatars, get_colors", but
registerMiscToolsis registered outside thehasPlusblock (line 40) while rewards, meals, and photos are inside. Please confirm whether this is intentional or if misc tools should also be gated.tests/errors.test.ts (1)
12-116: LGTM! Comprehensive test coverage for error handling.The tests thoroughly cover error class properties, default values, and the
formatErrorForMcpfunction behavior across different error types including non-Error edge cases.src/tools/misc.ts (1)
6-118: LGTM! Implementation follows established patterns.Both tools have clear descriptions, proper empty-state handling, and consistent error handling.
src/api/endpoints/rewards.ts (3)
53-78: LGTM! Well-structured reward creation.The
createRewardfunction correctly builds the JSON:API request structure, handles optional fields with null defaults, and conditionally adds category relationships.
112-118: Verify: EmptycategoryIdsarray behavior differs fromcreateReward.In
createReward(line 68), empty arrays are ignored (categoryIds.length > 0), but here an empty array would sendrelationships.categories.data: [], potentially clearing all categories. Verify if this is intentional to allow category clearing on update.
130-163: LGTM! Clean implementation of delete and redeem operations.The
deleteReward,redeemReward, andunredeemRewardfunctions are straightforward and follow consistent patterns.src/utils/errors.ts (1)
73-116: Good improvement: acceptingunknownfor safer error handling.This change correctly handles the TypeScript reality that
catchblocks receiveunknownvalues. The instanceof chain gracefully degrades from specific errors to generic Error to String fallback.src/api/endpoints/chores.ts (3)
152-155: Verify: Using PUT for partial update vs PATCH in rewards.This uses
PUTfor updating a chore, whileupdateRewardin rewards.ts usesPATCH.PUTtypically implies replacing the entire resource, whilePATCHis for partial updates. If the API supports both, this may work, but consider aligning withPATCHfor consistency and clearer semantics.
103-158: LGTM! Comprehensive update implementation with proper null handling.The
updateChorefunction correctly handles optional fields, nullable values for clearing, and category relationship updates (including unsetting via null).
160-168: LGTM! Simple and correct delete implementation.src/tools/chores.ts (3)
4-4: LGTM! Import updated to include new API functions.
267-345: LGTM! Well-implemented update tool with proper validation.The
update_choretool correctly handles:
- Nullable fields (
time,assigneecan be set tonullto clear)- Assignee resolution via
findCategoryByNamewith appropriate error message- Date/time parsing with timezone support
347-381: LGTM! Clean delete implementation with helpful documentation.The tool description includes a useful note about recurring chores, and the implementation follows established error-handling patterns.
src/api/types.ts (1)
207-334: LGTM! Type definitions are well-structured.The new request/response type definitions follow consistent JSON:API patterns and use appropriate TypeScript constructs:
- Create requests use required fields with optional extensions
- Update requests use
Partial<>for flexible updates- Response types correctly alias
JsonApiResponse<Resource>- Naming is consistent across all resource types
src/api/endpoints/misc.ts (1)
1-47: LGTM! Clean implementation following established patterns.The avatar and color endpoints are straightforward and consistent with other endpoint modules. The use of index signatures (
[key: string]: unknown) in the attributes provides appropriate flexibility for API evolution.src/api/endpoints/calendar.ts (1)
48-86: LGTM! Calendar CRUD operations implemented correctly.The three new calendar event operations follow established patterns and maintain type safety. The implementation correctly uses:
- POST for creation
- PUT for updates (via
client.request())- DELETE for deletion
CLAUDE.md (1)
1-83: LGTM! Documentation accurately reflects the expanded feature set.The documentation updates clearly communicate:
- The expanded tool count (12 → 35+)
- Plus subscription requirements and detection
- Clear categorization of base vs Plus-only tools
- The new type generation workflow
src/api/client.ts (3)
12-15: LGTM! Well-designed subscription status type.The union type appropriately models the possible subscription states, including
nullfor when the status is unknown or not yet determined.
218-238: LGTM! Clean API for subscription status.The three new methods provide a clear, type-safe interface for checking subscription status:
hasPlus()provides a convenient boolean checkgetSubscriptionStatus()exposes the full statusinitialize()enables pre-initialization to avoid lazy auth
250-259: LGTM! Useful helper for explicit initialization.The
initializeClient()function provides a convenient way to ensure the client is authenticated before use, which is helpful for the server startup flow.src/tools/rewards.ts (5)
151-216: LGTM! Well-implemented create_reward tool.The implementation correctly:
- Validates required parameters (name, pointValue)
- Resolves assignee names to category IDs using
findCategoryByName- Provides clear error messages when family members aren't found
- Returns actionable success messages with the created reward ID
218-269: LGTM! Clean update_reward implementation.The conditional updates object construction (lines 245-250) is a clean pattern that only includes fields that were actually provided. Good use of
Parameters<typeof updateReward>[1]for type inference.
271-305: LGTM! Simple and correct delete operation.The delete tool appropriately warns users about permanent removal in the description.
307-356: LGTM! Redeem tool with good assignee resolution.Correctly reuses the
findCategoryByNamepattern from create_reward to resolve the assignee parameter, maintaining consistency across tools.
358-392: LGTM! Complete unredeem implementation.Provides the necessary undo functionality for reward redemptions.
src/api/endpoints/lists.ts (2)
70-120: LGTM! Complete list CRUD operations.The three list operations are well-implemented with:
- Appropriate parameter types and defaults (color defaults to null)
- Consistent use of request/response types
- Correct HTTP methods (POST, PUT, DELETE)
- Type-safe request body construction
122-177: LGTM! Complete list item CRUD operations.The list item operations mirror the list operations pattern effectively:
- Clear parameter lists with optional fields
- Flexible update mechanism via partial updates object
- Proper path construction with both listId and itemId
- Consistent null defaults for optional fields
src/tools/meals.ts (6)
19-55: LGTM! Clean meal categories retrieval.Simple and effective tool for discovering meal category IDs needed for other meal operations.
57-133: LGTM! Recipe listing and detail tools implemented well.Both
get_recipesandget_recipeprovide clear, structured output. The attribute iteration inget_recipe(lines 117-121) elegantly handles dynamic recipe fields.
135-240: LGTM! Complete recipe CRUD operations.The create, update, and delete tools follow the same robust patterns established in the rewards module:
- Conditional updates object construction
- Clear success messages with IDs
- Appropriate parameter validation
- Permanent deletion warnings
242-276: LGTM! Useful grocery list integration.The
add_recipe_to_grocery_listtool provides helpful meal planning workflow integration.
278-339: LGTM! Thoughtful date range defaults.Lines 299-300 provide sensible defaults:
- Start: today
- End: 7 days from start
This makes the tool easy to use for the common "what's for dinner this week?" query while still allowing custom ranges.
341-387: LGTM! Complete meal sitting creation.The tool correctly:
- Parses user-friendly date strings ("today", "tomorrow", or YYYY-MM-DD)
- Handles timezone conversions via config
- Links recipes to meal sittings via optional recipeId
src/tools/calendar.ts (6)
4-10: LGTM!Import expansion correctly brings in the new CRUD endpoints from the calendar API module, aligning with the new tool implementations below.
99-99: Improved type safety.Passing the raw
errortoformatErrorForMcp(error)is correct since the function acceptsunknownand handles all error types gracefully.
162-162: Consistent error handling.Same improvement as above—correctly leverages the
unknownparameter type offormatErrorForMcp.
170-232: Well-structured tool implementation.The tool correctly validates inputs via zod, documents parameters clearly, and handles errors consistently. The ISO format requirement for timestamps is documented in the schema descriptions.
264-275: Verify partial update handling.The updates object is typed as
Record<string, unknown>, which bypasses theUpdateCalendarEventRequesttype. Ensure the API accepts partial updates with only the fields that changed, and consider using a stricter type if the request schema is known.
294-328: LGTM!The delete tool is straightforward and follows the established pattern with proper error handling and user feedback.
src/tools/lists.ts (5)
4-15: LGTM!Import expansion correctly brings in all required list API endpoints for the new CRUD operations.
112-112: Consistent error handling.Correctly updated to pass raw
errortoformatErrorForMcp.
271-309: LGTM!The create_list tool correctly validates inputs, creates the list via the API, and returns a clear confirmation message.
368-412: LGTM!The delete_list tool correctly resolves the list, performs the deletion, and provides confirmation. Error handling is consistent.
414-468: LGTM!Good UX with the default-to-grocery-list behavior, making it easy for users to add items without specifying a list. The confirmation message is informative.
src/api/endpoints/meals.ts (10)
1-12: LGTM!The import and
MealCategoryResourceinterface are well-defined. Using[key: string]: unknownprovides flexibility for additional API fields.
14-42: LGTM!Resource interfaces are well-structured with appropriate optional fields and relationship definitions.
44-61: LGTM!Response interfaces correctly model JSON:API patterns with optional
includedarrays for sideloaded resources.
63-72: LGTM!Simple and correct implementation for fetching meal categories.
74-100: LGTM!Recipe fetching functions are well-implemented with sensible defaults for including related meal categories.
102-125: LGTM!The createRecipe function correctly handles required and optional fields with appropriate defaults.
127-151: LGTM!Partial update implementation is correct, only sending fields that were explicitly provided.
153-172: LGTM!Both functions are implemented correctly. The
addRecipeToGroceryListaction endpoint follows REST conventions for resource actions.
174-195: LGTM!The getMealSittings function correctly handles optional date range filtering.
197-223: LGTM!The createMealSitting function correctly handles required and optional parameters for scheduling meals.
Use version-sorted tag list instead of git describe HEAD^ for more reliable changelog generation across different repository structures. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Summary
Changes
New Tools (23+)
Calendar:
create_calendar_event,update_calendar_event,delete_calendar_eventChores:
update_chore,delete_choreLists:
create_list,update_list,delete_list,create_list_item,update_list_item,delete_list_itemMisc:
get_avatars,get_colorsPlus-Only:
create_reward,update_reward,delete_reward,redeem_reward,unredeem_rewardget_meal_categories,get_recipes,get_recipe,create_recipe,update_recipe,delete_recipe,add_recipe_to_grocery_list,get_meal_sittings,create_meal_sittingget_albumsCode Quality Improvements
.eslintrc.cjsconfigurationSubscriptionStatuswith proper union typeformatErrorForMcpacceptunknownfor safer error handlingresolveListIdhelper to reduce duplication in list toolsTest plan
npm run typecheckpassesnpm run lintpassesnpm test- 31/31 tests pass🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Infrastructure
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.