1. Conduid
  2. Healthcare
  3. Tandoor Recipes
MCP server · Healthcare

Tandoor Recipes

Model Context Protocol server for Tandoor — recipes, meal plans, shopping lists, ingredients, cook logs, nutrition, AI import, and more.

37Low

Scored 5 months ago · breakdown

About Tandoor Recipes

Tandoor Recipes is an MCP server in the Healthcare category: model Context Protocol server for Tandoor — recipes, meal plans, shopping lists, ingredients, cook logs, nutrition, AI import, and more.

Install

Claude Code
claude mcp add tandoor-recipes -- npx -y @cliftonz/tandoor-recipes-mcp
npx
npx -y @cliftonz/tandoor-recipes-mcp

This server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.

Ask AI

✦

Ask AI about Tandoor Recipes

Powered by Claude · Grounded in docs

I know everything about Tandoor Recipes. Ask me about installation, configuration, usage, or troubleshooting.

Security checks

  • ✓README presentThe repository ships documentation.

5 checks have not been run yet.

README

Tandoor Recipes MCP

npm version

A Model Context Protocol (MCP) server that gives LLM agents full read/write access to a Tandoor Recipes instance — recipes, meal plans, ingredients, shopping lists, cook logs, nutrition, and AI-powered URL/image imports.

Turn "plan the week and make me a grocery list" into one prompt.

Why this server

  • Full Tandoor API coverage — 100+ typed tools spanning recipes, meal plans, ingredients, steps, shopping lists, cook logs, recipe books, foods, units, keywords, supermarket categories, property types / nutrition, custom filters, unit conversions, automations, user files, user prefs, activity logs.
  • Resources + Prompts, not just tools — read-only subscribable resources like tandoor://meal-plan/this-week and tandoor://pantry/on-hand, plus ready-made prompts (plan_week, grocery_list_for_plan, what_can_i_make_tonight). Most Tandoor MCP forks ship tools only.
  • Slim-by-default responses — a full recipe GET shrinks from ~20k characters to ~2k by stripping substitute trees, readonly timestamps, image URLs, etc. Pass format: "full" anywhere for the raw Tandoor response.
  • 3-stage URL import with a real fallback — tries Tandoor's native scraper first, then extracts schema.org JSON-LD from the page ourselves (works when Tandoor can't reach the URL or doesn't support the site), with an optional stub-on-failure escape hatch.
  • AI import from images / PDFs — multipart upload to Tandoor's ai-import/ endpoint, saves the parsed recipe.
  • Validated inputs — every tool has a Zod input schema; invalid calls are rejected at the MCP boundary before reaching the handler.
  • Transport-safe — retries with jittered backoff on 429 / 5xx, redacts your bearer token from error messages, reads response bodies exactly once (no "Body is unusable" footguns).
  • structuredContent + text — clients that support structured output skip a JSON re-parse round-trip; older clients still get text content.

Install

npm install -g @cliftonz/tandoor-recipes-mcp

Or npx without installing:

npx -y @cliftonz/tandoor-recipes-mcp

Configure

  1. In Tandoor: Settings → API Tokens → Create new token.
  2. Point your MCP client at the server.

Claude Code — one-shot plugin install

/plugin marketplace add Cliftonz/tandoor-recipe-mcp
/plugin install tandoor-recipes-mcp@cliftonz-tandoor

Claude Code prompts you for TANDOOR_URL and TANDOOR_TOKEN on install and stores the token securely. No mcpServers JSON editing needed.

Claude Desktop / Claude Code — manual config

{
  "mcpServers": {
    "tandoor": {
      "command": "npx",
      "args": ["-y", "@cliftonz/tandoor-recipes-mcp"],
      "env": {
        "TANDOOR_URL": "https://your-tandoor-instance.com",
        "TANDOOR_TOKEN": "your-api-token",
        "TANDOOR_MCP_PROFILE": "full"
      }
    }
  }
}

Recommended Claude Code permissions

The repo ships a .claude/settings.json that auto-allows read tools and prompts for everything else. Copy these into your own project's .claude/settings.json to reduce permission friction:

{
  "permissions": {
    "allow": [
      "mcp__tandoor__list_*",
      "mcp__tandoor__get_*"
    ],
    "ask": [
      "mcp__tandoor__create_*",
      "mcp__tandoor__update_*",
      "mcp__tandoor__delete_*",
      "mcp__tandoor__merge_*"
    ]
  }
}

Environment variables

