Mealie
Interact with your Mealie recipe database to manage and find recipes.
Install
Install and configure the MCP from https://github.com/rldiao/mealie-mcp-server now. Follow the repository's installation instructions, ask me for anything you can't complete yourself, and verify its tools load.Mealie MCP Server
A Model Context Protocol (MCP) server that connects AI assistants to your Mealie recipe database through clients such as Claude Desktop.
Contents
- Features
- Quick Start
- Configuration
- Remote Access
- Docker
- Usage Examples
- Available Tools
- Development
- Important Notes
- Support and Contributing
- License and Credits
Features
- Recipes: Create, read, update, import, duplicate, and delete recipes.
- Search: Filter by text, categories, tags, and tools with AND/OR logic.
- Images and assets: Upload recipe images and files, or set images from URLs.
- Nutrition and display: Set per-serving nutrition and recipe visibility
settings such as
showAssetsandshowNutrition. - Ingredients: Resolve free-text ingredients against Mealie's food and unit vocabulary.
- Shopping lists: Manage lists and items, perform bulk operations, and add recipe ingredients with quantity scaling.
- Organization: Manage categories, tags, foods, units, and recipe tools; find unused categories and tags.
- Meal planning: View, create, update, and delete meal plan entries, create multiple entries, and mark recipes as made today.
Quick Start
Prerequisites
- Python 3.12+
- A running Mealie instance and an API key from your account settings
- Package manager uv
Installation
Option 1: Using the MCP SDK CLI (Recommended)
Clone the repository, then install the server into Claude Desktop with the
mcp command supplied by the Python MCP SDK (no standalone fastmcp package
is needed):
git clone https://github.com/rldiao/mealie-mcp-server.git
cd mealie-mcp-server
uv sync --locked
uv run mcp install src/server.py --with-editable . \
--env-var MEALIE_BASE_URL=https://your-mealie-instance.com \
--env-var MEALIE_API_KEY=your-mealie-api-key
Option 2: Using uvx
Add this to your MCP client's configuration to run directly from GitHub without
cloning (in Claude Desktop, use claude_desktop_config.json):
{
"mcpServers": {
"mealie-mcp-server": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/rldiao/mealie-mcp-server",
"mealie-mcp-server"
],
"env": {
"MEALIE_BASE_URL": "https://your-mealie-instance.com",
"MEALIE_API_KEY": "your-mealie-api-key"
}
}
}
}
Restart Claude Desktop to load the server.
Configuration
Set environment variables in your MCP client configuration or shell. For a local
checkout, you can also copy .env.template to .env and fill in
your instance details. Never commit your API key.
| Variable | Default | Description |
|---|---|---|
MEALIE_BASE_URL | Required | Mealie base URL, including protocol and port if needed |
MEALIE_API_KEY | Required | API key from your Mealie account settings |
MEALIE_ENABLE_AI_IMPORT | false | Opt in to AI recipe import; accepts true/false (case-insensitive) |
MCP_TRANSPORT | stdio | stdio, streamable-http, or legacy sse |
MCP_HOST | 127.0.0.1 | HTTP bind address; use 0.0.0.0 in containers |
MCP_PORT | 8765 | HTTP port, from 1 to 65535 |
LOG_LEVEL | INFO | DEBUG, INFO, WARNING, ERROR, or CRITICAL |
Remote Access
The default stdio transport is for local clients. To serve HTTP clients, configure your Mealie credentials as described above and run from the checkout:
export MCP_TRANSPORT=streamable-http
export MCP_HOST=127.0.0.1
export MCP_PORT=8765
uv run mealie-mcp-server
The server will expose its MCP endpoint at http://<host>:<port>/mcp.
Security: HTTP transports have no built-in authentication. Anyone who can reach the endpoint can use the configured Mealie credentials through its tools. Keep it on a trusted interface; for remote access, use a reverse proxy that enforces authentication and HTTPS.
Docker
The Dockerfile runs the server as a persistent container.
Build
docker build -t mealie-mcp-server .
Standalone
docker run -d \
--name mealie-mcp \
-e MEALIE_BASE_URL=http://your-mealie-host:9000 \
-e MEALIE_API_KEY=your-mealie-api-key \
-e MCP_TRANSPORT=streamable-http \
-e MCP_HOST=0.0.0.0 \
-e MCP_PORT=8765 \
-p 127.0.0.1:8765:8765 \
mealie-mcp-server
The port is published only on the host's loopback interface. See Remote Access before making it reachable remotely.
Docker Compose
Add this service to the Compose file that runs Mealie. The example assumes that
the Mealie service is named mealie and both services use a network named
mealie_net, defined in that Compose file. Set MEALIE_API_KEY in the shell or
Compose .env file.
services:
mealie-mcp:
build: .
container_name: mealie-mcp
restart: unless-stopped
environment:
MEALIE_BASE_URL: http://mealie:9000
MEALIE_API_KEY: ${MEALIE_API_KEY}
MCP_TRANSPORT: streamable-http
MCP_HOST: "0.0.0.0"
MCP_PORT: "8765"
expose:
- "8765"
networks:
- mealie_net
expose does not publish a host port. Connect a reverse proxy on the same network
for remote access, following the HTTP security guidance.
Usage Examples
"Search for chicken recipes"
"Create a new recipe for pasta carbonara"
"Mark the meatloaf recipe as made today"
"Create a shopping list for this week"
"Add all ingredients from the lasagna recipe to my shopping list"
"Plan chicken soup for lunch on Friday"
See Usage Examples for detailed workflows and troubleshooting.
Available Tools
Recipe Tools (12 operations)
get_recipes- List/search recipes with advanced filteringget_recipe- Get complete recipe details, or a summary withconcise=truecreate_recipe- Create a recipe; only the name is required, with optional ingredients, instructions, metadata, nutrition, and display settingsimport_recipe_from_url- Import a recipe from a web pageupdate_recipe- Update content or metadata, including nutrition and display settings; omitted fields are preserved, and empty lists clear contentduplicate_recipe- Clone a recipemark_recipe_last_made- Update last made timestampset_recipe_image_from_url- Set image from URLupload_recipe_image_file- Upload image fileupload_recipe_asset_file- Upload document/assetupdate_recipe_categories_and_tags- Replace or clear categories, tags, or both using IDsdelete_recipe- Delete recipe
Shopping List Tools (15 operations)
get_shopping_lists- List all shopping listscreate_shopping_list- Create new listget_shopping_list- Get list by IDupdate_shopping_list- Rename a list while preserving other fieldsdelete_shopping_list- Delete listadd_recipe_to_shopping_list- Add recipe ingredientsremove_recipe_from_shopping_list- Remove recipe ingredientsget_shopping_list_items- List all itemsget_shopping_list_item- Get item by IDcreate_shopping_list_item- Create single itemcreate_shopping_list_items_bulk- Create multiple itemsupdate_shopping_list_item- Update item (preserves fields)update_shopping_list_items_bulk- Update multiple itemsdelete_shopping_list_item- Delete single itemdelete_shopping_list_items_bulk- Delete multiple items
Category Tools (6 operations)
get_categories- List/search categoriesget_empty_categories- Find unused categoriescreate_category- Create new categoryget_category- Get by exactly one ofcategory_idorcategory_slugupdate_category- Update categorydelete_category- Delete category
Tag Tools (6 operations)
get_tags- List/search tagsget_empty_tags- Find unused tagscreate_tag- Create new tagget_tag- Get by exactly one oftag_idortag_slugupdate_tag- Update tagdelete_tag- Delete tag
Food Tools (5 operations)
get_foods- List/search foods (resolve IDs for structured ingredients)create_food- Create a new foodget_food- Get by IDupdate_food- Update fooddelete_food- Delete food
Unit Tools (5 operations)
get_units- List/search unitscreate_unit- Create a new unitget_unit- Get by IDupdate_unit- Update unitdelete_unit- Delete unit
Kitchen Tools (5 operations)
get_tools- List/search recipe tools (includeshouseholdsWithTool)create_tool- Create a new toolget_tool- Get by exactly one oftool_idortool_slugupdate_tool- Update tooldelete_tool- Delete tool
Parser Tools (1 operation)
parse_ingredients- Resolve one or more ingredient lines in one request; always returns a list
Meal Plan Tools (6 operations)
get_all_mealplans- List meal planscreate_mealplan- Create meal plan entrycreate_mealplan_bulk- Create multiple entriesupdate_mealplan- Update an entry while preserving omitted fieldsdelete_mealplan- Delete an entryget_todays_mealplan- Get today's meals
Total: 61 tools
With MEALIE_ENABLE_AI_IMPORT=true, import_recipe_with_ai adds one optional
recipe operation: 62 total tools, including 13 recipe tools. It is absent
from discovery and cannot be called when disabled.
Migrating consolidated tools (breaking change)
Redundant MCP names have been removed, not retained as aliases. Refresh your client's tool list and update saved calls:
| Removed tool | Replacement |
|---|---|
create_recipe_full | create_recipe with the same arguments |
get_recipe_detailed | get_recipe (full details by default) |
get_recipe_concise | get_recipe with concise=true |
patch_recipe | update_recipe with the same arguments |
set_recipe_categories | update_recipe_categories_and_tags with category_ids |
set_recipe_tags | update_recipe_categories_and_tags with tag_ids |
get_category_by_slug | get_category with category_slug |
get_tag_by_slug | get_tag with tag_slug |
get_tool_by_slug | get_tool with tool_slug |
parse_ingredient | parse_ingredients(ingredients=[...]); read the first result |
Existing create_recipe and update_recipe calls remain supported. Recipe
updates can now combine content and metadata, with omitted or null fields left
unchanged. Ingredient and instruction lists replace only the provided fields.
Nutrition remains a whole-object replacement, while settings are merged.
Distinct operations remain separate: single and bulk writes have different response/failure contracts; paginated lists differ from individual lookups, unused-organizer queries, and today's meal plans. Recipe URL import, image URL scraping, and file uploads also perform different operations.
Optional AI recipe import
Set MEALIE_ENABLE_AI_IMPORT=true in your MCP client's environment, shell, or
local .env. Restart the server and refresh the client's tool list. This applies
to stdio, SSE, and Streamable HTTP. Offline SDK discovery remains configuration-
and network-free, listing only default tools; optional registration occurs at
runtime startup (or when passing an explicit enabled ServerConfig).
import_recipe_with_ai requires Mealie 3.23.0+ and a default AI provider
configured for the API user's group. It accepts any combination of:
content: plain text, raw HTML, or JSON; also used for corrections or notes.url: an HTTP(S) recipe or video URL, fetched by Mealie and saved as the source.image_paths: ordered image paths accessible to the MCP server's filesystem, not a remote caller's computer. Multiple photos become one recipe; the first becomes its cover image.
At least one nonblank source is required. Sources are combined, with pasted
content taking precedence when they disagree. Optional translate_language
requests translation. create_new_organizers defaults to false: matching
existing tags, categories, and kitchen tools may be assigned, but new ones are
created only when explicitly requested.
Before each import the server reads /api/groups/self to check aiEnabled and,
for photos, imageProviderEnabled. Missing/malformed capabilities or a failed
lookup produce an explicit error, not a silent disabled result. Video detection
and the audio-provider requirement are handled by Mealie. These checks establish
configuration, not provider connectivity, credentials, or available quota.
This tool immediately creates and saves a recipe. Source material is processed
by Mealie's configured AI providers and may incur charges. Review the returned
recipe for accuracy. The import has a 300-second read timeout; other API calls
retain their existing timeouts. No imports are automatically retried. After a
timeout or connection failure, check Mealie before retrying or switching tools:
creation may already have succeeded. If the follow-up fetch fails, the error
includes created_slug and stage; retrieve that recipe rather than importing again.
Choose the tool according to the task:
| Task | Tool |
|---|---|
| Ordinary recipe webpage | import_recipe_from_url |
| Unstructured text, photos, video, combined sources, translation, or explicit AI import | import_recipe_with_ai (opt-in) |
| Save already-composed ingredients and instructions | create_recipe |
| Attach a photo to an existing recipe without extracting content | upload_recipe_image_file |
The opt-in controls only this new tool. It does not disable Mealie's own AI fallback for URL scraping or other existing AI features. See Mealie's AI import documentation and usage examples.
Development
Setup
After cloning the repository, install development dependencies:
uv sync --locked --extra dev
For manual testing, configure your Mealie instance:
cp .env.template .env
# Edit .env with your Mealie instance details
Launch the MCP Inspector:
uv run mcp dev src/server.py
Run the offline checks; these do not require a Mealie instance or credentials:
uv run ruff check src tests
uv run pytest -q
Project Structure
| Path | Purpose |
|---|---|
src/mealie/ | HTTP client and API mixins |
src/tools/ | FastMCP tool definitions and registration |
src/models/ | Pydantic request and response models |
src/server.py | Configuration, lifecycle, and entry point |
src/prompts.py | MCP prompts |
tests/ | Offline tests and fixtures |
Repository conventions are in AGENTS.md, with focused guidance for source code and tests.
The automated suite uses fake HTTP responses and includes local HTTP-transport checks. It does not replace compatibility testing against your deployed Mealie version.
Important Notes
The calls below use Python-style notation to illustrate MCP tool arguments; they are not standalone Python scripts.
Filtering by Tags and Categories
When filtering recipes, you must use slugs or UUIDs, not display names:
Use get_tags() or get_categories() first to find the correct slugs:
get_recipes(tags=["quick-meals", "healthy"])
For example, pass quick-meals, not the display name Quick Meals.
Nutrition Is Replaced, Not Merged
Mealie replaces the whole nutrition object on write. update_recipe follows
suit, so pass every value you want to keep:
# Clears every nutrition value except fat.
update_recipe(slug="...", nutrition={"fatContent": "12"})
Parsing Ingredients in Bulk
Resolving ingredients by hand costs one to two get_foods / get_units calls
each. parse_ingredients does a whole recipe in one request and returns results
that can be handed straight to create_recipe:
parse_ingredients(ingredients=["1/4 cup chopped onion", "2 large eggs"])
# -> [{"input": "1/4 cup chopped onion", "confidence": 0.99, "quantity": 0.25,
# "unit": {"id": "...", "name": "cup"},
# "food": {"id": "...", "name": "onion"}, "note": "chopped"}, ...]
A null unit or food means your instance has no matching entry; create one
with create_food / create_unit, or leave the text in the note. Pass
verbose=True for Mealie's full response including per-field confidences.
Uploaded Assets and Nutrition Can Be Stored but Hidden
A recipe's settings object controls what the UI renders. showAssets and
showNutrition gate the assets and nutrition cards, so an asset uploaded with
upload_recipe_asset_file can be present in the API response and still be
invisible in the web UI. Flip the toggle with:
update_recipe(slug="...", settings={"showAssets": True})
Mealie seeds a new recipe's settings from the household preferences
(recipeShowAssets, recipeShowNutrition, ...), so the defaults differ per
instance. Check rather than assume.
Only the toggles you pass are changed. The tool reads the recipe's current settings and sends the merged object, because Mealie does not reliably preserve toggles omitted from a settings PATCH.
Field Preservation
When updating shopping list items, both single and bulk updates fetch the current records and preserve omitted fields. You only need to specify the fields you want to change:
# Only updates 'checked' field, preserves note, quantity, etc.
update_shopping_list_item(item_id="...", checked=True)
Bulk shopping inputs accept snake_case names such as shopping_list_id and
Mealie's camelCase names such as shoppingListId. Conflicting aliases and
duplicate IDs in a bulk update are rejected before writing.
Meal Plan Validation and Clearing
Meal dates must use YYYY-MM-DD, and entry types must be breakfast, lunch,
dinner, or side. Creation requires a recipe or a nonblank title. Bulk meal
plans are validated in full before any entries are created.
Omitted update fields remain unchanged. To remove an existing recipe link,
use update_mealplan(entry_id="...", clear_recipe=True, title="Leftovers").
Do not combine clear_recipe with a replacement recipe_id.
Recovering from Partially Completed Writes
Recipe creation/population and bulk meal-plan creation require multiple API requests and are not atomic. If a later request fails, the tool error includes recovery information identifying completed work. Inspect that information and the current Mealie state rather than blindly retrying the entire operation. A failed or timed-out request may have completed remotely.
Support and Contributing
- Check the changelog for changes and migration notes.
- Review the usage guide and Mealie documentation.
- Report problems through GitHub issues.
- For pull requests, follow the development workflow and include tests for behavior changes.
License and Credits
Licensed under the MIT License.
- Mealie - The recipe management system
- Python MCP SDK - SDK and bundled FastMCP server
- Model Context Protocol - Protocol documentation
- Claude Desktop
