Skip to main content
Glama
README.md
# grocy-mcp (Grocy MCP connector)

MCP connector for a [Grocy](https://github.com/grocy/grocy) instance. It speaks the Grocy REST API over stdio and over stateless Streamable HTTP on localhost.

Grocy is MIT software. Self-host it. This connector does not grant any right to the Grocy name, and it does not imply endorsement.

This connector is MIT. It is a BYO-key client for your own instance.

The connector covers all 74 paths (87 operations) in `grocy.openapi.json`. Stock mutations, chores, tasks, batteries, recipes, meal plan, equipment, userobjects, userfields, files, users, and system endpoints are included.

## Setup

```bash
npm install
npm run ci
npm start
npm run start:http
```

`npm start` speaks stdio. `npm run start:http` serves Streamable HTTP at `http://127.0.0.1:3000/mcp` and `GET /health`. HTTP mode has no authentication. Keep it on localhost.

Create an API key in Grocy under Manage API keys. The connector sends it as `GROCY-API-KEY` and never prints it.

```json
{
  "mcpServers": {
    "grocy": {
      "command": "node",
      "args": ["/workspace/connectors/grocy/dist/index.js"],
      "env": {
        "GROCY_URL": "http://127.0.0.1:5056",
        "GROCY_API_KEY": "...",
        "GROCY_ALLOW_WRITES": "false",
        "GROCY_CONTACT": "you@example.com"
      }
    }
  }
}
```

A trailing `/api` on `GROCY_URL` is stripped.

Docker (HTTP, no authentication, localhost only):

```bash
docker build -t grocy-mcp .
docker run -p 3000:3000 \
  -e GROCY_URL=http://host.docker.internal:5056 \
  -e GROCY_API_KEY=... \
  grocy-mcp
```

Do not put the API key in the image.

## Tools

Generic entity CRUD (`grocy_objects_*`) is how you create and edit products, recipes, chores, tasks, batteries, equipment, meal plan rows, shopping lists, userobjects, userfields, and the other ExposedEntity values.

| Tool                                       | Call                                                                                    |
| ------------------------------------------ | --------------------------------------------------------------------------------------- |
| `grocy_system_info`                        | `GET /api/system/info`                                                                  |
| `grocy_system_db_changed_time`             | `GET /api/system/db-changed-time`                                                       |
| `grocy_system_config`                      | `GET /api/system/config`                                                                |
| `grocy_system_time`                        | `GET /api/system/time`                                                                  |
| `grocy_system_localization`                | `GET /api/system/localization-strings`                                                  |
| `grocy_system_log_missing_localization`    | `POST /api/system/log-missing-localization`                                             |
| `grocy_objects_list`                       | `GET /api/objects/{entity}`                                                             |
| `grocy_objects_get`                        | `GET /api/objects/{entity}/{objectId}`                                                  |
| `grocy_objects_create`                     | `POST /api/objects/{entity}`                                                            |
| `grocy_objects_update`                     | `PUT /api/objects/{entity}/{objectId}`                                                  |
| `grocy_objects_delete`                     | `DELETE /api/objects/{entity}/{objectId}`                                               |
| `grocy_userfields_get`                     | `GET /api/userfields/{entity}/{objectId}`                                               |
| `grocy_userfields_put`                     | `PUT /api/userfields/{entity}/{objectId}`                                               |
| `grocy_files_get`                          | `GET /api/files/{group}/{fileName}`                                                     |
| `grocy_files_put`                          | `PUT /api/files/{group}/{fileName}`                                                     |
| `grocy_files_delete`                       | `DELETE /api/files/{group}/{fileName}`                                                  |
| `grocy_users_list`                         | `GET /api/users`                                                                        |
| `grocy_users_create`                       | `POST /api/users`                                                                       |
| `grocy_users_update`                       | `PUT /api/users/{userId}`                                                               |
| `grocy_users_delete`                       | `DELETE /api/users/{userId}`                                                            |
| `grocy_user_permissions`                   | `/api/users/{userId}/permissions` with action `get`, `add`, `replace`                   |
| `grocy_current_user`                       | `GET /api/user`                                                                         |
| `grocy_user_settings`                      | `/api/user/settings` with action `list`, `get`, `put`, `delete`                         |
| `grocy_stock_overview`                     | `GET /api/stock`                                                                        |
| `grocy_stock_volatile`                     | `GET /api/stock/volatile`                                                               |
| `grocy_stock_entry`                        | `/api/stock/entry/{entryId}` with action `get`, `update`, `printlabel`                  |
| `grocy_stock_product`                      | product stock reads plus `copy` and `printlabel`                                        |
| `grocy_stock_add`                          | `POST .../add` by `product_id` or `barcode`                                             |
| `grocy_stock_consume`                      | `POST .../consume` by `product_id` or `barcode`                                         |
| `grocy_stock_transfer`                     | `POST .../transfer` by `product_id` or `barcode`                                        |
| `grocy_stock_inventory`                    | `POST .../inventory` by `product_id` or `barcode`                                       |
| `grocy_stock_open`                         | `POST .../open` by `product_id` or `barcode`                                            |
| `grocy_stock_merge_products`               | `POST /api/stock/products/{keep}/merge/{remove}`                                        |
| `grocy_stock_product_by_barcode`           | `GET /api/stock/products/by-barcode/{barcode}`                                          |
| `grocy_stock_location_entries`             | `GET /api/stock/locations/{locationId}/entries`                                         |
| `grocy_shopping_list`                      | shopping list add-missing, add-overdue, add-expired, clear, add_product, remove_product |
| `grocy_stock_booking`                      | get or undo a stock booking                                                             |
| `grocy_stock_transaction`                  | get or undo a stock transaction                                                         |
| `grocy_barcode_lookup`                     | `GET /api/stock/barcodes/external-lookup/{barcode}`                                     |
| `grocy_recipe_fulfillment`                 | one recipe or all recipes                                                               |
| `grocy_recipe_consume`                     | `POST /api/recipes/{recipeId}/consume`                                                  |
| `grocy_recipe_add_missing_to_shoppinglist` | add missing recipe products to a shopping list                                          |
| `grocy_recipe_copy`                        | `POST /api/recipes/{recipeId}/copy`                                                     |
| `grocy_recipe_printlabel`                  | print a recipe Grocycode                                                                |
| `grocy_chores_list`                        | `GET /api/chores`                                                                       |
| `grocy_chore_get`                          | `GET /api/chores/{choreId}`                                                             |
| `grocy_chore_execute`                      | `POST /api/chores/{choreId}/execute`                                                    |
| `grocy_chore_undo_execution`               | undo a chore execution                                                                  |
| `grocy_chores_calculate_assignments`       | recalculate next assignments                                                            |
| `grocy_chore_printlabel`                   | print a chore Grocycode                                                                 |
| `grocy_chore_merge`                        | merge two chores                                                                        |
| `grocy_batteries_list`                     | `GET /api/batteries`                                                                    |
| `grocy_battery_get`                        | `GET /api/batteries/{batteryId}`                                                        |
| `grocy_battery_charge`                     | track a charge cycle                                                                    |
| `grocy_battery_undo_charge`                | undo a charge cycle                                                                     |
| `grocy_battery_printlabel`                 | print a battery Grocycode                                                               |
| `grocy_tasks_list`                         | `GET /api/tasks`                                                                        |
| `grocy_task_complete`                      | complete a task                                                                         |
| `grocy_task_undo`                          | mark a task not done                                                                    |
| `grocy_calendar_ical`                      | `GET /api/calendar/ical`                                                                |
| `grocy_calendar_sharing_link`              | `GET /api/calendar/ical/sharing-link`                                                   |
| `grocy_print_shoppinglist`                 | thermal print a shopping list                                                           |

`grocy_files_*` takes the plain `file_name`. The connector base64-encodes it for Grocy.

## Environment

| Variable              | Default                   | Role                                                                                 |
| --------------------- | ------------------------- | ------------------------------------------------------------------------------------ |
| `GROCY_URL`           | `https://example.invalid` | Instance origin. No userinfo, query, or hash. A trailing `/api` is stripped          |
| `GROCY_API_KEY`       | unset                     | Required for an upstream call. At least 8 characters. Never printed                  |
| `GROCY_ALLOW_WRITES`  | off                       | The literal `true` enables writes. Any other value keeps writes as a blocked preview |
| `GROCY_CONTACT`       | `contact@example.com`     | Contact inside the User-Agent. Must not contain the API key                          |
| `GROCY_PER_MINUTE`    | `30`                      | Local sliding-window cap                                                             |
| `GROCY_CACHE_TTL_SEC` | `60`                      | TTL for successful reads. `0` disables the cache                                     |
| `GROCY_TIMEOUT_MS`    | `20000`                   | Upstream timeout                                                                     |
| `MCP_TRANSPORT`       | `stdio`                   | `stdio` or `http`. `--http` forces HTTP                                              |
| `PORT`                | `3000`                    | HTTP listen port                                                                     |

Invalid values are reported by field name and issue code. The rejected value is not included.

## Safety

A write tool returns a dry-run preview when `confirm` is omitted. The preview is the method, path, query, and body that would be sent.

`confirm` must be the boolean `true`. `false` and the string `"true"` are rejected.

When `confirm` is `true` and `GROCY_ALLOW_WRITES` is not `true`, the tool still returns the preview, sets `blocked` to true, and does not call the instance.

Writes include POST, PUT, DELETE, stock add/consume/transfer/inventory/open/undo, chore execute, file upload and delete, printlabel, thermal print, and barcode lookup with `add=true`.

The API key is removed from tool results, error text, and logs, including its URL-encoded form. It is refused in the query string, the base URL, the User-Agent, and a JSON request body. Password fields are redacted. Absolute server filesystem paths are dropped.

## Licence

Grocy is MIT (https://github.com/grocy/grocy). This connector is MIT.

## License

MIT, see [LICENSE](LICENSE). This is an independent, unofficial connector and is not endorsed by the Grocy project or its owners.

grocy.openapi.json is from grocy/grocy (MIT, Copyright (c) Bernd Bestel).

TDQS

B3/5.0

Scored across 62 tools

Disambiguation3/5

Most tools target distinct domain actions, but there is meaningful overlap: grocy_stock_transaction and grocy_stock_booking both expose booking-like get/undo operations, and generic grocy_objects_list/get/create/update/delete duplicate entity-specific tools for chores, batteries, tasks, and others. The descriptions help, but an agent still has multiple plausible paths for several operations.

Naming Consistency4/5

Tool names consistently use snake_case with a grocy_ prefix and generally follow a domain/action or domain/entity pattern. Minor inconsistency comes from multi-action aggregate tools like grocy_stock_product and grocy_stock_entry that omit the action from the name, but the overall convention is predictable.

Tool Count2/5

At 62 tools, the surface is very heavy for an agent to navigate and includes several aggregate tools that could absorb more actions. While Grocy is a broad domain, the count far exceeds typical well-scoped sets and increases selection burden.

Completeness4/5

The tool set covers a wide range of Grocy domains including stock, recipes, chores, batteries, tasks, users, files, calendar, printing, and system operations. Generic object CRUD fills many gaps for entities like equipment and meal plans, though reliance on generic operations rather than dedicated tools leaves minor gaps in explicit lifecycle coverage.

Maintenance

ActivityMaintained
ResponsivenessNo issues