Var Required Default Purpose
TANDOOR_URL ✅ — Base URL of your Tandoor instance
TANDOOR_TOKEN ✅ — API token with write access
TANDOOR_MCP_PROFILE — full basic exposes core tools only (~40); full includes everything (~100)
TANDOOR_MCP_INCLUDE_ONLY — — Comma-separated allowlist (glob * supported). E.g. list_*,get_*,create_meal_plan
TANDOOR_MCP_EXCLUDE — — Comma-separated denylist. E.g. merge_*,delete_* to hide destructive tools
TANDOOR_MCP_LOG — — Stderr trace mode. request, response, error, all, or comma list. Bearer token redacted.

The basic profile is useful when context size matters — every MCP client loads every tool schema into the model's context on startup. INCLUDE_ONLY and EXCLUDE compose on top of the profile for finer control (e.g. "give me only read tools" or "hide destructive ops from this agent").

Example conversations

Plan the week + generate a grocery list:

You: "Plan dinners for the week biased toward vegetarian recipes I've rated 4+, using what's on-hand where possible. Then give me the shopping list grouped by aisle."

Claude:

  1. Reads tandoor://pantry/on-hand and tandoor://meal-types
  2. Calls list_recipes({keywords_or: [<vegetarian>], rating_gte: 4, sort_order: '-rating'})
  3. Calls create_meal_plan for each day of the week
  4. Calls add_recipe_to_shopping_list for each plan
  5. Reads tandoor://shopping-list/active and groups by supermarket category

Import a recipe from a URL and schedule it:

You: "Import https://example.com/lasagna and schedule it for Friday dinner, 4 servings."

Claude:

  1. import_recipe_from_url({url: "..."}) — JSON-LD extraction handles sites Tandoor doesn't know
  2. create_meal_plan({recipe_id, meal_type_id: <Dinner>, from_date: "2026-04-24", servings: 4})

Cook log:

You: "Log that I made the Thai green curry last night — 4 out of 5, kids loved it."

Claude: create_cook_log({recipe: <id>, rating: 4, comment: "Kids loved it", servings: 4})

Tool catalog

All write-returning tools default to a slim JSON shape. Pass format: "full" for the raw Tandoor response.

Recipes

search_recipes · list_recipes · get_recipe · create_recipe · update_recipe · import_recipe_from_url · upload_recipe_image · related_recipes · add_recipe_to_shopping_list · recipe_ai_properties · recipe_batch_update

search_recipes is the preferred high-level entry point: it accepts food/keyword/book names (not IDs) and resolves them internally. Use list_recipes only for the raw ID-based filter surface.

list_recipes takes the full Tandoor filter surface: query, sort_order, rating[_gte|_lte], timescooked[_gte|_lte], cookedon_[gte|lte], keywords[_or|_and|_or_not|_and_not][], foods[...], books[...], makenow, new, random, internal, filter, date ranges, pagination.

Meal plans (bulk_create_meal_plans for week-planning)

list_meal_plans · get_meal_plan · create_meal_plan · update_meal_plan · delete_meal_plan · auto_meal_plan · list_meal_types · bulk_create_meal_plans

Ingredients + steps

list_ingredients · get_ingredient · create_ingredient · update_ingredient · delete_ingredient · parse_ingredient list_steps · get_step · create_step · update_step · delete_step

Shopping lists

list_shopping_entries · get_shopping_entry · create_shopping_entry · update_shopping_entry · delete_shopping_entry · bulk_check_shopping_entries · list_shopping_list_recipes · get_shopping_list_recipe · create_shopping_list_recipe · update_shopping_list_recipe · delete_shopping_list_recipe · bulk_create_shopping_list_recipe_entries

Foods + units + keywords + categories (full profile)

list_foods · get_food · create_food · update_food · delete_food · merge_food · move_food · food_shopping_update · food_fdc_lookup · food_ai_properties · food_batch_update list_units · get_unit · create_unit · update_unit · delete_unit · merge_unit list_unit_conversions · get_unit_conversion · create_unit_conversion · update_unit_conversion · delete_unit_conversion list_keywords · get_keyword · create_keyword · update_keyword · delete_keyword · merge_keyword · move_keyword list_supermarket_categories · *_supermarket_category_relation

Cook log + recipe books (full profile)

list_cook_logs · get_cook_log · create_cook_log · update_cook_log · delete_cook_log list_recipe_books · get_recipe_book · create_recipe_book · update_recipe_book · delete_recipe_book · list_recipe_book_entries · get_recipe_book_entry · add_recipe_to_book · remove_recipe_from_book

Nutrition + property types + custom filters (full profile)

list_property_types · get_property_type · create_property_type · update_property_type · delete_property_type list_properties · get_property · create_property · update_property · delete_property list_custom_filters · get_custom_filter · create_custom_filter · update_custom_filter · delete_custom_filter

