mcp-grocy 2.7.2 → 2.8.0

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/CHANGELOG.md CHANGED
@@ -1,9 +1,22 @@
1
- ## [2.7.2](https://github.com/miguelangel-nubla/mcp-grocy/compare/v2.7.1...v2.7.2) (2026-09-10)
1
+ # [2.8.0](https://github.com/miguelangel-nubla/mcp-grocy/compare/v2.7.2...v2.8.0) (2026-09-25)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * accept numbers and booleans encoded as strings in tool arguments ([5dfbbc7](https://github.com/miguelangel-nubla/mcp-grocy/commit/5dfbbc799fdfde36255f6fcc3665e0113f36cf14))
7
+ * advertise tool parameter descriptions in tools/list ([0418bf5](https://github.com/miguelangel-nubla/mcp-grocy/commit/0418bf5be83428f19e52c2952e2f3e5bdd078d73))
8
+ * **tools:** normalize created_object_id and id to numbers in responses ([5f613d6](https://github.com/miguelangel-nubla/mcp-grocy/commit/5f613d6b6c87f860ac3a79e6d8a473a91d19d3a7))
2
9
 
3
10
 
11
+ ### Features
12
+
13
+ * add recipes_mealplan_add_note tool for meal plan notes with sections ([e80aa65](https://github.com/miguelangel-nubla/mcp-grocy/commit/e80aa651e9653bf765d361a4ebc3d285d325a23e)), closes [#2](https://github.com/miguelangel-nubla/mcp-grocy/issues/2)
14
+
15
+ ## [2.7.2](https://github.com/miguelangel-nubla/mcp-grocy/compare/v2.7.1...v2.7.2) (2026-09-10)
16
+
4
17
  ### Bug Fixes
5
18
 
6
- * add prepack script, update release configs, and fix docker workflows ([c464c05](https://github.com/miguelangel-nubla/mcp-grocy/commit/c464c054ab4f3f420647196ded7454c60f3702fc))
19
+ - add prepack script, update release configs, and fix docker workflows ([c464c05](https://github.com/miguelangel-nubla/mcp-grocy/commit/c464c054ab4f3f420647196ded7454c60f3702fc))
7
20
 
8
21
  ## [2.7.1](https://github.com/miguelangel-nubla/mcp-grocy/compare/v2.7.0...v2.7.1) (2026-09-10)
9
22
 
package/README.md CHANGED
@@ -54,7 +54,7 @@ Transform your LLM into an intelligent household management assistant with focus
54
54
  ### 🛒 **Smart Shopping & Planning**
55
55
 
56
56
  - Maintain shopping lists with intelligent quantity management
57
- - Plan meals with recipe scheduling and fulfillment checking
57
+ - Plan meals with recipe scheduling, free-text notes per meal plan section, and fulfillment checking
58
58
  - Automatically add missing ingredients to shopping lists
59
59
  - Track shopping locations and optimize store visits
60
60
 
@@ -1,9 +1,22 @@
1
- ## [2.7.2](https://github.com/miguelangel-nubla/mcp-grocy/compare/v2.7.1...v2.7.2) (2026-09-10)
1
+ # [2.8.0](https://github.com/miguelangel-nubla/mcp-grocy/compare/v2.7.2...v2.8.0) (2026-09-25)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * accept numbers and booleans encoded as strings in tool arguments ([5dfbbc7](https://github.com/miguelangel-nubla/mcp-grocy/commit/5dfbbc799fdfde36255f6fcc3665e0113f36cf14))
7
+ * advertise tool parameter descriptions in tools/list ([0418bf5](https://github.com/miguelangel-nubla/mcp-grocy/commit/0418bf5be83428f19e52c2952e2f3e5bdd078d73))
8
+ * **tools:** normalize created_object_id and id to numbers in responses ([5f613d6](https://github.com/miguelangel-nubla/mcp-grocy/commit/5f613d6b6c87f860ac3a79e6d8a473a91d19d3a7))
2
9
 
3
10
 
11
+ ### Features
12
+
13
+ * add recipes_mealplan_add_note tool for meal plan notes with sections ([e80aa65](https://github.com/miguelangel-nubla/mcp-grocy/commit/e80aa651e9653bf765d361a4ebc3d285d325a23e)), closes [#2](https://github.com/miguelangel-nubla/mcp-grocy/issues/2)
14
+
15
+ ## [2.7.2](https://github.com/miguelangel-nubla/mcp-grocy/compare/v2.7.1...v2.7.2) (2026-09-10)
16
+
4
17
  ### Bug Fixes
5
18
 
6
- * add prepack script, update release configs, and fix docker workflows ([c464c05](https://github.com/miguelangel-nubla/mcp-grocy/commit/c464c054ab4f3f420647196ded7454c60f3702fc))
19
+ - add prepack script, update release configs, and fix docker workflows ([c464c05](https://github.com/miguelangel-nubla/mcp-grocy/commit/c464c054ab4f3f420647196ded7454c60f3702fc))
7
20
 
8
21
  ## [2.7.1](https://github.com/miguelangel-nubla/mcp-grocy/compare/v2.7.0...v2.7.1) (2026-09-10)
9
22
 
@@ -54,7 +54,7 @@ Transform your LLM into an intelligent household management assistant with focus
54
54
  ### 🛒 **Smart Shopping & Planning**
55
55
 
56
56
  - Maintain shopping lists with intelligent quantity management
57
- - Plan meals with recipe scheduling and fulfillment checking
57
+ - Plan meals with recipe scheduling, free-text notes per meal plan section, and fulfillment checking
58
58
  - Automatically add missing ingredients to shopping lists
59
59
  - Track shopping locations and optimize store visits
60
60
 
@@ -122,6 +122,18 @@ use_mcp_tool('mcp-grocy', 'recipes_mealplan_add_recipe', {
122
122
 
123
123
  Use **`recipes_mealplan_get_sections`** for valid `sectionId` values.
124
124
 
125
+ ### Add a note to the meal plan (no recipe)
126
+
127
+ ```typescript
128
+ use_mcp_tool('mcp-grocy', 'recipes_mealplan_add_note', {
129
+ day: '2024-07-01',
130
+ note: 'Leftovers from Sunday',
131
+ sectionId: 3,
132
+ });
133
+ ```
134
+
135
+ Same `sectionId` values as above (`-1` = Grocy's built-in "no section").
136
+
125
137
  ### Remove a meal plan entry
126
138
 
127
139
  ```typescript
@@ -130,7 +142,7 @@ use_mcp_tool('mcp-grocy', 'recipes_mealplan_delete_entry', {
130
142
  });
131
143
  ```
132
144
 
133
- Use **`recipes_mealplan_get`** to find `mealPlanEntryId`.
145
+ Use **`recipes_mealplan_get`** to find `mealPlanEntryId`. Works for recipe and note entries.
134
146
 
135
147
  ### Cook / consume recipe ingredients
136
148
 
@@ -6,6 +6,36 @@ import { z } from 'zod';
6
6
  function isStringTupleEnum(values) {
7
7
  return values.length > 0 && values.every((v) => typeof v === 'string');
8
8
  }
9
+ /**
10
+ * Some MCP clients serialize every tool argument as a string ("12", "true"). Accept those
11
+ * encodings for number/boolean properties: z.preprocess converts them before validation, and the
12
+ * JSON Schema advertised by tools/list still shows the wrapped type because Zod 4's toJSONSchema
13
+ * (io: 'input', which the SDK uses) resolves a preprocess pipe to its output schema — pinned by
14
+ * tests/tool-input-zod.test.ts. Only JSON number syntax and "true"/"false" are converted;
15
+ * anything else is passed through unchanged so the usual type error is still raised.
16
+ */
17
+ const JSON_NUMBER = /^-?(0|[1-9]\d*)(\.\d+)?([eE][+-]?\d+)?$/;
18
+ function numericStringToNumber(value) {
19
+ if (typeof value !== 'string')
20
+ return value;
21
+ const trimmed = value.trim();
22
+ if (!JSON_NUMBER.test(trimmed))
23
+ return value;
24
+ const parsed = Number(trimmed);
25
+ return Number.isFinite(parsed) ? parsed : value;
26
+ }
27
+ function booleanStringToBoolean(value) {
28
+ if (typeof value !== 'string')
29
+ return value;
30
+ const normalized = value.trim().toLowerCase();
31
+ if (normalized === 'true')
32
+ return true;
33
+ if (normalized === 'false')
34
+ return false;
35
+ return value;
36
+ }
37
+ const lenientNumber = () => z.preprocess(numericStringToNumber, z.number());
38
+ const lenientBoolean = () => z.preprocess(booleanStringToBoolean, z.boolean());
9
39
  function propertyToZod(prop, required) {
10
40
  const t = prop.type;
11
41
  let inner;
@@ -21,10 +51,10 @@ function propertyToZod(prop, required) {
21
51
  }
22
52
  case 'number':
23
53
  case 'integer':
24
- inner = z.number();
54
+ inner = lenientNumber();
25
55
  break;
26
56
  case 'boolean':
27
- inner = z.boolean();
57
+ inner = lenientBoolean();
28
58
  break;
29
59
  case 'array': {
30
60
  const items = prop.items;
@@ -35,10 +65,10 @@ function propertyToZod(prop, required) {
35
65
  inner = z.array(z.string());
36
66
  }
37
67
  else if (items?.type === 'number' || items?.type === 'integer') {
38
- inner = z.array(z.number());
68
+ inner = z.array(lenientNumber());
39
69
  }
40
70
  else if (items?.type === 'boolean') {
41
- inner = z.array(z.boolean());
71
+ inner = z.array(lenientBoolean());
42
72
  }
43
73
  else {
44
74
  inner = z.array(z.unknown());
@@ -62,7 +92,9 @@ function propertyToZod(prop, required) {
62
92
  default:
63
93
  inner = z.unknown();
64
94
  }
65
- return required ? inner : inner.optional();
95
+ // Keep the per-property description in the advertised JSON Schema (LLM clients read it).
96
+ const described = prop.description ? inner.describe(prop.description) : inner;
97
+ return required ? described : described.optional();
66
98
  }
67
99
  function objectPropsToZod(properties, requiredList) {
68
100
  const required = new Set(requiredList ?? []);
@@ -6,10 +6,43 @@ import { config } from '../config/index.js';
6
6
  import { ErrorHandler, ValidationError } from '../utils/errors.js';
7
7
  import { logger } from '../utils/logger.js';
8
8
  export class BaseToolHandler {
9
+ /**
10
+ * Normalizes response data so IDs (like created_object_id or entity id) are numeric.
11
+ */
12
+ normalizeResponseData(data) {
13
+ if (!data || typeof data !== 'object') {
14
+ return data;
15
+ }
16
+ if (Array.isArray(data)) {
17
+ return data.map((item) => this.normalizeResponseData(item));
18
+ }
19
+ if (Object.prototype.toString.call(data) !== '[object Object]') {
20
+ return data;
21
+ }
22
+ const normalized = {};
23
+ for (const [key, value] of Object.entries(data)) {
24
+ if (key === 'created_object_id' && value !== null && value !== undefined) {
25
+ const num = Number(value);
26
+ normalized[key] = Number.isInteger(num) && num > 0 ? num : value;
27
+ }
28
+ else if (key === 'id' && typeof value === 'string') {
29
+ const num = Number(value);
30
+ normalized[key] = Number.isInteger(num) && num > 0 ? num : value;
31
+ }
32
+ else if (value && typeof value === 'object') {
33
+ normalized[key] = this.normalizeResponseData(value);
34
+ }
35
+ else {
36
+ normalized[key] = value;
37
+ }
38
+ }
39
+ return normalized;
40
+ }
9
41
  /**
10
42
  * Create a standardized success result
11
43
  */
12
44
  createSuccess(data, message) {
45
+ const normalizedData = this.normalizeResponseData(data);
13
46
  let serializeStructured;
14
47
  try {
15
48
  serializeStructured = config?.server?.serialize_structured_to_content ?? false;
@@ -17,10 +50,10 @@ export class BaseToolHandler {
17
50
  catch {
18
51
  serializeStructured = false;
19
52
  }
20
- const textContent = serializeStructured && data !== undefined && data !== null
53
+ const textContent = serializeStructured && normalizedData !== undefined && normalizedData !== null
21
54
  ? message
22
- ? `${message}\n${this.safeStringify(data)}`
23
- : this.safeStringify(data)
55
+ ? `${message}\n${this.safeStringify(normalizedData)}`
56
+ : this.safeStringify(normalizedData)
24
57
  : message || 'Operation completed successfully';
25
58
  return {
26
59
  content: [
@@ -30,7 +63,7 @@ export class BaseToolHandler {
30
63
  },
31
64
  ],
32
65
  structuredContent: {
33
- data: data ?? null,
66
+ data: normalizedData ?? null,
34
67
  },
35
68
  };
36
69
  }
@@ -0,0 +1,64 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { BaseToolHandler } from './base.js';
3
+ class TestHandler extends BaseToolHandler {
4
+ testNormalize(data) {
5
+ return this.normalizeResponseData(data);
6
+ }
7
+ testSuccess(data, message) {
8
+ return this.createSuccess(data, message);
9
+ }
10
+ }
11
+ describe('BaseToolHandler normalization', () => {
12
+ const handler = new TestHandler();
13
+ it('normalizes created_object_id string to number', () => {
14
+ const input = { created_object_id: '1330' };
15
+ const output = handler.testNormalize(input);
16
+ expect(output).toEqual({ created_object_id: 1330 });
17
+ });
18
+ it('leaves created_object_id untouched if already a number', () => {
19
+ const input = { created_object_id: 1330 };
20
+ const output = handler.testNormalize(input);
21
+ expect(output).toEqual({ created_object_id: 1330 });
22
+ });
23
+ it('normalizes string id to number', () => {
24
+ const input = { id: '46', name: 'Arroz redondo' };
25
+ const output = handler.testNormalize(input);
26
+ expect(output).toEqual({ id: 46, name: 'Arroz redondo' });
27
+ });
28
+ it('normalizes nested objects and arrays', () => {
29
+ const input = {
30
+ list: { id: '1', name: 'Groceries' },
31
+ items: [
32
+ { id: '10', product: { id: '46', name: 'Rice' } },
33
+ { id: '11', product: { id: '55', name: 'Beans' } },
34
+ ],
35
+ };
36
+ const output = handler.testNormalize(input);
37
+ expect(output).toEqual({
38
+ list: { id: 1, name: 'Groceries' },
39
+ items: [
40
+ { id: 10, product: { id: 46, name: 'Rice' } },
41
+ { id: 11, product: { id: 55, name: 'Beans' } },
42
+ ],
43
+ });
44
+ });
45
+ it('does not touch barcodes, dates, or non-id fields', () => {
46
+ const input = {
47
+ id: '1',
48
+ barcode: '012345678905',
49
+ created_at: '2026-09-11 12:00:00',
50
+ note: '46',
51
+ };
52
+ const output = handler.testNormalize(input);
53
+ expect(output).toEqual({
54
+ id: 1,
55
+ barcode: '012345678905',
56
+ created_at: '2026-09-11 12:00:00',
57
+ note: '46',
58
+ });
59
+ });
60
+ it('createSuccess automatically applies normalization to structuredContent and textContent', () => {
61
+ const res = handler.testSuccess({ created_object_id: '1330' }, 'Created');
62
+ expect(res.structuredContent?.data).toEqual({ created_object_id: 1330 });
63
+ });
64
+ });
@@ -121,7 +121,7 @@ export const recipeToolDefinitions = [
121
121
  // ==================== MEAL PLANNING ====================
122
122
  {
123
123
  name: 'recipes_mealplan_get',
124
- description: '[RECIPES/MEALPLAN] Get your meal plan data from Grocy instance with corresponding recipe details. Returns planned meals for the requested date plus surrounding days for context. Use this to find out what recipes/meals are planned for a specific date (e.g., "what\'s for dinner tomorrow", "recipes for today", "meal plan for next week"). The returned data includes the id field (meal plan entry ID) which can be used with recipes_mealplan_delete_entry.',
124
+ description: '[RECIPES/MEALPLAN] Get your meal plan data from Grocy instance with corresponding recipe details. Returns planned entries for the requested date plus surrounding days for context. Each entry has a type: "recipe" (recipe_id + recipe_servings; names in recipes) or "note" (free text in note, no recipe); other values (e.g., "product") are not handled by these tools. section_id maps to the returned sections. Use this to find out what is planned for a specific date (e.g., "what\'s for dinner tomorrow", "recipes for today", "meal plan for next week"). The returned id field (meal plan entry ID) can be used with recipes_mealplan_delete_entry.',
125
125
  annotations: { readOnlyHint: true },
126
126
  inputSchema: {
127
127
  type: 'object',
@@ -140,7 +140,7 @@ export const recipeToolDefinitions = [
140
140
  },
141
141
  {
142
142
  name: 'recipes_mealplan_get_sections',
143
- description: '[RECIPES/MEALPLAN] **Read-only:** list meal plan section names/IDs (Breakfast, Dinner, …). Does not return planned meals or dates—use recipes_mealplan_get for the calendar. Needed before recipes_mealplan_add_recipe to pick sectionId; the row with id -1 and name null is Grocy\'s built-in "no section".',
143
+ description: '[RECIPES/MEALPLAN] **Read-only:** list meal plan section names/IDs (Breakfast, Dinner, …). Does not return planned meals or dates—use recipes_mealplan_get for the calendar. Needed before recipes_mealplan_add_recipe or recipes_mealplan_add_note to pick sectionId; the row with id -1 and name null is Grocy\'s built-in "no section".',
144
144
  annotations: { readOnlyHint: true },
145
145
  inputSchema: {
146
146
  type: 'object',
@@ -150,7 +150,7 @@ export const recipeToolDefinitions = [
150
150
  },
151
151
  {
152
152
  name: 'recipes_mealplan_add_recipe',
153
- description: '[RECIPES/MEALPLAN] **Write:** put a recipe on the calendar (date + section + servings). Not for listing sections (recipes_mealplan_get_sections) or viewing the plan (recipes_mealplan_get).',
153
+ description: '[RECIPES/MEALPLAN] **Write:** put a recipe on the calendar (date + section + servings). For free text without a recipe use recipes_mealplan_add_note. Not for listing sections (recipes_mealplan_get_sections) or viewing the plan (recipes_mealplan_get).',
154
154
  inputSchema: {
155
155
  type: 'object',
156
156
  properties: {
@@ -174,15 +174,37 @@ export const recipeToolDefinitions = [
174
174
  required: ['recipeId', 'day', 'servings', 'sectionId'],
175
175
  },
176
176
  },
177
+ {
178
+ name: 'recipes_mealplan_add_note',
179
+ description: '[RECIPES/MEALPLAN] **Write:** add a free-text note (e.g., "Leftovers", "Eating out") to a meal plan day and section—no recipe involved, nothing is consumed from stock. To plan an actual recipe use recipes_mealplan_add_recipe.',
180
+ inputSchema: {
181
+ type: 'object',
182
+ properties: {
183
+ day: {
184
+ type: 'string',
185
+ description: 'Day to add the note to in YYYY-MM-DD format (e.g., "2024-12-25").',
186
+ },
187
+ note: {
188
+ type: 'string',
189
+ description: 'Text shown on the meal plan for that day (e.g., "Leftovers from Sunday", "Dinner at grandma\'s"). Must not be empty.',
190
+ },
191
+ sectionId: {
192
+ type: 'number',
193
+ description: 'ID of the meal plan section (e.g., breakfast, lunch, dinner) to file the note under. Use recipes_mealplan_get_sections tool to discover available sections and their IDs. Use -1 for Grocy\'s built-in "no section"; if the user names no meal or section, use -1 rather than guessing.',
194
+ },
195
+ },
196
+ required: ['day', 'note', 'sectionId'],
197
+ },
198
+ },
177
199
  {
178
200
  name: 'recipes_mealplan_delete_entry',
179
- description: '[RECIPES/MEALPLAN] Delete a specific recipe entry from the meal plan. Use recipes_mealplan_get to find the mealPlanEntryId of the entry you want to remove.',
201
+ description: '[RECIPES/MEALPLAN] Delete one meal plan entry of any type (recipe, note, product) by its mealPlanEntryId. Use recipes_mealplan_get to find the mealPlanEntryId of the entry you want to remove.',
180
202
  inputSchema: {
181
203
  type: 'object',
182
204
  properties: {
183
205
  mealPlanEntryId: {
184
206
  type: 'number',
185
- description: 'ID of the specific meal plan entry to delete. Use recipes_mealplan_get to find the correct entry ID.',
207
+ description: 'ID of the specific meal plan entry to delete (works for any entry type). Use recipes_mealplan_get to find the correct entry ID.',
186
208
  },
187
209
  },
188
210
  required: ['mealPlanEntryId'],
@@ -259,7 +281,7 @@ export const recipeToolDefinitions = [
259
281
  : {
260
282
  mealPlanEntryId: {
261
283
  type: 'number',
262
- description: `ID of the meal plan entry. Must be a recipe entry; note and product entries cannot be completed with this tool.${allowAlreadyDone ? '' : ' Note: This will fail if the meal plan entry is already marked as done (done=1).'}`,
284
+ description: `ID of the meal plan entry. Must be a recipe entry (type 'recipe' in recipes_mealplan_get); note and product entries cannot be completed with this tool.${allowAlreadyDone ? '' : ' Note: This will fail if the meal plan entry is already marked as done (done=1).'}`,
263
285
  },
264
286
  }),
265
287
  stockAmounts: {
@@ -121,6 +121,20 @@ export class RecipeToolHandlers extends BaseToolHandler {
121
121
  return this.createSuccess(result, 'Recipe added to meal plan successfully');
122
122
  });
123
123
  };
124
+ /**
125
+ * Add free-text note to meal plan
126
+ */
127
+ addNoteToMealPlan = async (args) => {
128
+ return this.executeToolHandler(async () => {
129
+ const { day, note, sectionId } = args || {};
130
+ this.validateRequired({ day, note, sectionId }, ['day', 'note', 'sectionId']);
131
+ if (typeof note !== 'string' || note.trim() === '') {
132
+ throw new ValidationError('note must be non-empty text', 'recipes_mealplan_add_note');
133
+ }
134
+ const result = await this.createMealPlanEntry(day, sectionId, { type: 'note', note }, 'recipes_mealplan_add_note');
135
+ return this.createSuccess(result, 'Note added to meal plan successfully');
136
+ });
137
+ };
124
138
  /**
125
139
  * Cook recipe - consume ingredients from stock
126
140
  */
@@ -241,6 +255,7 @@ export class RecipeToolHandlers extends BaseToolHandler {
241
255
  simplifiedMealPlanByDate[entryDate].push({
242
256
  id: entry.id,
243
257
  day: entry.day,
258
+ type: entry.type,
244
259
  section_id: entry.section_id,
245
260
  recipe_id: entry.recipe_id,
246
261
  recipe_servings: entry.recipe_servings,
@@ -275,14 +290,14 @@ export class RecipeToolHandlers extends BaseToolHandler {
275
290
  });
276
291
  };
277
292
  /**
278
- * Delete recipe from meal plan
293
+ * Delete a meal plan entry (any type)
279
294
  */
280
- deleteRecipeFromMealPlan = async (args) => {
295
+ deleteMealPlanEntry = async (args) => {
281
296
  return this.executeToolHandler(async () => {
282
297
  const { mealPlanEntryId } = args || {};
283
298
  this.validateRequired({ mealPlanEntryId }, ['mealPlanEntryId']);
284
299
  const result = await this.apiCall(`/objects/meal_plan/${mealPlanEntryId}`, 'DELETE');
285
- return this.createSuccess(result, 'Recipe deleted from meal plan successfully');
300
+ return this.createSuccess(result, 'Meal plan entry deleted successfully');
286
301
  });
287
302
  };
288
303
  // ==================== RECIPE CREATION ====================
@@ -18,7 +18,8 @@ export const recipeModule = {
18
18
  recipes_mealplan_get: handlers.getMealPlan,
19
19
  recipes_mealplan_get_sections: handlers.getMealPlanSections,
20
20
  recipes_mealplan_add_recipe: handlers.addRecipeToMealPlan,
21
- recipes_mealplan_delete_entry: handlers.deleteRecipeFromMealPlan,
21
+ recipes_mealplan_add_note: handlers.addNoteToMealPlan,
22
+ recipes_mealplan_delete_entry: handlers.deleteMealPlanEntry,
22
23
  // Recipe Cooking
23
24
  recipes_cooking_consume: handlers.consumeRecipe,
24
25
  recipes_cooking_complete: handlers.cookedSomething,
package/build/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // Auto-generated file - DO NOT MODIFY
2
- export const VERSION = '2.7.2';
2
+ export const VERSION = '2.8.0';
3
3
  export const PACKAGE_NAME = 'mcp-grocy';
4
4
  export const SERVER_NAME = 'mcp-grocy';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-grocy",
3
- "version": "2.7.2",
3
+ "version": "2.8.0",
4
4
  "description": "Model Context Protocol (MCP) server for Grocy integration",
5
5
  "license": "MIT",
6
6
  "type": "module",