yazio-mcp 0.0.16-beta.0 → 0.0.16-beta.2

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/README.md CHANGED
@@ -15,6 +15,8 @@ An MCP (Model Context Protocol) server that connects Claude/Cursor to your Yazio
15
15
  - 📊 **Nutrition Analysis** - Get comprehensive diet data and insights
16
16
  - 🍎 **Food Tracking** - Search, add, and manage food entries
17
17
  - 🏃‍♂️ **Fitness Data** - Track exercises and water intake
18
+ - 📓 **Diary Notes** - Read and write daily notes and feeling tags
19
+ - 🥣 **Recipes** - Create, log, and delete your own recipes
18
20
  - ⚖️ **Weight Monitoring** - View weight history and trends
19
21
  - 🎯 **Goal Management** - Access and manage nutrition goals
20
22
  - 🔍 **Product Search** - Search Yazio's extensive [food database](https://www.yazio.com/en/foods)
@@ -91,7 +93,8 @@ Easily log meals you forgot to track in the Yazio app directly from Claude or Cu
91
93
  | `get_user` | Get user profile | - |
92
94
  | `get_user_daily_summary` | Get daily nutrition summary | `date` |
93
95
  | `get_user_consumed_items` | Get food entries for a date | `date` |
94
- | `get_user_weight` | Get weight data | `date` (optional) |
96
+ | `get_user_weight` | Get the last weight entry up to a date | `date` (optional) |
97
+ | `get_user_weight_history` | Get all weight entries in a date range | `start`, `end` (optional) |
95
98
  | `get_user_exercises` | Get exercise data | `date` |
96
99
  | `get_user_water_intake` | Get water intake | `date` |
97
100
  | `get_user_goals` | Get nutrition goals | `date` (optional) |
@@ -109,6 +112,9 @@ Easily log meals you forgot to track in the Yazio app directly from Claude or Cu
109
112
  | `create_product` | Create a custom product from label values per 100 g/ml | `name`, `category`, `energy_per_100`, `protein_per_100`, `fat_per_100`, `carb_per_100` |
110
113
  | `add_quick_entry` | Log a one-off entry with total nutrition, without a product ("quick add") | `name`, `date`, `daytime`, `energy` |
111
114
  | `add_user_consumed_recipe` | Log portions of a recipe | `recipe_id`, `portion_count`, `date`, `daytime` |
115
+ | `create_user_recipe` | Create a recipe from products; nutrients per portion are calculated | `name`, `portion_count`, `ingredients` |
116
+ | `get_user_note` | Get the diary note and feeling tags for a date | `date` |
117
+ | `set_user_note` | Set the diary note and/or feeling tags for a date | `date`, `note`, `tags` |
112
118
 
113
119
  ## Test Connection
114
120
 
@@ -1,4 +1,5 @@
1
1
  import * as z from 'zod';
2
+ export declare const DateTimeStringSchema: z.ZodPipe<z.ZodString, z.ZodTransform<`${string}-${string}-${string} ${string}:${string}:${string}`, string>>;
2
3
  export declare const DaytimeSchema: z.ZodEnum<{
3
4
  breakfast: "breakfast";
4
5
  lunch: "lunch";
@@ -100,14 +101,14 @@ export declare const UserSchema: z.ZodObject<{
100
101
  name: z.ZodString;
101
102
  }, z.core.$loose>>;
102
103
  email: z.ZodString;
103
- premium_type: z.ZodString;
104
+ premium_type: z.ZodNullable<z.ZodString>;
104
105
  sex: z.ZodEnum<{
105
106
  male: "male";
106
107
  female: "female";
107
108
  other: "other";
108
109
  }>;
109
110
  first_name: z.ZodString;
110
- last_name: z.ZodString;
111
+ last_name: z.ZodNullable<z.ZodString>;
111
112
  city: z.ZodString;
112
113
  country: z.ZodString;
113
114
  weight_change_per_week: z.ZodNumber;
@@ -224,9 +225,13 @@ export declare const DailySummarySchema: z.ZodObject<{
224
225
  }, z.core.$loose>;
225
226
  active_fasting_countdown_template_key: z.ZodNullable<z.ZodString>;
226
227
  }, z.core.$loose>;