AI imports (full profile)

list_ai_providers · import_recipe_from_image (file path, URL, or text)

Automations, user files, prefs, logs (full profile)

list_automations · *_automation · list_user_files · *_user_file · list_user_preferences · get_user_preference · update_user_preference · get_server_settings · get_share_link · list_view_logs · list_import_logs · list_ai_logs

Gotchas

FDC lookups rate-limit after 30 requests/hour

food_fdc_lookup delegates to Tandoor, which calls the USDA FoodData Central API. Out of the box Tandoor uses USDA's public DEMO_KEY, capped at 30 requests/hour per IP. Bulk-enriching a grocery list hits that ceiling fast and you'll see 429s on Tandoor's side.

Fix (takes 2 minutes):

  1. Register a free personal key at api.data.gov/signup — no approval needed, instant.

  2. Set it on the Tandoor container, not the MCP server:

    # docker-compose.yml — under the tandoor service
    environment:
      - FDC_API_KEY=<your-key>
    

    Kubernetes / Helm: add FDC_API_KEY to the Tandoor deployment's env or a secret. Restart the Tandoor pod.

  3. The limit jumps to 1,000 requests/hour — plenty for bulk enrichment.

If FDC returns 404 for a food, the fdc_id you passed doesn't exist in USDA's database — try food_ai_properties as a fallback (uses Tandoor's configured AI provider instead of USDA).

Resources

URI Purpose
tandoor://meal-plan/this-week Monday–Sunday meal plan entries, slimmed to {id, date, meal_type, recipe_name, servings, note}
tandoor://pantry/on-hand Foods flagged food_onhand=true
tandoor://shopping-list/active Unchecked, recent shopping entries
tandoor://meal-types Breakfast/Lunch/Dinner/etc. with IDs

Prompts

Name Purpose
plan_week Plan 7 days of dinners, optionally pantry-biased and keyword-filtered
grocery_list_for_plan Turn this week's meal plan into a shopping list grouped by aisle
what_can_i_make_tonight Find makeable recipes ≤ N minutes from on-hand foods
import_and_plan Import a URL recipe and schedule it in one shot

Development

git clone https://github.com/Cliftonz/tandoor-recipe-mcp.git
cd tandoor-recipe-mcp
npm install
npm run build
npm test

Tests use Vitest and mock fetch — no live Tandoor instance needed for the default run.

End-to-end tests

An opt-in E2E suite exercises the full write path against a real Tandoor instance. Run it only against a throwaway/isolated Tandoor space — the suite creates and deletes real rows.

TANDOOR_URL=https://your-tandoor.example \
TANDOOR_TOKEN=... \
npm run test:e2e
Var Effect
TANDOOR_E2E_KEEP=1 Skip cleanup; leave created resources for inspection
TANDOOR_E2E_SKIP_IMPORT=1 Skip the URL-import step (offline runners)
TANDOOR_E2E_IMPORT_URL=<url> Override the default recipe URL
TANDOOR_E2E_AI_PROVIDER=<id> Run the AI-import step against this provider

Security posture

This server treats the configured Tandoor instance as trusted enough to read+write on your behalf — you provide the bearer token. It does NOT treat the instance as fully trusted for content:

  • Tool responses from create_meal_plan / update_meal_plan are slimmed — only ids and structural fields flow back to the LLM. User-visible names (recipe.name, meal_type.name, keyword names) are omitted so a hostile or compromised Tandoor instance can't inject model-steering text into Claude's context via these paths. Call get_recipe or list_meal_types if you need the human-readable form.
  • Keyword payloads are capped at 50 entries and projected to {id, name} before being forwarded into writes — stops amplification and mass-assignment exposure.
  • Bearer tokens are redacted from every error message and log line.

If your Tandoor deployment is single-tenant and you own every recipe, the posture is conservative for your case. If you share a Tandoor instance with untrusted users (or run a Tandoor instance exposed to the public internet with anonymous sharing), the hardening above matters.

License

MIT

README copy captured when this server was indexed; it may lag the repository. The original is authoritative.

Questions

About Tandoor Recipes

How do I install Tandoor Recipes?

Run claude mcp add tandoor-recipes -- npx -y @cliftonz/tandoor-recipes-mcp, then add the server to your MCP client's configuration.

Is Tandoor Recipes safe to use with an AI agent?

Its trust score is 37 out of 100 (low). It passes 1 of the 1 static security checks run so far. It has no ConduID identity yet, so agent calls to it are not receipted.

Is Tandoor Recipes still maintained?

Conduid hasn't recorded a commit date for this repository yet. Check the repository directly for recent activity.