mealie-mcp

mealie-mcp

A read-only MCP server for Mealie that enables searching recipes, managing shopping lists, meal plans, and retrieving household/instance info via tools. Supports secure per-user authentication and multiple Mealie instances.

Category
访问服务器

README

mealie-mcp

A Model Context Protocol server for Mealie, built with FastMCP and served over the Streamable HTTP transport. Ships as a Docker container.

It exposes tools only — no MCP resources or prompts. It is read-only by default; write tools can be enabled with MEALIE_READONLY=false.

How auth works

There are two independent credentials:

Credential Header Purpose
MCP endpoint token Authorization: Bearer <token> A static secret (set via MCP_AUTH_TOKEN) that gates the server. Requests without a valid token are rejected with 401.
Mealie API token X-Mealie-Token: <token> Supplied per request by each client. The server forwards it to Mealie as a bearer token, so one server can serve many Mealie users.

Optionally, a client can target a different Mealie instance per request with the X-Mealie-Url: https://other-mealie.example.com header (otherwise MEALIE_BASE_URL is used).

Get a Mealie API token from your Mealie profile: Profile → Manage API Tokens.

Tools

Read tools (always available)

Recipessearch_recipes, get_recipe, get_recipe_suggestions Reference datalist_categories, list_tags, list_tools, list_foods, list_units, list_cookbooks Householdget_shopping_lists, get_shopping_list, get_meal_plan, get_todays_meals Instanceget_current_user, get_app_info

Write tools (only when MEALIE_READONLY=false)

Recipescreate_recipe_from_url, create_recipe, update_recipe, delete_recipe, mark_recipe_made Shoppingadd_shopping_item, set_shopping_item_checked, add_recipe_to_shopping_list Meal planscreate_mealplan_entry, delete_mealplan_entry

Write tools respect the per-request Mealie token's own permissions, so a read-only Mealie token can never mutate data even when write tools are enabled.

Run with Docker

cp .env.example .env
# edit .env: set MCP_AUTH_TOKEN (a long random secret) and MEALIE_BASE_URL
docker compose up --build -d

The MCP endpoint is then available at http://<host>:8000/mcp, with an unauthenticated liveness probe at http://<host>:8000/healthz.

The endpoint token is the only thing standing between the internet and your Mealie instance. Put the server behind a reverse proxy with TLS, or on a private network, and use a long random MCP_AUTH_TOKEN.

Run locally (without Docker)

pip install -r requirements.txt
export MCP_AUTH_TOKEN="a-long-random-secret"
export MEALIE_BASE_URL="https://mealie.example.com"
python main.py

Connecting a client

Point your MCP client at the Streamable HTTP endpoint and send both headers. Example with the FastMCP client:

from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

transport = StreamableHttpTransport(
    url="http://localhost:8000/mcp",
    headers={
        "Authorization": "Bearer <your MCP_AUTH_TOKEN>",
        "X-Mealie-Token": "<your Mealie API token>",
    },
)

async with Client(transport) as client:
    tools = await client.list_tools()
    result = await client.call_tool("search_recipes", {"search": "soup"})

LibreChat

See examples/librechat.yaml for a ready-to-use mcpServers entry. It maps the endpoint bearer token to a LibreChat environment variable and each user's Mealie token to a per-user customUserVars field, so every LibreChat user acts as their own Mealie account.

Set requiresOAuth: false on the server entry. This server uses a static Authorization Bearer gate, not OAuth. Without the flag, LibreChat's OAuth auto-detection probes the endpoint without your headers, gets a 401, and misclassifies the server as OAuth-protected — so it never sends your token (you'll see 401s followed by /.well-known/oauth-* 404s). See Troubleshooting.

Configuration

