@bojanrajkovic/mcp-paprika 2.0.0-beta.1 → 2.0.0-beta.3
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/dist/tools/aisles.js +2 -0
- package/dist/tools/categories.js +2 -0
- package/dist/tools/category-writes.js +6 -0
- package/dist/tools/create.js +2 -0
- package/dist/tools/delete.js +2 -0
- package/dist/tools/discover.js +2 -0
- package/dist/tools/empty-trash.js +2 -0
- package/dist/tools/grocery-clear.js +4 -0
- package/dist/tools/grocery-item-purchase.js +2 -0
- package/dist/tools/grocery-item.js +6 -0
- package/dist/tools/grocery-list.js +10 -0
- package/dist/tools/grocery-move.js +2 -0
- package/dist/tools/list.js +2 -0
- package/dist/tools/meal-add-menu.js +2 -0
- package/dist/tools/meal-history-search.js +2 -0
- package/dist/tools/meal-log-cooked.js +2 -0
- package/dist/tools/meal-plan-read.js +2 -0
- package/dist/tools/meal-reschedule.js +2 -0
- package/dist/tools/meal-types.js +2 -0
- package/dist/tools/meal-writes.js +6 -0
- package/dist/tools/menu-item-move.js +2 -0
- package/dist/tools/menu-item-write.js +6 -0
- package/dist/tools/menu-read.js +4 -0
- package/dist/tools/menu-write.js +6 -0
- package/dist/tools/pantry-batch-add.js +2 -0
- package/dist/tools/pantry-delete.js +2 -0
- package/dist/tools/pantry-get.js +2 -0
- package/dist/tools/pantry-list.js +2 -0
- package/dist/tools/pantry-stock.js +4 -0
- package/dist/tools/pantry-update.js +2 -0
- package/dist/tools/photo-generate.js +2 -0
- package/dist/tools/photo-writes.js +4 -0
- package/dist/tools/read.js +2 -0
- package/dist/tools/recipe-categorize.js +2 -0
- package/dist/tools/recipe-favorite.js +4 -0
- package/dist/tools/recipe-rating.js +2 -0
- package/dist/tools/recipe-restore.js +2 -0
- package/dist/tools/search.js +2 -0
- package/dist/tools/update.js +2 -0
- package/package.json +1 -1
package/dist/tools/aisles.js
CHANGED
|
@@ -3,6 +3,8 @@ import { textResult } from "./helpers.js";
|
|
|
3
3
|
export function registerAislesTool(server, ctx) {
|
|
4
4
|
const log = ctx.log.child({ component: "list_aisles" });
|
|
5
5
|
server.registerTool("list_aisles", {
|
|
6
|
+
title: "List grocery aisles",
|
|
7
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
6
8
|
description: "List all known aisles, sorted by order then name. " +
|
|
7
9
|
"Includes the aisle UID needed for pantry and grocery item writes.",
|
|
8
10
|
inputSchema: {},
|
package/dist/tools/categories.js
CHANGED
|
@@ -3,6 +3,8 @@ import { textResult } from "./helpers.js";
|
|
|
3
3
|
export function registerCategoryTools(server, ctx) {
|
|
4
4
|
const log = ctx.log.child({ component: "list_categories" });
|
|
5
5
|
server.registerTool("list_categories", {
|
|
6
|
+
title: "List recipe categories",
|
|
7
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
6
8
|
description: "List all recipe categories with the number of recipes in each. Categories are sorted alphabetically.",
|
|
7
9
|
inputSchema: {},
|
|
8
10
|
}, async (_args) => {
|
|
@@ -11,6 +11,8 @@ function categorySummary(ctx, category) {
|
|
|
11
11
|
export function registerCreateCategoryTool(server, ctx) {
|
|
12
12
|
const log = ctx.log.child({ component: "create_category" });
|
|
13
13
|
server.registerTool("create_category", {
|
|
14
|
+
title: "Create a recipe category",
|
|
15
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
14
16
|
description: "Create a new recipe category. Optionally nest it under an existing category by passing that " +
|
|
15
17
|
"category's UID as `parentUid` to build a hierarchy (e.g. Thai → Curries). Use `list_categories` " +
|
|
16
18
|
"to find parent UIDs. To put recipes in the new category, follow up with `update_recipe`.",
|
|
@@ -45,6 +47,8 @@ export function registerCreateCategoryTool(server, ctx) {
|
|
|
45
47
|
export function registerUpdateCategoryTool(server, ctx) {
|
|
46
48
|
const log = ctx.log.child({ component: "update_category" });
|
|
47
49
|
server.registerTool("update_category", {
|
|
50
|
+
title: "Rename or re-parent a recipe category",
|
|
51
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
48
52
|
description: "Rename and/or re-parent an existing category. Pass `name` to rename, `parentUid` to move it under " +
|
|
49
53
|
"another category, or `null` for `parentUid` to make it top-level. Re-parenting builds the hierarchy " +
|
|
50
54
|
"that `list_categories` renders.",
|
|
@@ -99,6 +103,8 @@ export function registerUpdateCategoryTool(server, ctx) {
|
|
|
99
103
|
export function registerDeleteCategoryTool(server, ctx) {
|
|
100
104
|
const log = ctx.log.child({ component: "delete_category" });
|
|
101
105
|
server.registerTool("delete_category", {
|
|
106
|
+
title: "Delete a recipe category",
|
|
107
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
102
108
|
description: "Delete a category. Refuses if the category still has child categories or is assigned to any recipe — " +
|
|
103
109
|
"reassign or delete those first (move recipes with `update_recipe`, re-parent children with " +
|
|
104
110
|
"`update_category`). This keeps the hierarchy and recipe links consistent.",
|
package/dist/tools/create.js
CHANGED
|
@@ -6,6 +6,8 @@ import { coldStartGuard, commitRecipe, recipeToMarkdown, resolveCategoryRefs, te
|
|
|
6
6
|
export function registerCreateTool(server, ctx) {
|
|
7
7
|
const log = ctx.log.child({ component: "create_recipe" });
|
|
8
8
|
server.registerTool("create_recipe", {
|
|
9
|
+
title: "Create a new recipe",
|
|
10
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
9
11
|
description: "Create a new recipe in the Paprika account. If you built this recipe from a web page, " +
|
|
10
12
|
"follow up with `upload_recipe_photo` and the page's main/hero (og:image) image URL to attach its photo.",
|
|
11
13
|
inputSchema: {
|
package/dist/tools/delete.js
CHANGED
|
@@ -4,6 +4,8 @@ import { coldStartGuard, commitRecipe, textResult } from "./helpers.js";
|
|
|
4
4
|
export function registerDeleteTool(server, ctx) {
|
|
5
5
|
const log = ctx.log.child({ component: "trash_recipe" });
|
|
6
6
|
server.registerTool("trash_recipe", {
|
|
7
|
+
title: "Move a recipe to the trash",
|
|
8
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },
|
|
7
9
|
description: "Soft-delete a recipe by UID, moving it to the Paprika trash. " +
|
|
8
10
|
"This operation is reversible — trashed recipes can be recovered in the Paprika app. " +
|
|
9
11
|
"Requires an exact UID; fuzzy title matching is not supported to prevent accidental deletion.",
|
package/dist/tools/discover.js
CHANGED
|
@@ -3,6 +3,8 @@ import { coldStartGuard, recipeMetadataLines, textResult } from "./helpers.js";
|
|
|
3
3
|
export function registerDiscoverTool(server, ctx, vectorStore) {
|
|
4
4
|
const log = ctx.log.child({ component: "discover_recipes" });
|
|
5
5
|
server.registerTool("discover_recipes", {
|
|
6
|
+
title: "Discover recipes by natural-language search",
|
|
7
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
6
8
|
description: "Discover recipes using semantic search. Finds recipes matching a natural language description of what you're looking for.",
|
|
7
9
|
inputSchema: {
|
|
8
10
|
query: z.string().describe("Natural language description of what you're looking for"),
|
|
@@ -5,6 +5,8 @@ import { coldStartGuard, commitRecipeHardDelete, reconcileLocalRecipe, reconcile
|
|
|
5
5
|
export function registerEmptyTrashTool(server, ctx) {
|
|
6
6
|
const log = ctx.log.child({ component: "purge_recipe" });
|
|
7
7
|
server.registerTool("purge_recipe", {
|
|
8
|
+
title: "Permanently delete a trashed recipe",
|
|
9
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },
|
|
8
10
|
description: "Permanently delete a recipe that is already in the Paprika trash. " +
|
|
9
11
|
"This is IRREVERSIBLE — once emptied from the trash the recipe cannot be recovered. " +
|
|
10
12
|
"The recipe must first be moved to the trash with trash_recipe (a reversible soft-delete); " +
|
|
@@ -5,6 +5,8 @@ import { textResult } from "./helpers.js";
|
|
|
5
5
|
export function registerClearPurchasedTool(server, ctx) {
|
|
6
6
|
const log = ctx.log.child({ component: "clear_purchased_grocery_items" });
|
|
7
7
|
server.registerTool("clear_purchased_grocery_items", {
|
|
8
|
+
title: "Remove purchased items from a grocery list",
|
|
9
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
8
10
|
description: "Clear all purchased items from a grocery list.",
|
|
9
11
|
inputSchema: {
|
|
10
12
|
listUid: GroceryListUidSchema.describe("Grocery list UID to clear purchased items from"),
|
|
@@ -37,6 +39,8 @@ export function registerClearPurchasedTool(server, ctx) {
|
|
|
37
39
|
export function registerClearAllTool(server, ctx) {
|
|
38
40
|
const log = ctx.log.child({ component: "clear_grocery_list" });
|
|
39
41
|
server.registerTool("clear_grocery_list", {
|
|
42
|
+
title: "Remove all items from a grocery list",
|
|
43
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
40
44
|
description: "Clear all items from a grocery list.",
|
|
41
45
|
inputSchema: {
|
|
42
46
|
listUid: GroceryListUidSchema.describe("Grocery list UID to clear all items from"),
|
|
@@ -11,6 +11,8 @@ export const markGroceryItemPurchasedInputSchema = z
|
|
|
11
11
|
export function registerMarkGroceryItemPurchasedTool(server, ctx) {
|
|
12
12
|
const log = ctx.log.child({ component: "mark_grocery_item_purchased" });
|
|
13
13
|
server.registerTool("mark_grocery_item_purchased", {
|
|
14
|
+
title: "Mark a grocery item purchased",
|
|
15
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
14
16
|
description: "Mark a grocery item as purchased (checked off) by UID.",
|
|
15
17
|
inputSchema: markGroceryItemPurchasedInputSchema,
|
|
16
18
|
}, async (args) => {
|
|
@@ -17,6 +17,8 @@ const itemInputSchema = z.object({
|
|
|
17
17
|
export function registerAddGroceryItemsTool(server, ctx) {
|
|
18
18
|
const log = ctx.log.child({ component: "add_grocery_items" });
|
|
19
19
|
server.registerTool("add_grocery_items", {
|
|
20
|
+
title: "Add items to a grocery list",
|
|
21
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
20
22
|
description: "Add one or more items to a grocery list. Check read_grocery_list first to avoid duplicate ingredients — no server-side duplicate guard.",
|
|
21
23
|
inputSchema: {
|
|
22
24
|
listUid: GroceryListUidSchema.describe("UID of the grocery list to add items to"),
|
|
@@ -150,6 +152,8 @@ export const updateGroceryItemInputSchema = z
|
|
|
150
152
|
export function registerUpdateGroceryItemTool(server, ctx) {
|
|
151
153
|
const log = ctx.log.child({ component: "update_grocery_item" });
|
|
152
154
|
server.registerTool("update_grocery_item", {
|
|
155
|
+
title: "Edit a grocery item",
|
|
156
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
153
157
|
description: "Update a grocery item's quantity, aisle, or notes by UID. Only provided fields are changed; " +
|
|
154
158
|
"omitted fields retain their current values. To check an item off, use mark_grocery_item_purchased.",
|
|
155
159
|
inputSchema: updateGroceryItemInputSchema,
|
|
@@ -188,6 +192,8 @@ export function registerUpdateGroceryItemTool(server, ctx) {
|
|
|
188
192
|
export function registerDeleteGroceryItemTool(server, ctx) {
|
|
189
193
|
const log = ctx.log.child({ component: "delete_grocery_item" });
|
|
190
194
|
server.registerTool("delete_grocery_item", {
|
|
195
|
+
title: "Delete a grocery item",
|
|
196
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
191
197
|
description: "Delete a grocery item by UID.",
|
|
192
198
|
inputSchema: {
|
|
193
199
|
uid: GroceryItemUidSchema.describe("Grocery item UID to delete"),
|
|
@@ -6,6 +6,8 @@ import { formatLookupOutcome, resolveLookup, textResult, uidOrTextLookupSchema }
|
|
|
6
6
|
export function registerListGroceryListsTool(server, ctx) {
|
|
7
7
|
const log = ctx.log.child({ component: "list_grocery_lists" });
|
|
8
8
|
server.registerTool("list_grocery_lists", {
|
|
9
|
+
title: "List your grocery lists",
|
|
10
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
9
11
|
description: "List all grocery lists sorted alphabetically by name, with UID and item count per list.",
|
|
10
12
|
inputSchema: {},
|
|
11
13
|
}, async () => {
|
|
@@ -28,6 +30,8 @@ export function registerListGroceryListsTool(server, ctx) {
|
|
|
28
30
|
export function registerReadGroceryListTool(server, ctx) {
|
|
29
31
|
const log = ctx.log.child({ component: "read_grocery_list" });
|
|
30
32
|
server.registerTool("read_grocery_list", {
|
|
33
|
+
title: "Read a grocery list and its items",
|
|
34
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
31
35
|
description: "Get a grocery list by UID or name. Name lookup is tiered (exact → starts-with → contains) " +
|
|
32
36
|
"and case-insensitive, with a disambiguation list when multiple lists match the same tier. " +
|
|
33
37
|
'Pass exactly one shape: {"uid": "..."} or {"name": "..."}.',
|
|
@@ -58,6 +62,8 @@ export function registerReadGroceryListTool(server, ctx) {
|
|
|
58
62
|
export function registerCreateGroceryListTool(server, ctx) {
|
|
59
63
|
const log = ctx.log.child({ component: "create_grocery_list" });
|
|
60
64
|
server.registerTool("create_grocery_list", {
|
|
65
|
+
title: "Create a grocery list",
|
|
66
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
61
67
|
description: "Create a new grocery list with the given name. Rejects duplicate names (case-insensitive exact match); " +
|
|
62
68
|
"if a duplicate is found, the response includes the existing UID.",
|
|
63
69
|
inputSchema: {
|
|
@@ -99,6 +105,8 @@ export function registerCreateGroceryListTool(server, ctx) {
|
|
|
99
105
|
export function registerRenameGroceryListTool(server, ctx) {
|
|
100
106
|
const log = ctx.log.child({ component: "rename_grocery_list" });
|
|
101
107
|
server.registerTool("rename_grocery_list", {
|
|
108
|
+
title: "Rename a grocery list",
|
|
109
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
102
110
|
description: "Rename a grocery list. Rejects if the new name conflicts with a different existing list.",
|
|
103
111
|
inputSchema: {
|
|
104
112
|
uid: GroceryListUidSchema.describe("Grocery list UID to rename"),
|
|
@@ -140,6 +148,8 @@ export function registerRenameGroceryListTool(server, ctx) {
|
|
|
140
148
|
export function registerDeleteGroceryListTool(server, ctx) {
|
|
141
149
|
const log = ctx.log.child({ component: "delete_grocery_list" });
|
|
142
150
|
server.registerTool("delete_grocery_list", {
|
|
151
|
+
title: "Delete a grocery list",
|
|
152
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
143
153
|
description: "Delete a grocery list by UID.",
|
|
144
154
|
inputSchema: {
|
|
145
155
|
uid: GroceryListUidSchema.describe("Grocery list UID to delete"),
|
|
@@ -8,6 +8,8 @@ import { commitPantryItemsBatch } from "./pantry-helpers.js";
|
|
|
8
8
|
export function registerMoveToPantryTool(server, ctx) {
|
|
9
9
|
const log = ctx.log.child({ component: "move_grocery_items_to_pantry" });
|
|
10
10
|
server.registerTool("move_grocery_items_to_pantry", {
|
|
11
|
+
title: "Move grocery items to the pantry",
|
|
12
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },
|
|
11
13
|
description: "Move one or more grocery items to the pantry. Creates pantry items (with today's purchase date), then deletes the grocery items.",
|
|
12
14
|
inputSchema: {
|
|
13
15
|
uids: z.array(GroceryItemUidSchema).min(1).describe("Grocery item UIDs to move to pantry"),
|
package/dist/tools/list.js
CHANGED
|
@@ -3,6 +3,8 @@ import { coldStartGuard, textResult } from "./helpers.js";
|
|
|
3
3
|
export function registerListTool(server, ctx) {
|
|
4
4
|
const log = ctx.log.child({ component: "list_recipes" });
|
|
5
5
|
server.registerTool("list_recipes", {
|
|
6
|
+
title: "List your saved recipes",
|
|
7
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
6
8
|
description: "List all recipes with pagination. Returns recipe summaries sorted alphabetically. Use offset/limit to paginate through the full library. Response includes total recipe count.",
|
|
7
9
|
inputSchema: {
|
|
8
10
|
offset: z.number().int().nonnegative().optional().default(0).describe("Number of recipes to skip (default: 0)"),
|
|
@@ -56,6 +56,8 @@ function renderPlannerAdds(menuName, startDay, items) {
|
|
|
56
56
|
export function registerAddMenuToPlannerTool(server, ctx) {
|
|
57
57
|
const log = ctx.log.child({ component: "schedule_menu" });
|
|
58
58
|
server.registerTool("schedule_menu", {
|
|
59
|
+
title: "Add a saved menu's recipes to the meal planner",
|
|
60
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
59
61
|
description: "Instantiate a saved menu's recipes as meal-planner entries. Look the menu up by UID or name " +
|
|
60
62
|
"(tiered fuzzy match), then materialize each of its items into a meal dated start_date + (day − 1) " +
|
|
61
63
|
"days, posting them all in one batch. This is a one-way COPY, not a link: the planner meals carry no " +
|
|
@@ -30,6 +30,8 @@ export const searchMealHistoryInputSchema = z
|
|
|
30
30
|
export function registerSearchMealHistoryTool(server, ctx) {
|
|
31
31
|
const log = ctx.log.child({ component: "search_meal_history" });
|
|
32
32
|
server.registerTool("search_meal_history", {
|
|
33
|
+
title: "Search past cooked meals by recipe or category",
|
|
34
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
33
35
|
description: 'Search PAST meals (recall/browse), by a specific recipe, a recipe category ("class"), a meal type, ' +
|
|
34
36
|
'and/or a date window — any combination, ANDed. Answers "when did we last have tacos", "how often do ' +
|
|
35
37
|
'we eat Italian", "show the dinners we had in March", or "what have we eaten lately". With no filters ' +
|
|
@@ -21,6 +21,8 @@ export const logCookedMealInputSchema = z
|
|
|
21
21
|
export function registerLogCookedMealTool(server, ctx) {
|
|
22
22
|
const log = ctx.log.child({ component: "log_cooked_meal" });
|
|
23
23
|
server.registerTool("log_cooked_meal", {
|
|
24
|
+
title: "Log a meal you cooked",
|
|
25
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
24
26
|
description: "Log a meal you cooked: records the given recipe on the planner, defaulting to today and the Dinner " +
|
|
25
27
|
"meal type — a quick way to keep your cooking history current. Pass `date` to log a different day or " +
|
|
26
28
|
"`type` for a non-dinner meal. To log a freeform (non-recipe) meal or to plan ahead in bulk, use plan_meals.",
|
|
@@ -16,6 +16,8 @@ export const readMealPlanInputSchema = z
|
|
|
16
16
|
export function registerReadMealPlanTool(server, ctx) {
|
|
17
17
|
const log = ctx.log.child({ component: "read_meal_plan" });
|
|
18
18
|
server.registerTool("read_meal_plan", {
|
|
19
|
+
title: "Show upcoming planned meals",
|
|
20
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
19
21
|
description: "Read the upcoming meal plan: meals scheduled from today forward, grouped by day in ascending date " +
|
|
20
22
|
'order (today first). Defaults to the next 7 days; pass `days` to widen the window. For past meals or recall ("when did we last have X"), use search_meal_history.',
|
|
21
23
|
inputSchema: readMealPlanInputSchema,
|
|
@@ -24,6 +24,8 @@ export const rescheduleMealInputSchema = z
|
|
|
24
24
|
export function registerRescheduleMealTool(server, ctx) {
|
|
25
25
|
const log = ctx.log.child({ component: "reschedule_meal" });
|
|
26
26
|
server.registerTool("reschedule_meal", {
|
|
27
|
+
title: "Reschedule a planned meal",
|
|
28
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
27
29
|
description: "Reschedule a planned meal to a different date by UID, optionally also changing its meal type. " +
|
|
28
30
|
"Moving the date re-sequences the meal to the end of the destination day's order. To change a " +
|
|
29
31
|
"meal's recipe link, freeform name, or scale instead, use update_meal.",
|
package/dist/tools/meal-types.js
CHANGED
|
@@ -35,6 +35,8 @@ function mealTypeLine(mt) {
|
|
|
35
35
|
export function registerMealTypesTool(server, ctx) {
|
|
36
36
|
const log = ctx.log.child({ component: "list_meal_types" });
|
|
37
37
|
server.registerTool("list_meal_types", {
|
|
38
|
+
title: "List meal types",
|
|
39
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
38
40
|
description: "List all meal types — the built-in Breakfast/Lunch/Dinner/Snacks plus any custom " +
|
|
39
41
|
"types — sorted by order then name. Each entry shows whether it is built-in or custom, " +
|
|
40
42
|
"its calendar-export schedule (all-day or a clock time), and its UID. Reference a type " +
|
|
@@ -55,6 +55,8 @@ export const addMealsInputSchema = z.object({
|
|
|
55
55
|
export function registerAddMealsTool(server, ctx) {
|
|
56
56
|
const log = ctx.log.child({ component: "plan_meals" });
|
|
57
57
|
server.registerTool("plan_meals", {
|
|
58
|
+
title: "Add meals to the planner",
|
|
59
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
58
60
|
description: "Add one or more meals to the meal planner. Each item is EITHER recipe-linked (supply " +
|
|
59
61
|
"recipe_uid; display name auto-resolves from the recipe) OR freeform (supply name; no " +
|
|
60
62
|
"recipe). The two shapes are mutually exclusive — Paprika.app's UI dispatches display " +
|
|
@@ -226,6 +228,8 @@ export const updateMealInputSchema = z.object({
|
|
|
226
228
|
export function registerUpdateMealTool(server, ctx) {
|
|
227
229
|
const log = ctx.log.child({ component: "update_meal" });
|
|
228
230
|
server.registerTool("update_meal", {
|
|
231
|
+
title: "Edit a planned meal",
|
|
232
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
229
233
|
description: "Update an existing meal by UID. The `update` payload is a discriminated union: pick exactly one " +
|
|
230
234
|
"of {recipe_uid?, ...other} | {name, ...other} | {recipe_uid: null, name?, ...other}. Recipe link " +
|
|
231
235
|
"and display name are structurally exclusive: name auto-resolves from the recipe for linked meals, " +
|
|
@@ -368,6 +372,8 @@ const deleteMealInputSchema = z.object({
|
|
|
368
372
|
export function registerDeleteMealTool(server, ctx) {
|
|
369
373
|
const log = ctx.log.child({ component: "delete_meal" });
|
|
370
374
|
server.registerTool("delete_meal", {
|
|
375
|
+
title: "Delete a planned meal",
|
|
376
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
371
377
|
description: "Soft-delete a meal from the planner by UID. Idempotent: a second delete on the same UID " +
|
|
372
378
|
"returns a friendly 'already deleted' message without re-POSTing. Requires an exact UID.",
|
|
373
379
|
inputSchema: deleteMealInputSchema.shape,
|
|
@@ -20,6 +20,8 @@ export const moveMenuItemInputSchema = z
|
|
|
20
20
|
export function registerMoveMenuItemTool(server, ctx) {
|
|
21
21
|
const log = ctx.log.child({ component: "move_menu_item" });
|
|
22
22
|
server.registerTool("move_menu_item", {
|
|
23
|
+
title: "Move a menu item to a different day",
|
|
24
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
23
25
|
description: "Move a menu item to a different day within its menu, by UID. A day beyond the menu's current span " +
|
|
24
26
|
"auto-extends the menu so the item stays visible, and the item is re-sequenced to the end of the " +
|
|
25
27
|
"menu's order. To change a menu item's meal type or recipe link instead, use update_menu_item.",
|
|
@@ -47,6 +47,8 @@ export const addMenuItemsInputSchema = z.object({
|
|
|
47
47
|
export function registerAddMenuItemsTool(server, ctx) {
|
|
48
48
|
const log = ctx.log.child({ component: "add_menu_items" });
|
|
49
49
|
server.registerTool("add_menu_items", {
|
|
50
|
+
title: "Add items to a menu",
|
|
51
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
50
52
|
description: "Add one or more menuitems to a menu (saved meal plan). Look the menu up by UID or name (tiered " +
|
|
51
53
|
"fuzzy match). Each item is EITHER recipe-linked (supply recipe_uid; display name auto-resolves " +
|
|
52
54
|
"from the recipe) OR freeform (supply name; no recipe) — the two are mutually exclusive, matching " +
|
|
@@ -205,6 +207,8 @@ export const updateMenuItemInputSchema = z
|
|
|
205
207
|
export function registerUpdateMenuItemTool(server, ctx) {
|
|
206
208
|
const log = ctx.log.child({ component: "update_menu_item" });
|
|
207
209
|
server.registerTool("update_menu_item", {
|
|
210
|
+
title: "Edit a menu item",
|
|
211
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
208
212
|
description: "Update an existing menuitem's meal type or recipe link by UID. Provide at least one of type or " +
|
|
209
213
|
"recipe_uid; omitted fields keep their current values. Changing recipe_uid re-resolves the display " +
|
|
210
214
|
"name from the new recipe. To move an item to a different day, use move_menu_item. The menu link " +
|
|
@@ -283,6 +287,8 @@ export const deleteMenuItemInputSchema = z.object({
|
|
|
283
287
|
export function registerDeleteMenuItemTool(server, ctx) {
|
|
284
288
|
const log = ctx.log.child({ component: "delete_menu_item" });
|
|
285
289
|
server.registerTool("delete_menu_item", {
|
|
290
|
+
title: "Delete a menu item",
|
|
291
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
286
292
|
description: "Soft-delete a menuitem (a planned recipe) from a menu by UID. Idempotent: a second delete on the " +
|
|
287
293
|
"same UID returns a friendly 'already deleted' message without re-POSTing. Requires an exact UID.",
|
|
288
294
|
inputSchema: deleteMenuItemInputSchema.shape,
|
package/dist/tools/menu-read.js
CHANGED
|
@@ -4,6 +4,8 @@ import { menuStartGuard, menuToMarkdown } from "./menu-helpers.js";
|
|
|
4
4
|
export function registerListMenusTool(server, ctx) {
|
|
5
5
|
const log = ctx.log.child({ component: "list_menus" });
|
|
6
6
|
server.registerTool("list_menus", {
|
|
7
|
+
title: "List your menus",
|
|
8
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
7
9
|
description: "List all menus (saved meal plans) in Paprika order, with item count and day span per menu. " +
|
|
8
10
|
"Use read_menu to see a menu's full day-by-day breakdown.",
|
|
9
11
|
inputSchema: {},
|
|
@@ -26,6 +28,8 @@ export function registerListMenusTool(server, ctx) {
|
|
|
26
28
|
export function registerReadMenuTool(server, ctx) {
|
|
27
29
|
const log = ctx.log.child({ component: "read_menu" });
|
|
28
30
|
server.registerTool("read_menu", {
|
|
31
|
+
title: "Read a menu and its items",
|
|
32
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
29
33
|
description: "Get a menu by UID or name, rendered day by day with each day's planned recipes. " +
|
|
30
34
|
"Name lookup is tiered (exact → starts-with → contains) and case-insensitive, with a " +
|
|
31
35
|
"disambiguation list when multiple menus match the same tier. Each recipe line carries " +
|
package/dist/tools/menu-write.js
CHANGED
|
@@ -6,6 +6,8 @@ import { commitMenu, commitMenuItemsBatch, menuStartGuard, menuToMarkdown } from
|
|
|
6
6
|
export function registerCreateMenuTool(server, ctx) {
|
|
7
7
|
const log = ctx.log.child({ component: "create_menu" });
|
|
8
8
|
server.registerTool("create_menu", {
|
|
9
|
+
title: "Create a menu",
|
|
10
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
9
11
|
description: "Create a new menu (saved meal plan) with the given name. Rejects duplicate names " +
|
|
10
12
|
"(case-insensitive exact match); if a duplicate is found, the response includes the existing UID. " +
|
|
11
13
|
"Optionally set the day span (default 1) and free-text notes.",
|
|
@@ -57,6 +59,8 @@ export function registerCreateMenuTool(server, ctx) {
|
|
|
57
59
|
export function registerUpdateMenuTool(server, ctx) {
|
|
58
60
|
const log = ctx.log.child({ component: "update_menu" });
|
|
59
61
|
server.registerTool("update_menu", {
|
|
62
|
+
title: "Edit a menu",
|
|
63
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
60
64
|
description: "Update a menu's name, day span, and/or notes. Look it up by UID or name (tiered fuzzy match, " +
|
|
61
65
|
"case-insensitive). Provide at least one of name, days, or notes. Renaming to a name already used " +
|
|
62
66
|
"by a different menu is rejected (the existing UID is surfaced). Shrinking days below the highest " +
|
|
@@ -154,6 +158,8 @@ export function registerUpdateMenuTool(server, ctx) {
|
|
|
154
158
|
export function registerDeleteMenuTool(server, ctx) {
|
|
155
159
|
const log = ctx.log.child({ component: "delete_menu" });
|
|
156
160
|
server.registerTool("delete_menu", {
|
|
161
|
+
title: "Delete a menu",
|
|
162
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },
|
|
157
163
|
description: "Delete a menu and all of its planned recipes (menuitems). Look it up by UID or name (tiered fuzzy " +
|
|
158
164
|
"match, case-insensitive). The menuitems are tombstoned first, then the menu itself. " +
|
|
159
165
|
'Pass exactly one lookup shape: {"uid": "..."} or {"name": "..."}.',
|
|
@@ -20,6 +20,8 @@ const itemInputSchema = z.object({
|
|
|
20
20
|
export function registerAddPantryItemsTool(server, ctx) {
|
|
21
21
|
const log = ctx.log.child({ component: "add_pantry_items" });
|
|
22
22
|
server.registerTool("add_pantry_items", {
|
|
23
|
+
title: "Add items to the pantry",
|
|
24
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
23
25
|
description: "Add one or more items to the pantry. Skips items that duplicate an existing ingredient (case-insensitive) " +
|
|
24
26
|
"and reports them with the existing UID and a suggestion to use update_pantry_item. " +
|
|
25
27
|
"All date fields are validated up-front; a single unparseable date rejects the entire batch.",
|
|
@@ -5,6 +5,8 @@ import { commitPantryItem, pantryStartGuard } from "./pantry-helpers.js";
|
|
|
5
5
|
export function registerDeletePantryItemTool(server, ctx) {
|
|
6
6
|
const log = ctx.log.child({ component: "delete_pantry_item" });
|
|
7
7
|
server.registerTool("delete_pantry_item", {
|
|
8
|
+
title: "Delete a pantry item",
|
|
9
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
8
10
|
description: "Soft-delete a pantry item by UID. Idempotent: a second delete on the same UID " +
|
|
9
11
|
"returns a friendly 'already deleted' message without re-saving. Requires an exact UID.",
|
|
10
12
|
inputSchema: {
|
package/dist/tools/pantry-get.js
CHANGED
|
@@ -4,6 +4,8 @@ import { pantryItemToMarkdown, pantryStartGuard } from "./pantry-helpers.js";
|
|
|
4
4
|
export function registerGetPantryItemTool(server, ctx) {
|
|
5
5
|
const log = ctx.log.child({ component: "read_pantry_item" });
|
|
6
6
|
server.registerTool("read_pantry_item", {
|
|
7
|
+
title: "Read a pantry item",
|
|
8
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
7
9
|
description: "Get a pantry item by UID or ingredient name. Ingredient lookup is fuzzy " +
|
|
8
10
|
"(exact → starts-with → contains) and case-insensitive, with a disambiguation list " +
|
|
9
11
|
"when multiple items match the same tier. " +
|
|
@@ -3,6 +3,8 @@ import { pantryStartGuard } from "./pantry-helpers.js";
|
|
|
3
3
|
export function registerListPantryTool(server, ctx) {
|
|
4
4
|
const log = ctx.log.child({ component: "list_pantry_items" });
|
|
5
5
|
server.registerTool("list_pantry_items", {
|
|
6
|
+
title: "List your pantry items",
|
|
7
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
6
8
|
description: "List all pantry items sorted alphabetically by ingredient name. Returns the ingredient, quantity, and aisle for each item. Use read_pantry_item with the UID for full details.",
|
|
7
9
|
inputSchema: {},
|
|
8
10
|
}, async () => {
|
|
@@ -16,6 +16,8 @@ export const restockPantryItemInputSchema = z
|
|
|
16
16
|
export function registerMarkPantryItemOutOfStockTool(server, ctx) {
|
|
17
17
|
const log = ctx.log.child({ component: "mark_pantry_item_out_of_stock" });
|
|
18
18
|
server.registerTool("mark_pantry_item_out_of_stock", {
|
|
19
|
+
title: "Mark a pantry item out of stock",
|
|
20
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
19
21
|
description: "Mark a pantry item as out of stock by UID (e.g. you've run out of it).",
|
|
20
22
|
inputSchema: markPantryItemOutOfStockInputSchema,
|
|
21
23
|
}, async (args) => {
|
|
@@ -43,6 +45,8 @@ export function registerMarkPantryItemOutOfStockTool(server, ctx) {
|
|
|
43
45
|
export function registerRestockPantryItemTool(server, ctx) {
|
|
44
46
|
const log = ctx.log.child({ component: "restock_pantry_item" });
|
|
45
47
|
server.registerTool("restock_pantry_item", {
|
|
48
|
+
title: "Mark a pantry item back in stock",
|
|
49
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
46
50
|
description: "Mark a pantry item as back in stock by UID (e.g. you've restocked it).",
|
|
47
51
|
inputSchema: restockPantryItemInputSchema,
|
|
48
52
|
}, async (args) => {
|
|
@@ -28,6 +28,8 @@ export const updatePantryItemInputSchema = z
|
|
|
28
28
|
export function registerUpdatePantryItemTool(server, ctx) {
|
|
29
29
|
const log = ctx.log.child({ component: "update_pantry_item" });
|
|
30
30
|
server.registerTool("update_pantry_item", {
|
|
31
|
+
title: "Edit a pantry item",
|
|
32
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
31
33
|
description: "Update a pantry item's ingredient, quantity, aisle, or dates by UID. Only provided fields are " +
|
|
32
34
|
"changed; omitted fields retain their existing values. Setting expirationDate also updates " +
|
|
33
35
|
"hasExpiration accordingly. To change stock status, use mark_pantry_item_out_of_stock / restock_pantry_item.",
|
|
@@ -41,6 +41,8 @@ export const generatePhotoInputSchema = z.object({
|
|
|
41
41
|
export function registerGeneratePhotoTool(server, ctx, photographyClient) {
|
|
42
42
|
const log = ctx.log.child({ component: "generate_recipe_photo" });
|
|
43
43
|
server.registerTool("generate_recipe_photo", {
|
|
44
|
+
title: "Generate a recipe photo with AI",
|
|
45
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
44
46
|
description: "Generate a styled food photo for a recipe with an AI image model and (by default) attach it to the " +
|
|
45
47
|
"recipe. The prompt is built from the recipe's name, description, and categories — so well-described, " +
|
|
46
48
|
"categorized recipes produce the best results; pass `style` to guide plating or describe an obscure dish. " +
|
|
@@ -99,6 +99,8 @@ async function resolveSourceBytes(source, ctx, recipeUid) {
|
|
|
99
99
|
export function registerUploadPhotoTool(server, ctx) {
|
|
100
100
|
const log = ctx.log.child({ component: "upload_recipe_photo" });
|
|
101
101
|
server.registerTool("upload_recipe_photo", {
|
|
102
|
+
title: "Upload a photo to a recipe",
|
|
103
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
102
104
|
description: "Attach a photo to a recipe from exactly one `source`: a `url` (PREFERRED for web images — the server " +
|
|
103
105
|
"downloads it), a `generation_token` (to save an image you previewed with generate_recipe_photo, attach:false — " +
|
|
104
106
|
"no need to regenerate), or, for programmatic callers, inline `image_base64`. If you built the recipe " +
|
|
@@ -160,6 +162,8 @@ export function registerUploadPhotoTool(server, ctx) {
|
|
|
160
162
|
export function registerDeletePhotoTool(server, ctx) {
|
|
161
163
|
const log = ctx.log.child({ component: "delete_recipe_photo" });
|
|
162
164
|
server.registerTool("delete_recipe_photo", {
|
|
165
|
+
title: "Delete a recipe photo",
|
|
166
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
163
167
|
description: "Delete a photo from a recipe by UID. Idempotent: a second delete on the same UID returns a friendly " +
|
|
164
168
|
"'already deleted' message without re-POSTing. Requires an exact photo UID.",
|
|
165
169
|
inputSchema: deletePhotoInputSchema.shape,
|
package/dist/tools/read.js
CHANGED
|
@@ -3,6 +3,8 @@ import { coldStartGuard, formatLookupOutcome, recipeToMarkdown, resolveLookup, u
|
|
|
3
3
|
export function registerReadTool(server, ctx) {
|
|
4
4
|
const log = ctx.log.child({ component: "read_recipe" });
|
|
5
5
|
server.registerTool("read_recipe", {
|
|
6
|
+
title: "Read a recipe by UID or title",
|
|
7
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
6
8
|
description: "Read a recipe by UID or title. Title lookup is fuzzy (exact → starts-with → contains) " +
|
|
7
9
|
"and returns a disambiguation list when multiple recipes match the same tier. " +
|
|
8
10
|
'Pass exactly one shape: {"uid": "..."} or {"title": "..."}.',
|
|
@@ -24,6 +24,8 @@ export const categorizeRecipeInputSchema = z
|
|
|
24
24
|
export function registerCategorizeRecipeTool(server, ctx) {
|
|
25
25
|
const log = ctx.log.child({ component: "categorize_recipe" });
|
|
26
26
|
server.registerTool("categorize_recipe", {
|
|
27
|
+
title: "Add, replace, or remove a recipe's categories",
|
|
28
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
27
29
|
description: "Add, replace, or remove a recipe's categories by UID. Pass category names or UIDs and a mode: " +
|
|
28
30
|
"add (union with current — the default), replace (set exactly these), or remove (drop these). " +
|
|
29
31
|
"Unknown category names are skipped with a warning. To edit other recipe fields, use update_recipe.",
|
|
@@ -15,6 +15,8 @@ export const unfavoriteRecipeInputSchema = z
|
|
|
15
15
|
export function registerFavoriteRecipeTool(server, ctx) {
|
|
16
16
|
const log = ctx.log.child({ component: "favorite_recipe" });
|
|
17
17
|
server.registerTool("favorite_recipe", {
|
|
18
|
+
title: "Mark a recipe as a favorite",
|
|
19
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
18
20
|
description: "Mark a recipe as a favorite by UID (adds it to the Favorites list).",
|
|
19
21
|
inputSchema: favoriteRecipeInputSchema,
|
|
20
22
|
}, async (args) => {
|
|
@@ -43,6 +45,8 @@ export function registerFavoriteRecipeTool(server, ctx) {
|
|
|
43
45
|
export function registerUnfavoriteRecipeTool(server, ctx) {
|
|
44
46
|
const log = ctx.log.child({ component: "unfavorite_recipe" });
|
|
45
47
|
server.registerTool("unfavorite_recipe", {
|
|
48
|
+
title: "Remove a recipe from favorites",
|
|
49
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
46
50
|
description: "Remove a recipe from the Favorites list by UID.",
|
|
47
51
|
inputSchema: unfavoriteRecipeInputSchema,
|
|
48
52
|
}, async (args) => {
|
|
@@ -11,6 +11,8 @@ export const rateRecipeInputSchema = z
|
|
|
11
11
|
export function registerRateRecipeTool(server, ctx) {
|
|
12
12
|
const log = ctx.log.child({ component: "rate_recipe" });
|
|
13
13
|
server.registerTool("rate_recipe", {
|
|
14
|
+
title: "Rate a recipe",
|
|
15
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
14
16
|
description: "Rate a recipe 0–5 stars by UID. Sets the recipe's star rating; pass 0 to clear it.",
|
|
15
17
|
inputSchema: rateRecipeInputSchema,
|
|
16
18
|
}, async (args) => {
|
|
@@ -11,6 +11,8 @@ export const restoreRecipeInputSchema = z
|
|
|
11
11
|
export function registerRestoreRecipeTool(server, ctx) {
|
|
12
12
|
const log = ctx.log.child({ component: "restore_recipe" });
|
|
13
13
|
server.registerTool("restore_recipe", {
|
|
14
|
+
title: "Restore a recipe from the trash",
|
|
15
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
14
16
|
description: "Restore a trashed recipe by UID, moving it out of the trash back into the active library. " +
|
|
15
17
|
"The inverse of trash_recipe; use purge_recipe to permanently delete a trashed recipe instead.",
|
|
16
18
|
inputSchema: restoreRecipeInputSchema,
|
package/dist/tools/search.js
CHANGED
|
@@ -31,6 +31,8 @@ export const searchRecipesInputSchema = z
|
|
|
31
31
|
export function registerSearchTool(server, ctx) {
|
|
32
32
|
const log = ctx.log.child({ component: "search_recipes" });
|
|
33
33
|
server.registerTool("search_recipes", {
|
|
34
|
+
title: "Search recipes by name, ingredient, or time",
|
|
35
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
34
36
|
description: "Search and filter recipes. Use any combination of: free-text query (matches name, " +
|
|
35
37
|
"ingredients, description), an ingredient list with all/any match mode, and/or max " +
|
|
36
38
|
"prep/cook/total time constraints. At least one criterion is required. Results are " +
|
package/dist/tools/update.js
CHANGED
|
@@ -29,6 +29,8 @@ export const updateRecipeInputSchema = z
|
|
|
29
29
|
export function registerUpdateTool(server, ctx) {
|
|
30
30
|
const log = ctx.log.child({ component: "update_recipe" });
|
|
31
31
|
server.registerTool("update_recipe", {
|
|
32
|
+
title: "Edit a recipe's details",
|
|
33
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
|
|
32
34
|
description: "Update a recipe's content fields by UID (name, ingredients, directions, description, notes, " +
|
|
33
35
|
"servings, prep/cook/total time, source, difficulty, nutritional info). Only provided fields " +
|
|
34
36
|
"change; omitted fields keep their values. This tool does NOT edit rating, categories, favorite " +
|