228
+ export declare const WeightHistorySchema: z.ZodArray<z.ZodObject<{
229
+ date: z.ZodPipe<z.ZodString, z.ZodTransform<`${string}-${string}-${string} ${string}:${string}:${string}`, string>>;
230
+ value: z.ZodNumber;
231
+ }, z.core.$loose>>;
227
232
  export declare const WeightEntrySchema: z.ZodObject<{
228
233
  id: z.ZodString;
229
- date: z.ZodString;
234
+ date: z.ZodPipe<z.ZodString, z.ZodTransform<`${string}-${string}-${string} ${string}:${string}:${string}`, string>>;
230
235
  value: z.ZodNullable<z.ZodNumber>;
231
236
  external_id: z.ZodNullable<z.ZodString>;
232
237
  gateway: z.ZodNullable<z.ZodString>;
@@ -274,7 +279,7 @@ export declare const WaterIntakeSchema: z.ZodObject<{
274
279
  export declare const ConsumedItemsSchema: z.ZodObject<{
275
280
  products: z.ZodArray<z.ZodObject<{
276
281
  id: z.ZodString;
277
- date: z.ZodString;
282
+ date: z.ZodPipe<z.ZodString, z.ZodTransform<`${string}-${string}-${string} ${string}:${string}:${string}`, string>>;
278
283
  daytime: z.ZodEnum<{
279
284
  breakfast: "breakfast";
280
285
  lunch: "lunch";
@@ -289,7 +294,7 @@ export declare const ConsumedItemsSchema: z.ZodObject<{
289
294
  }, z.core.$loose>>;
290
295
  recipe_portions: z.ZodArray<z.ZodObject<{
291
296
  id: z.ZodString;
292
- date: z.ZodString;
297
+ date: z.ZodPipe<z.ZodString, z.ZodTransform<`${string}-${string}-${string} ${string}:${string}:${string}`, string>>;
293
298
  daytime: z.ZodEnum<{
294
299
  breakfast: "breakfast";
295
300
  lunch: "lunch";
@@ -302,7 +307,7 @@ export declare const ConsumedItemsSchema: z.ZodObject<{
302
307
  }, z.core.$loose>>;
303
308
  simple_products: z.ZodArray<z.ZodObject<{
304
309
  id: z.ZodString;
305
- date: z.ZodString;
310
+ date: z.ZodPipe<z.ZodString, z.ZodTransform<`${string}-${string}-${string} ${string}:${string}:${string}`, string>>;
306
311
  daytime: z.ZodEnum<{
307
312
  breakfast: "breakfast";
308
313
  lunch: "lunch";
@@ -403,3 +408,7 @@ export declare const RecipeSchema: z.ZodObject<{
403
408
  }, z.core.$loose>>;
404
409
  }, z.core.$loose>;
405
410
  export declare const RecipeIdsSchema: z.ZodArray<z.ZodString>;
411
+ export declare const FeelingSchema: z.ZodObject<{
412
+ note: z.ZodNullable<z.ZodString>;
413
+ tags: z.ZodArray<z.ZodString>;
414
+ }, z.core.$loose>;
@@ -6,6 +6,7 @@ export type YazioDietaryPreferences = z.infer<typeof S.DietaryPreferencesSchema>
6
6
  export type YazioGoals = z.infer<typeof S.GoalsSchema>;
7
7
  export type YazioDailySummary = z.infer<typeof S.DailySummarySchema>;
8
8
  export type YazioWeightEntry = z.infer<typeof S.WeightEntrySchema>;
9
+ export type YazioWeightHistory = z.infer<typeof S.WeightHistorySchema>;
9
10
  export type YazioExercises = z.infer<typeof S.ExercisesSchema>;
10
11
  export type YazioSuggestedProduct = z.infer<typeof S.SuggestedProductsSchema>[number];
11
12
  export type YazioWaterIntake = z.infer<typeof S.WaterIntakeSchema>;
@@ -13,6 +14,7 @@ export type YazioConsumedItems = z.infer<typeof S.ConsumedItemsSchema>;
13
14
  export type YazioProductSearchResult = z.infer<typeof S.ProductSearchResultsSchema>[number];
14
15
  export type YazioProduct = z.infer<typeof S.ProductSchema>;
15
16
  export type YazioRecipe = z.infer<typeof S.RecipeSchema>;
17
+ export type YazioFeeling = z.infer<typeof S.FeelingSchema>;
16
18
  export type Daytime = z.infer<typeof S.DaytimeSchema>;
17
19
  /** "YYYY-MM-DD" or "YYYY-MM-DD HH:mm:ss" (local time, sent as is) */
18
20
  export type YazioDateTime = string;
@@ -65,6 +67,24 @@ export interface CreateProductDto {
65
67
  }[];
66
68
  producer: string | null;
67
69
  }
70
+ export interface CreateUserRecipeDto {
71
+ id: string;
72
+ name: string;
73
+ portion_count: number;
74
+ /** Per portion; energy.energy, nutrient.fat, nutrient.protein and nutrient.carb are required */
75
+ nutrients: Record<string, number>;
76
+ /** At least 2 */
77
+ servings: {
78
+ product_id: string;
79
+ name: string;
80
+ producer: string | null;
81
+ amount: number;
82
+ base_unit: string;
83
+ serving: string | null;
84
+ serving_quantity: number | null;
85
+ }[];
86
+ instructions: string[];
87
+ }
68
88
  /**
69
89
  * POST /user/water-intake, found in https://github.com/juriadams/yazio/issues/3:
70
90
  * - the body is a bare array of entries, not wrapped in an object;
@@ -1,5 +1,5 @@
1
1
  import { YazioHttp, type Credentials, type YazioHttpOptions } from './http.js';
2
- import type { AddConsumedItemsDto, CreateProductDto, Daytime, ProductSearchOptions, WaterIntakeEntry } from './types.js';
2
+ import type { AddConsumedItemsDto, CreateProductDto, CreateUserRecipeDto, Daytime, ProductSearchOptions, WaterIntakeEntry, YazioFeeling } from './types.js';
3
3
  export declare const today: () => string;
4
4
  export declare class YazioApi {
5
5
  readonly http: YazioHttp;
@@ -14,10 +14,10 @@ export declare class YazioApi {
14
14
  name: string;
15
15
  } | null;
16
16
  email: string;
17
- premium_type: string;
17
+ premium_type: string | null;
18
18
  sex: "male" | "female" | "other";
19
19
  first_name: string;
20
- last_name: string;
20
+ last_name: string | null;
21
21
  city: string;
22
22
  country: string;
23
23
  weight_change_per_week: number;
@@ -153,12 +153,18 @@ export declare class YazioApi {
153
153
  getLastWeight: (date?: string) => Promise<{
154
154
  [x: string]: unknown;
155
155
  id: string;
156
- date: string;
156
+ date: `${string}-${string}-${string} ${string}:${string}:${string}`;
157
157
  value: number | null;
158
158
  external_id: string | null;
159
159
  gateway: string | null;
160
160
  source: string | null;
161
161
  } | null>;
162
+ /** Every entry between the dates, both included; a day can have several */
163
+ getWeightHistory: (start: string, end?: string) => Promise<{
164
+ [x: string]: unknown;
165
+ date: `${string}-${string}-${string} ${string}:${string}:${string}`;
166
+ value: number;
167
+ }[]>;
162
168
  getExercises: (date?: string) => Promise<{
163
169
  [x: string]: unknown;
164
170
  training: {
@@ -202,7 +208,7 @@ export declare class YazioApi {
202
208
  products: {
203
209
  [x: string]: unknown;
204
210
  id: string;
205
- date: string;
211
+ date: `${string}-${string}-${string} ${string}:${string}:${string}`;
206
212
  daytime: "breakfast" | "lunch" | "dinner" | "snack";
207
213
  type: string;
208
214
  product_id: string;
@@ -213,7 +219,7 @@ export declare class YazioApi {
213
219
  recipe_portions: {
214
220
  [x: string]: unknown;
215
221
  id: string;
216
- date: string;
222
+ date: `${string}-${string}-${string} ${string}:${string}:${string}`;
217
223
  daytime: "breakfast" | "lunch" | "dinner" | "snack";
218
224
  recipe_id: string;
219
225
  portion_count: number;
@@ -222,7 +228,7 @@ export declare class YazioApi {
222
228
  simple_products: {
223
229
  [x: string]: unknown;
224
230
  id: string;
225
- date: string;
231
+ date: `${string}-${string}-${string} ${string}:${string}:${string}`;
226
232
  daytime: "breakfast" | "lunch" | "dinner" | "snack";
227
233
  name: string;
228
234
  nutrients: Record<string, number>;
@@ -338,4 +344,13 @@ export declare class YazioApi {
338
344
  }>;
339
345
  getUserRecipeIds: () => Promise<string[]>;
340
346
  deleteUserRecipe: (id: string) => Promise<void>;
347
+ createUserRecipe: (recipe: CreateUserRecipeDto) => Promise<void>;
348
+ /** The diary note and feeling tags of a day */
349
+ getFeeling: (date: string) => Promise<{
350
+ [x: string]: unknown;
351
+ note: string | null;
352
+ tags: string[];
353
+ }>;
354
+ /** Replaces the day's note and tags; the API ignores a date in the body */
355
+ setFeeling: (date: string, feeling: YazioFeeling) => Promise<void>;
341
356
  }
package/dist/index.js CHANGED
@@ -22139,6 +22139,7 @@ function v4(options, buf, offset) {
22139
22139
  var v4_default = v4;
22140
22140
 
22141
22141
  // src/api/schemas.ts
22142
+ var DateTimeStringSchema = string2().regex(/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]) ([01]\d|2[0-3]):[0-5]\d:[0-5]\d$/).transform((value) => value);
22142
22143
  var DaytimeSchema = _enum(["breakfast", "lunch", "dinner", "snack"]);
22143
22144
  var ProductCategorySchema = _enum([
22144
22145
  "babyfood",
@@ -22231,10 +22232,10 @@ var UserSchema = looseObject({
22231
22232
  name: string2()
22232
22233
  }).nullable(),
22233
22234
  email: string2(),
22234
- premium_type: string2(),
22235
+ premium_type: string2().nullable(),
22235
22236
  sex: _enum(["male", "female", "other"]),
22236
22237
  first_name: string2(),
22237
- last_name: string2(),
22238
+ last_name: string2().nullable(),
22238
22239
  city: string2(),
22239
22240
  country: string2(),
22240
22241
  weight_change_per_week: number2(),
@@ -22315,9 +22316,10 @@ var DailySummarySchema = looseObject({
22315
22316
  }),
22316
22317
  active_fasting_countdown_template_key: string2().nullable()
22317
22318
  });
22319
+ var WeightHistorySchema = array(looseObject({ date: DateTimeStringSchema, value: number2() }));
22318
22320
  var WeightEntrySchema = looseObject({
22319
22321
  id: string2(),
22320
- date: string2(),
22322
+ date: DateTimeStringSchema,
22321
22323
  value: number2().nullable(),
22322
22324
  external_id: string2().nullable(),
22323
22325
  gateway: string2().nullable(),
@@ -22355,7 +22357,7 @@ var WaterIntakeSchema = looseObject({
22355
22357
  });
22356
22358
  var ConsumedProductSchema = looseObject({
22357
22359
  id: string2(),
22358
- date: string2(),
22360
+ date: DateTimeStringSchema,
22359
22361
  daytime: DaytimeSchema,
22360
22362
  type: string2(),
22361
22363
  product_id: string2(),
@@ -22365,7 +22367,7 @@ var ConsumedProductSchema = looseObject({
22365
22367
  });
22366
22368
  var ConsumedRecipePortionSchema = looseObject({
22367
22369
  id: string2(),
22368
- date: string2(),
22370
+ date: DateTimeStringSchema,
22369
22371
  daytime: DaytimeSchema,
22370
22372
  type: string2().optional(),
22371
22373
  recipe_id: string2(),
@@ -22373,7 +22375,7 @@ var ConsumedRecipePortionSchema = looseObject({
22373
22375
  });
22374
22376
  var ConsumedSimpleProductSchema = looseObject({
22375
22377
  id: string2(),
22376
- date: string2(),
22378
+ date: DateTimeStringSchema,
22377
22379
  daytime: DaytimeSchema,
22378
22380
  type: string2().optional(),
22379
22381
  name: string2(),
@@ -22444,6 +22446,10 @@ var RecipeSchema = looseObject({
22444
22446
  )
22445
22447
  });
22446
22448
  var RecipeIdsSchema = array(string2());
22449
+ var FeelingSchema = looseObject({
22450
+ note: string2().nullable(),
22451
+ tags: array(string2())
22452
+ });
22447
22453
 
22448
22454
  // src/schemas.ts
22449
22455
  var DateStringSchema = iso_exports.date().describe("Date in YYYY-MM-DD format");
@@ -22471,6 +22477,10 @@ var GetUserInfoInputSchema = EmptyInputSchema;
22471
22477
  var GetUserWeightInputSchema = object({
22472
22478
  date: DateStringSchema.optional().describe("Returns the last weight entry up to this date (defaults to today)")
22473
22479
  });
22480
+ var GetUserWeightHistoryInputSchema = object({
22481
+ start: DateStringSchema.describe("First date, included"),
22482
+ end: DateStringSchema.optional().describe("Last date, included (defaults to today)")
22483
+ });
22474
22484
  var GetWaterIntakeInputSchema = DateInputSchema;
22475
22485
  var SearchProductsInputSchema = QueryInputSchema;
22476
22486
  function lenient(schema) {
@@ -22507,7 +22517,6 @@ var GetUserSuggestedProductsInputSchema = object({
22507
22517
  daytime: DaytimeSchema.optional().describe("Meal to get suggestions for (defaults to breakfast)"),
22508
22518
  limit: LimitSchema
22509
22519
  });
22510
- var DateTimeStringSchema = string2().regex(/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]) ([01]\d|2[0-3]):[0-5]\d:[0-5]\d$/).transform((value) => value);
22511
22520
  var ConsumedAtSchema = union([DateStringSchema, DateTimeStringSchema]).describe('Date and time when the food was consumed in "YYYY-MM-DD HH:mm:ss" format (e.g., "2025-12-18 12:30:00"), or date only in YYYY-MM-DD format');
22512
22521
  var AddConsumedItemInputSchema = object({
22513
22522
  // id: ProductIdSchema.describe('Random identifier for the consumed item'),
@@ -22563,6 +22572,27 @@ var AddQuickEntryInputSchema = object({
22563
22572
  carb: number2().nonnegative().optional().describe("Total carbohydrates in g"),
22564
22573
  extra_nutrients: ExtraNutrientsSchema
22565
22574
  });
22575
+ var CreateUserRecipeInputSchema = object({
22576
+ name: string2().min(1).describe("Recipe name"),
22577
+ portion_count: number2().int().positive().describe("Number of portions the recipe makes"),
22578
+ ingredients: array(object({
22579
+ product_id: ProductIdSchema.describe("Product ID from search_products or create_product"),
22580
+ amount: number2().positive().describe("Amount of the product in the whole recipe, in its base unit (g or ml)"),
22581
+ serving: ServingTypeSchema.optional(),
22582
+ serving_quantity: number2().positive().optional().describe("Quantity of servings")
22583
+ }).refine((item) => item.serving === void 0 === (item.serving_quantity === void 0), {
22584
+ message: "Pass serving and serving_quantity together, or neither"
22585
+ })).min(2).describe("Products in the whole recipe; Yazio requires at least 2"),
22586
+ instructions: array(string2().min(1)).optional().describe("Preparation steps")
22587
+ });
22588
+ var GetUserNoteInputSchema = DateInputSchema;
22589
+ var SetUserNoteInputSchema = object({
22590
+ date: DateStringSchema,
22591
+ note: string2().nullable().optional().describe("Note text for the day; null clears it; leave out to keep the current note"),
22592
+ tags: array(string2()).optional().describe('Feeling tags as in the Yazio app, e.g. ["happy", "motivated", "headache"]; the API rejects unknown tags. [] clears them; leave out to keep the current tags')
22593
+ }).refine((args) => args.note !== void 0 || args.tags !== void 0, {
22594
+ message: "Provide note, tags or both"
22595
+ });
22566
22596
  var GetDietaryPreferencesInputSchema = EmptyInputSchema;
22567
22597
  var GetUserGoalsInputSchema = object({
22568
22598
  date: DateStringSchema.optional().describe("Date to get the goals for (defaults to today)")
@@ -22706,6 +22736,8 @@ var YazioApi = class {
22706
22736
  getGoals = (date5 = today()) => this.http.request("GET", "/user/goals/unmodified", { query: { date: date5 }, schema: GoalsSchema });
22707
22737
  getDailySummary = (date5) => this.http.request("GET", "/user/widgets/daily-summary", { query: { date: date5 }, schema: DailySummarySchema });
22708
22738
  getLastWeight = (date5 = today()) => this.http.request("GET", "/user/bodyvalues/weight/last", { query: { date: date5 }, schema: WeightEntrySchema.nullable() });
22739
+ /** Every entry between the dates, both included; a day can have several */
22740
+ getWeightHistory = (start, end = today()) => this.http.request("GET", "/user/bodyvalues/weight", { query: { start, end }, schema: WeightHistorySchema });
22709
22741
  getExercises = (date5 = today()) => this.http.request("GET", "/user/exercises", { query: { date: date5 }, schema: ExercisesSchema });
22710
22742
  getSuggestedProducts = (daytime, date5 = today()) => this.http.request("GET", "/user/products/suggested", { query: { date: date5, daytime }, schema: SuggestedProductsSchema });
22711
22743
  getConsumedItems = (date5) => this.http.request("GET", "/user/consumed-items", { query: { date: date5 }, schema: ConsumedItemsSchema });
@@ -22726,6 +22758,11 @@ var YazioApi = class {
22726
22758
  getRecipe = (id) => this.http.request("GET", `/recipes/${encodeURIComponent(id)}`, { schema: RecipeSchema });
22727
22759
  getUserRecipeIds = () => this.http.request("GET", "/user/recipes", { schema: RecipeIdsSchema });
22728
22760
  deleteUserRecipe = (id) => this.http.request("DELETE", `/user/recipes/${encodeURIComponent(id)}`);
22761
+ createUserRecipe = (recipe) => this.http.request("POST", "/user/recipes", { body: recipe });
22762
+ /** The diary note and feeling tags of a day */
22763
+ getFeeling = (date5) => this.http.request("GET", "/user/feeling", { query: { date: date5 }, schema: FeelingSchema });
22764
+ /** Replaces the day's note and tags; the API ignores a date in the body */
22765
+ setFeeling = (date5, feeling) => this.http.request("PUT", "/user/feeling", { query: { date: date5 }, body: feeling });
22729
22766
  };
22730
22767
 
22731
22768
  // src/index.ts
@@ -22736,12 +22773,14 @@ var SERVER_INSTRUCTIONS = `Access to the signed-in user's Yazio nutrition and fi
22736
22773
  Conventions:
22737
22774
  - Dates are YYYY-MM-DD; diary and water entries also take "YYYY-MM-DD HH:mm:ss". Amounts are in base units, grams (g) or milliliters (ml).
22738
22775
  - daytime (meal) is one of: breakfast, lunch, dinner, snack.
22739
- - get_* and search_products only read. add_*, create_product, remove_user_consumed_item and delete_user_recipe change the user's data.
22776
+ - get_* and search_products only read. add_*, create_*, set_user_note, remove_user_consumed_item and delete_user_recipe change the user's data.
22740
22777
 
22741
22778
  Logging food: search_products, then get_product for its servings and base unit, then add_user_consumed_item. For food that isn't in the database, use add_quick_entry for a one-off entry or create_product for something eaten again. For a recipe, use add_user_consumed_recipe.
22742
22779
 
22743
22780
  Water: add_user_water_intake with add_ml adds to the day's total.
22744
22781
 
22782
+ Notes: get_user_note reads the day's diary note and feeling tags, set_user_note changes them.
22783
+
22745
22784
  Removing a diary entry: get_user_consumed_items gives the entry's id (not its product_id) for remove_user_consumed_item.`;
22746
22785
  var YazioMcpServer = class {
22747
22786
  yazioClient = null;
@@ -22923,7 +22962,7 @@ var YazioMcpServer = class {
22923
22962
  "get_user_weight",
22924
22963
  {
22925
22964
  title: "Get Weight",
22926
- description: "Get user weight data",
22965
+ description: "Get the last weight entry up to a date. Use get_user_weight_history for all entries in a date range.",
22927
22966
  inputSchema: GetUserWeightInputSchema,
22928
22967
  annotations: {
22929
22968
  readOnlyHint: true,
@@ -22934,6 +22973,21 @@ var YazioMcpServer = class {
22934
22973
  return await this.getUserWeight(args);
22935
22974
  }
22936
22975
  );
22976
+ server.registerTool(
22977
+ "get_user_weight_history",
22978
+ {
22979
+ title: "Get Weight History",
22980
+ description: "Get all weight entries between two dates in one call, e.g. for trends. A day can have several entries at different times.",
22981
+ inputSchema: GetUserWeightHistoryInputSchema,
22982
+ annotations: {
22983
+ readOnlyHint: true,
22984
+ idempotentHint: true
22985
+ }
22986
+ },
22987
+ async (args) => {
22988
+ return await this.getUserWeightHistory(args);
22989
+ }
22990
+ );
22937
22991
  server.registerTool(
22938
22992
  "get_user_daily_summary",
22939
22993
  {
@@ -23019,7 +23073,7 @@ var YazioMcpServer = class {
23019
23073
  "delete_user_recipe",
23020
23074
  {
23021
23075
  title: "Delete Recipe",
23022
- description: "Permanently delete one of the user's own recipes. It can't be restored or recreated through this server, so confirm with the user first.",
23076
+ description: "Permanently delete one of the user's own recipes. It can't be restored, so confirm with the user first.",
23023
23077
  inputSchema: DeleteUserRecipeInputSchema,
23024
23078
  annotations: {
23025
23079
  readOnlyHint: false,
@@ -23127,6 +23181,53 @@ var YazioMcpServer = class {
23127
23181
  return await this.addUserConsumedRecipe(args);
23128
23182
  }
23129
23183
  );
23184
+ server.registerTool(
23185
+ "create_user_recipe",
23186
+ {
23187
+ title: "Create Recipe",
23188
+ description: "Create a recipe from products and their amounts in the whole recipe. The nutrients per portion are calculated from the products. Returns the recipe ID for add_user_consumed_recipe.",
23189
+ inputSchema: CreateUserRecipeInputSchema,
23190
+ annotations: {
23191
+ readOnlyHint: false,
23192
+ destructiveHint: false,
23193
+ idempotentHint: false
23194
+ }
23195
+ },
23196
+ async (args) => {
23197
+ return await this.createUserRecipe(args);
23198
+ }
23199
+ );
23200
+ server.registerTool(
23201
+ "get_user_note",
23202
+ {
23203
+ title: "Get Note",
23204
+ description: "Get the user's diary note and feeling tags for a date (the Notes card in the Yazio diary)",
23205
+ inputSchema: GetUserNoteInputSchema,
23206
+ annotations: {
23207
+ readOnlyHint: true,
23208
+ idempotentHint: true
23209
+ }
23210
+ },
23211
+ async (args) => {
23212
+ return await this.getUserNote(args);
23213
+ }
23214
+ );
23215
+ server.registerTool(
23216
+ "set_user_note",
23217
+ {
23218
+ title: "Set Note",
23219
+ description: "Set the user's diary note and/or feeling tags for a date. Fields you leave out keep their current value; the note text replaces the old text, so include it to append.",
23220
+ inputSchema: SetUserNoteInputSchema,
23221
+ annotations: {
23222
+ readOnlyHint: false,
23223
+ destructiveHint: true,
23224
+ idempotentHint: true
23225
+ }
23226
+ },
23227
+ async (args) => {
23228
+ return await this.setUserNote(args);
23229
+ }
23230
+ );
23130
23231
  }
23131
23232
  // The same read-only data as the get_* tools, for clients that attach resources as context
23132
23233
  setupResourceHandlers(server) {
@@ -23358,6 +23459,24 @@ ${JSON.stringify(weight, null, 2)}`
23358
23459
  throw new Error(`Failed to get user weight: ${error2}`);
23359
23460
  }
23360
23461
  }
23462
+ async getUserWeightHistory(args) {
23463
+ const client = await this.ensureAuthenticated();
23464
+ try {
23465
+ const entries = await client.getWeightHistory(args.start, args.end);
23466
+ return {
23467
+ content: [
23468
+ {
23469
+ type: "text",
23470
+ text: `Weight entries (${entries.length}):
23471
+
23472
+ ${JSON.stringify(entries, null, 2)}`
23473
+ }
23474
+ ]
23475
+ };
23476
+ } catch (error2) {
23477
+ throw new Error(`Failed to get weight history: ${error2}`);
23478
+ }
23479
+ }
23361
23480
  async getUserWaterIntake(args) {
23362
23481
  const client = await this.ensureAuthenticated();
23363
23482
  try {
@@ -23613,6 +23732,90 @@ ${JSON.stringify(suggestions, null, 2)}`
23613
23732
  throw new Error(`Failed to add recipe portion: ${error2}`);
23614
23733
  }
23615
23734
  }
23735
+ async createUserRecipe(args) {
23736
+ const client = await this.ensureAuthenticated();
23737
+ try {
23738
+ const products = await Promise.all(args.ingredients.map((item) => client.getProduct(item.product_id)));
23739
+ const totals = {};
23740
+ products.forEach((product, i) => {
23741
+ for (const [key, value] of Object.entries(product.nutrients)) {
23742
+ if (typeof value === "number") totals[key] = (totals[key] ?? 0) + value * args.ingredients[i].amount;
23743
+ }
23744
+ });
23745
+ const nutrients = Object.fromEntries(Object.entries(totals).map(([key, value]) => [key, value / args.portion_count]));
23746
+ const id = v4_default();
23747
+ await client.createUserRecipe({
23748
+ id,
23749
+ name: args.name,
23750
+ portion_count: args.portion_count,
23751
+ nutrients,
23752
+ servings: args.ingredients.map((item, i) => ({
23753
+ product_id: item.product_id,
23754
+ name: products[i].name,
23755
+ producer: products[i].producer,
23756
+ amount: item.amount,
23757
+ base_unit: products[i].base_unit,
23758
+ serving: item.serving ?? null,
23759
+ serving_quantity: item.serving_quantity ?? null
23760
+ })),
23761
+ instructions: args.instructions ?? []
23762
+ });
23763
+ return {
23764
+ content: [
23765
+ {
23766
+ type: "text",
23767
+ text: `Successfully created recipe "${args.name}" with id: ${id}
23768
+
23769
+ Nutrients per portion:
23770
+ ${JSON.stringify(nutrients, null, 2)}`
23771
+ }
23772
+ ]
23773
+ };
23774
+ } catch (error2) {
23775
+ throw new Error(`Failed to create recipe: ${error2}`);
23776
+ }
23777
+ }
23778
+ async getUserNote(args) {
23779
+ const client = await this.ensureAuthenticated();
23780
+ try {
23781
+ const feeling = await client.getFeeling(args.date);
23782
+ return {
23783
+ content: [
23784
+ {
23785
+ type: "text",
23786
+ text: `Note for ${args.date}:
23787
+
23788
+ ${JSON.stringify(feeling, null, 2)}`
23789
+ }
23790
+ ]
23791
+ };
23792
+ } catch (error2) {
23793
+ throw new Error(`Failed to get note: ${error2}`);
23794
+ }
23795
+ }
23796
+ async setUserNote(args) {
23797
+ const client = await this.ensureAuthenticated();
23798
+ try {
23799
+ const current = await client.getFeeling(args.date);
23800
+ const feeling = {
23801
+ note: args.note === void 0 ? current.note : args.note,
23802
+ tags: args.tags ?? current.tags
23803
+ };
23804
+ await client.setFeeling(args.date, feeling);
23805
+ return {
23806
+ content: [
23807
+ {
23808
+ type: "text",
23809
+ text: `Successfully set the note for ${args.date}:
23810
+
23811
+ ${JSON.stringify(feeling, null, 2)}`
23812
+ }
23813
+ ]
23814
+ };
23815
+ } catch (error2) {
23816
+ throw new Error(`Failed to set note: ${error2}`);
23817
+ }
23818
+ }
23616
23819
  async removeUserConsumedItem(args) {
23617
23820
  const client = await this.ensureAuthenticated();
23618
23821
  try {
package/dist/schemas.d.ts CHANGED
@@ -33,6 +33,10 @@ export declare const GetUserInfoInputSchema: z.ZodObject<{}, z.core.$strip>;
33
33
  export declare const GetUserWeightInputSchema: z.ZodObject<{
34
34
  date: z.ZodOptional<z.ZodISODate>;
35
35
  }, z.core.$strip>;
36
+ export declare const GetUserWeightHistoryInputSchema: z.ZodObject<{
37
+ start: z.ZodISODate;
38
+ end: z.ZodOptional<z.ZodISODate>;
39
+ }, z.core.$strip>;
36
40
  export declare const GetWaterIntakeInputSchema: z.ZodObject<{
37
41
  date: z.ZodISODate;
38
42
  }, z.core.$strip>;
@@ -187,6 +191,25 @@ export declare const AddQuickEntryInputSchema: z.ZodObject<{
187
191
  carb: z.ZodOptional<z.ZodNumber>;
188
192
  extra_nutrients: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
189
193
  }, z.core.$strip>;
194
+ export declare const CreateUserRecipeInputSchema: z.ZodObject<{
195
+ name: z.ZodString;
196
+ portion_count: z.ZodNumber;
197
+ ingredients: z.ZodArray<z.ZodObject<{
198
+ product_id: z.ZodUUID;
199
+ amount: z.ZodNumber;
200
+ serving: z.ZodOptional<z.ZodString>;
201
+ serving_quantity: z.ZodOptional<z.ZodNumber>;
202
+ }, z.core.$strip>>;
203
+ instructions: z.ZodOptional<z.ZodArray<z.ZodString>>;
204
+ }, z.core.$strip>;
205
+ export declare const GetUserNoteInputSchema: z.ZodObject<{
206
+ date: z.ZodISODate;
207
+ }, z.core.$strip>;
208
+ export declare const SetUserNoteInputSchema: z.ZodObject<{
209
+ date: z.ZodISODate;
210
+ note: z.ZodOptional<z.ZodNullable<z.ZodString>>;
211
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
212
+ }, z.core.$strip>;
190
213
  export declare const GetDietaryPreferencesInputSchema: z.ZodObject<{}, z.core.$strip>;
191
214
  export declare const GetUserGoalsInputSchema: z.ZodObject<{
192
215
  date: z.ZodOptional<z.ZodISODate>;
@@ -196,6 +219,7 @@ export type GetFoodEntriesInput = z.infer<typeof GetFoodEntriesInputSchema>;
196
219
  export type GetDailySummaryInput = z.infer<typeof GetDailySummaryInputSchema>;
197
220
  export type GetUserInfoInput = z.infer<typeof GetUserInfoInputSchema>;
198
221
  export type GetUserWeightInput = z.infer<typeof GetUserWeightInputSchema>;
222
+ export type GetUserWeightHistoryInput = z.infer<typeof GetUserWeightHistoryInputSchema>;
199
223
  export type GetWaterIntakeInput = z.infer<typeof GetWaterIntakeInputSchema>;
200
224
  export type SearchProductsInput = z.infer<typeof SearchProductsInputSchema>;
201
225
  export type GetProductInput = z.infer<typeof GetProductInputSchema>;
@@ -212,3 +236,6 @@ export type GetUserGoalsInput = z.infer<typeof GetUserGoalsInputSchema>;
212
236
  export type CreateProductInput = z.infer<typeof CreateProductInputSchema>;
213
237
  export type AddQuickEntryInput = z.infer<typeof AddQuickEntryInputSchema>;
214
238
  export type AddConsumedRecipeInput = z.infer<typeof AddConsumedRecipeInputSchema>;
239
+ export type CreateUserRecipeInput = z.infer<typeof CreateUserRecipeInputSchema>;
240
+ export type GetUserNoteInput = z.infer<typeof GetUserNoteInputSchema>;
241
+ export type SetUserNoteInput = z.infer<typeof SetUserNoteInputSchema>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yazio-mcp",
3
- "version": "0.0.16-beta.0",
3
+ "version": "0.0.16-beta.2",
4
4
  "description": "MCP server for accessing Yazio user & nutrition data (unofficial)",
5
5
  "mcpName": "io.github.fliptheweb/yazio-mcp",
6
6
  "author": "fliptheweb",