Variable Required Default Description
MCP_AUTH_TOKEN yes Comma-separated secret bearer token(s) for the MCP endpoint.
MEALIE_BASE_URL no¹ Default Mealie base URL (e.g. https://mealie.example.com).
MEALIE_READONLY no true Set false to also register write tools.
MEALIE_TIMEOUT no 30 Outbound request timeout in seconds.
MEALIE_VERIFY_SSL no true Set false for self-signed Mealie certs.
MCP_HOST no 0.0.0.0 Bind address.
MCP_PORT no 8000 Bind port.
MCP_PATH no /mcp Endpoint path.
MCP_LOG_LEVEL no info uvicorn log level.
MCP_AUTH_DEBUG no false Log a masked diagnostic for each request hitting the auth gate (to troubleshoot 401s). See Troubleshooting.

¹ Required unless every client sends the X-Mealie-Url header.

Troubleshooting 401 Unauthorized

A 401 means the endpoint token (the Authorization: Bearer <token> gate, not your Mealie token) was missing or didn't match MCP_AUTH_TOKEN. Many MCP clients react to a 401 by probing for OAuth (GET /.well-known/oauth-*, which this server returns 404 for, since it uses static tokens, not OAuth) — those 404s are a symptom of the 401, not a separate problem.

To see exactly what the gate receives, set MCP_AUTH_DEBUG=true and reconnect. Each request to the gate is logged with a masked summary (the token itself is never logged — only its length and a SHA-256 fingerprint):

auth-debug enabled: accepting 1 token(s) with fingerprints ['0c45a1f1']
auth-debug: POST /mcp authorization=scheme=Bearer token_len=10 fp=0c45a1f1 matches_configured=True -> 200
auth-debug: POST /mcp authorization=scheme=Bearer token_len=5 fp=02b60b3b matches_configured=False -> 401
auth-debug: POST /mcp authorization=absent (no Authorization header reached the server) -> 401
auth-debug: POST /mcp authorization=scheme=Bearer <empty token> -> 401

Read it as:

  • matches_configured=False — the client sent a token, but it doesn't equal any MCP_AUTH_TOKEN value. Check for typos, quoting, or trailing whitespace.
  • absent — no Authorization header reached the server. The client isn't sending it, or a reverse proxy/ingress stripped it before it arrived. With LibreChat this is usually OAuth auto-detection probing without your headers — set requiresOAuth: false on the server entry (see above).
  • <empty token> — the client sent Authorization: Bearer with no value, typically an unset ${...} variable in the client config.
  • matches_configured=True -> 200 — the gate is fine; the problem is elsewhere.

Docker Hub images

Released versions are published to Docker Hub at georgx22/mealie-mcp (multi-arch: linux/amd64, linux/arm64):

docker run -d -p 8000:8000 \
  -e MCP_AUTH_TOKEN="a-long-random-secret" \
  -e MEALIE_BASE_URL="https://mealie.example.com" \
  georgx22/mealie-mcp:latest

CI/CD

Three GitHub Actions workflows are included (.github/workflows/):

  • ci.yml — runs ruff, pyright, and pytest on every push/PR (Python 3.11–3.13).
  • docker-publish.yml — builds and pushes the multi-arch image to Docker Hub when a GitHub Release is published (tags X.Y.Z, X.Y, X, and latest).
  • claude.yml — runs Claude Code when someone mentions @claude in an issue, PR, or review comment.

Configure these repository secrets (Settings → Secrets and variables → Actions):

Secret Used by How to get it
DOCKERHUB_USERNAME docker-publish Your Docker Hub username (with push access to georgx22/mealie-mcp).
DOCKERHUB_TOKEN docker-publish A Docker Hub access token (Account Settings → Security → New Access Token).
CLAUDE_CODE_OAUTH_TOKEN claude Run claude setup-token locally (Claude Pro/Max), paste the token.

To cut a release (which triggers the image build):

gh release create v0.1.0 --generate-notes

Development

pip install -e ".[dev]"
ruff check .     # lint
pyright          # type check
pytest -q        # tests

See CONTRIBUTING.md for details. Changes are tracked in CHANGELOG.md. Licensed under MIT.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选