Skip to main content
Glama
Tandoor Recipes MCP

Tandoor Recipes MCP

by Cliftonz

Tandoor Recipes MCP

npm version CI OpenSSF Scorecard License: MIT

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, AI-powered URL/image imports, invite/access tokens, storages, sync, spaces, exports, imports, and more.

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

New in 3.1.0

  • File downloads (#10): download_recipe_file and download_file return a Tandoor file inline, or save it to TANDOOR_MCP_DOWNLOAD_ROOT with save: true. See Downloading files.

  • get_external_recipe_file_link works again. get_recipe_file_metadata is removed; use download_recipe_file instead.

Related MCP server: Tandoor MCP Server

New in 3.0.0

  • Per-section tool settings replace TANDOOR_MCP_PROFILE. One env var per section: tiered sections take off, simple, or full, and toggle sections take off or on. See Tool sections and Migration from 2.x.

  • Pantry and freezer inventory tools in the inventory section, plus a combined tandoor://pantry/on-hand resource.

  • Households: list, get, create, update, and delete households, and assign_household to move user-spaces between them.

  • Named shopping lists, such as one per store. Foods and shopping entries take shopping_lists.

  • Tandoor 2.6 API alignment. Requires Tandoor 2.6.0 or later.

  • HTTP transport fix (#12): the HTTP transport now answers every request, not only the first.

  • oxlint for linting.

307 tools in total; 46 are visible at startup with the default settings. The CHANGELOG has the full list of changes and breaking changes.

Why this server

  • Full Tandoor 2.6 API coverage. 307 typed tools, spanning every domain the Tandoor OpenAPI exposes.

  • Resources + prompts, not just tools. Read-only 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.

  • Per-section tool settings. One env var per section (recipes, meal plan, shopping, and so on) sets it. Tiered sections take off, simple, or full. Toggle sections take off or on. In stdio mode the LLM can turn a hidden section on mid-session with enable_tool_group. See Tool sections.

  • jq stash for large payloads. Responses larger than 5KB return a stash handle plus a schema summary; the LLM follows up with jq_query to project just the fields it needs.

  • 3-stage URL import with a real fallback. Tries Tandoor's native scraper first, then extracts schema.org JSON-LD from the page directly (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.

  • Local or remote. Stdio (default, for Claude Desktop / Claude Code), stateless HTTP (for out-of-Claude callers), or remote mode: a self-hosted server with OAuth sign-in that Claude and ChatGPT connect to as a custom connector.

  • Destructive-action safety layer. Every tree-shaped delete has a preview_* sibling that projects the cascade before it runs; every token-mint tool leads with an ESCALATION SURFACE warning.

Install

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

Or npx without installing:

npx -y @cliftonz/tandoor-recipes-mcp

Node 24 or later is required (see engines.node in package.json).

Other ways to get it:

  • Claude Desktop extension: tandoor-recipes-mcp.mcpb from the latest GitHub release. It needs no Node install. See Claude Desktop, desktop extension.

  • Docker image: ghcr.io/cliftonz/tandoor-recipes-mcp, for linux/amd64 and linux/arm64, tagged with each version and latest. The image starts in remote mode by default.

  • MCP Registry: listed as io.github.Cliftonz/tandoor-recipe-mcp in the MCP Registry, with the npm package, the .mcpb file and the Docker image.

  • Claude Code plugin and Codex plugin: see Configure.

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

From a terminal, the same two steps are:

claude plugin marketplace add Cliftonz/tandoor-recipe-mcp
claude 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, desktop extension

Use the desktop extension for Claude Desktop Chat and Cowork. It bundles the server and runs on Claude Desktop's built-in Node, so you do not need to install Node.

  1. Download tandoor-recipes-mcp.mcpb from the latest GitHub release.

  2. Double-click the file. Or, in Claude Desktop, open Settings > Extensions > Advanced settings > Install Extension and select the file.

  3. Enter your Tandoor URL and API token. Claude Desktop stores the token securely.

  4. Optional: set the section settings you want.

Claude Desktop, plugin marketplace

Claude Desktop can also add the plugin:

  1. Open Customize > Plugins > Add > Add marketplace > Add from a repository.

  2. Enter Cliftonz/tandoor-recipe-mcp.

  3. Open Customize > Plugins > Discover, select the plugin, and select Add.

This path does not give you a working server in Chat or Cowork. Chat and Cowork do not prompt for plugin settings, so the plugin's Tandoor URL and API token settings stay empty. Chat ignores local MCP servers from plugins. Cowork loads them only when the session runs on your computer. Use the desktop extension or the manual config instead. Use the plugin from the Claude Code CLI.

Claude Desktop / Claude Code, manual config

Edit the Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

For Claude Code, put the same mcpServers block in a project .mcp.json, or use claude mcp add.

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

Quit and reopen Claude Desktop to load the change. This config runs the server with npx, so Node 24 or later must be on your PATH.

Codex

The ChatGPT desktop app, the Codex CLI, and the Codex IDE extension share one config file, ~/.codex/config.toml. Every Codex path below runs the server with npx, so Node 24 or later must be on your PATH.

Codex, settings

  1. In the app, open Settings > MCP servers > Add server.

  2. Choose STDIO.

  3. Set the command to npx.

  4. Add the arguments -y and @cliftonz/tandoor-recipes-mcp.

  5. Add the environment variables TANDOOR_URL and TANDOOR_TOKEN. Add any TANDOOR_MCP_* section settings you want.

  6. Select Save, then restart the app.

From a terminal, the same setup is:

codex mcp add tandoor \
  --env TANDOOR_URL=https://your-tandoor-instance.com \
  --env TANDOOR_TOKEN=your-api-token \
  -- npx -y @cliftonz/tandoor-recipes-mcp

codex mcp add writes this block to ~/.codex/config.toml. You can also add it to config.toml by hand:

[mcp_servers.tandoor]
command = "npx"
args = ["-y", "@cliftonz/tandoor-recipes-mcp"]

[mcp_servers.tandoor.env]
TANDOOR_URL = "https://your-tandoor-instance.com"
TANDOOR_TOKEN = "your-api-token"

Codex, plugin

  1. Open the Plugins page and select Add > Add a marketplace.

  2. Enter the source Cliftonz/tandoor-recipe-mcp.

  3. Open the Tandoor plugin's details and select the plus button.

  4. Restart the app.

From a terminal:

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

Codex does not prompt for settings on install, and you cannot override a plugin's environment. The plugin passes through only TANDOOR_URL and TANDOOR_TOKEN from the app's environment. An app you start from the Dock usually does not see exports in ~/.zshrc. On macOS, set the variables for your login session and then restart the app:

launchctl setenv TANDOOR_URL https://your-tandoor-instance.com
launchctl setenv TANDOOR_TOKEN your-api-token

launchctl setenv does not survive a reboot. It also exposes the token to every app you start in that session.

The Codex plugin does not pass through section settings. To change sections, use saved sections or the settings path.

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_*",
      "mcp__tandoor__preview_*"
    ],
    "ask": [
      "mcp__tandoor__create_*",
      "mcp__tandoor__update_*",
      "mcp__tandoor__delete_*",
      "mcp__tandoor__merge_*",
      "mcp__tandoor__switch_active_space",
      "mcp__tandoor__create_access_token",
      "mcp__tandoor__create_invite_link",
      "mcp__tandoor__get_external_recipe_file_link"
    ]
  }
}

Transport modes

The server ships two transports. Default is stdio; opt in to HTTP with an env var. HTTP also has a remote mode for Claude and ChatGPT custom connectors.

Mode

When to use

Auth

stdio (default)

Claude Desktop, Claude Code, any MCP client that spawns the server as a subprocess.

Inherited from parent process.

http (stateless)

Out-of-Claude callers, local scripts, other agents on the same host.

Optional bearer via TANDOOR_MCP_HTTP_TOKEN.

http with TANDOOR_MCP_PUBLIC_URL (remote mode)

Claude (web, mobile, Desktop, Cowork, Code) and ChatGPT, through your own HTTPS URL.

OAuth sign-in. Each user pastes their own Tandoor API token.

HTTP mode

TANDOOR_URL=https://tandoor.example.com \
TANDOOR_TOKEN=... \
TANDOOR_MCP_TRANSPORT=http \
TANDOOR_MCP_HTTP_PORT=3737 \
TANDOOR_MCP_HTTP_TOKEN=some-long-random-string \
npx -y @cliftonz/tandoor-recipes-mcp

The server listens on http://127.0.0.1:${TANDOOR_MCP_HTTP_PORT:-3737}/mcp (POST only for JSON-RPC requests). Any other method on that path gets a 405 with Allow: POST and a JSON-RPC error body. Auth is checked first, so a request without a valid token gets a 401 instead. The server binds to 127.0.0.1 unless you set TANDOOR_MCP_HTTP_HOST. To reach it from another host, put a reverse proxy in front of it, or use remote mode.

If TANDOOR_MCP_HTTP_TOKEN is set, every request must include Authorization: Bearer <token>. Missing or wrong tokens get a 401 with WWW-Authenticate: Bearer.

HTTP-mode constraints: the jq stash and dynamic tool gating both assume a single long-lived session. In HTTP mode both are auto-disabled: enable_tool_group and disable_tool_group throw, and every tool response is inlined rather than stashed. The section settings fix the tool list at startup, so set every section you need before you start the server.

Remote mode

Remote mode runs the server on your own host, next to your Tandoor, with a built-in OAuth sign-in. You add it to Claude or ChatGPT as a custom connector, by its HTTPS URL. It works in Claude on the web, mobile, Desktop chat, Cowork and Claude Code, and in ChatGPT. Each person signs in by pasting their own Tandoor API token, so each person acts in Tandoor as themselves.

Why you host it yourself, and why it is not in a connector directory: every Tandoor is a separate, self-hosted server, so there is no single URL a directory listing could point to. A shared hosted copy would also have to hold everyone's Tandoor tokens. In remote mode the tokens stay on your server, encrypted with your key.

How a connection works:

  1. The app (Claude or ChatGPT) calls your public URL and gets a 401 that points to the server's OAuth metadata.

  2. The app identifies itself with its published client document, or registers itself automatically.

  3. The app opens the sign-in page in your browser. You paste a Tandoor API token and select Approve.

  4. The server checks the token against Tandoor, stores it encrypted, and gives the app its own tokens. The app never sees your Tandoor token.

Remote mode settings

Remote mode turns on when TANDOOR_MCP_PUBLIC_URL is set. These settings apply to remote mode, and the HTTP ones also apply to plain HTTP mode.

Variable

Default

Rules

TANDOOR_URL

none (required)

Your Tandoor. It only has to be reachable from the server, so an internal address such as http://web_recipes:8080 works. The server uses only the scheme, host and port.

TANDOOR_MCP_TANDOOR_PUBLIC_URL

TANDOOR_URL

The address users open Tandoor at, such as https://recipes.example.com. The sign-in page shows it and links to its /settings/api page for creating a token. Set it when TANDOOR_URL is an internal address. The server still calls Tandoor only at TANDOOR_URL. It uses only the scheme, host and port, and adds https:// when the scheme is missing. Ignored outside remote mode.

TANDOOR_MCP_TRANSPORT

stdio (http in the Docker image)

Must be http. The server refuses to start in remote mode otherwise.

TANDOOR_MCP_PUBLIC_URL

none

The HTTPS URL clients connect to, such as https://mcp.example.com/mcp. Must use https. Its path must equal TANDOOR_MCP_HTTP_PATH. No query string, fragment, username or password.

TANDOOR_MCP_SECRET_KEY

none (required in remote mode)

Exactly 64 hex characters (32 bytes). Generate one with openssl rand -hex 32. It encrypts the stored Tandoor tokens and signs the sign-in form.

TANDOOR_MCP_DATA_DIR

$XDG_DATA_HOME/tandoor-mcp, else ~/.local/share/tandoor-mcp (/data in the Docker image)

The folder for oauth.json. Must be an absolute path; a relative path is ignored.

TANDOOR_MCP_TRUST_PROXY

none (no proxy trusted)

Set it when a reverse proxy or tunnel sits in front. A hop count such as 1, or a comma-separated list of IP addresses and CIDR ranges. A /0 range is refused. The server uses it to find each visitor's IP address for rate limits.

TANDOOR_MCP_HTTP_HOST

127.0.0.1 (0.0.0.0 in the Docker image)

The address the server listens on.

TANDOOR_MCP_HTTP_PORT

3737

The port the server listens on.

TANDOOR_MCP_HTTP_PATH

/mcp

The MCP endpoint path. It cannot be, or start with, /authorize, /token, /register, /revoke, /consent or /.well-known.

TANDOOR_MCP_HTTP_DRAIN_MS

10000

On SIGTERM or SIGINT, how long the server waits for requests in progress. New requests get a 503 meanwhile.

TANDOOR_MCP_HTTP_MAX_BODY_BYTES

5242880

Larger request bodies get a 413.

TANDOOR_MCP_HTTP_MAX_CONNS

128

The most open connections the server accepts.

Header and request timeouts are fixed at 10 and 30 seconds.

Rules and behavior in remote mode:

  • TANDOOR_TOKEN is refused. The server will not start while it is set. Each user brings their own token.

  • TANDOOR_MCP_HTTP_TOKEN is refused. It belongs to the shared-password HTTP mode and cannot be combined with remote mode.

  • Tool sections apply to every connected user. The section settings are read once at startup, and enable_tool_group is off in HTTP mode, so everyone sees the same tools.

  • file_path uploads are refused. The server's disk is not the user's disk. Use file_url instead. Saving downloads with save: true is also stdio only.

  • A read-only Tandoor token works for reads only. Write tools return Tandoor's error. The connection stays.

  • Host and Origin are checked. A request must carry the public URL's host in its Host header, or localhost, 127.0.0.1 or [::1]. Anything else gets a 403, logged as host_rejected. A browser Origin header on the MCP path must equal the public URL's origin, or the request gets a 403, logged as origin_rejected.

  • Responses are plain JSON. The server does not hold event streams open, so proxies need no streaming or buffering settings. GET on the MCP path returns 405.

Run with Docker

The image is ghcr.io/cliftonz/tandoor-recipes-mcp. It defaults to TANDOOR_MCP_TRANSPORT=http, TANDOOR_MCP_HTTP_HOST=0.0.0.0 and TANDOOR_MCP_DATA_DIR=/data, and runs as the node user.

  1. Generate a secret key:

    openssl rand -hex 32
  2. Copy the tandoor-mcp service and the tandoor-mcp-data volume from docker-compose.example.yml into your Tandoor compose file, so both services share a network.

  3. Set the environment:

    • TANDOOR_URL: your Tandoor service on the internal network. The example uses http://web_recipes:8080; replace web_recipes with the name of your Tandoor service.

    • TANDOOR_MCP_TANDOOR_PUBLIC_URL: the address users open Tandoor at, such as https://recipes.example.com.

    • TANDOOR_MCP_PUBLIC_URL: your public HTTPS URL, ending in /mcp.

    • TANDOOR_MCP_SECRET_KEY: the key from step 1.

    • TANDOOR_MCP_TRUST_PROXY: "1" when one proxy or tunnel sits in front, as in the example.

  4. Start it:

    docker compose up -d tandoor-mcp

Notes on the example file:

  • The /data volume holds oauth.json. Keep the volume across upgrades, or everyone has to reconnect.

  • The port is published on 127.0.0.1 only (127.0.0.1:3737:3737), so only a proxy or tunnel on the same host can reach it. Remove the ports: entry if your proxy reaches the container over the Docker network.

  • Keep TANDOOR_MCP_HTTP_HOST=0.0.0.0 inside the container. Binding a specific address inside the container is not supported: the image's health check calls 127.0.0.1, so the container reports unhealthy. Limit exposure with the port mapping instead.

  • stop_grace_period: 15s is longer than the 10-second drain, so requests in progress can finish on docker compose down.

The sign-in page shows your Tandoor address and links to its /settings/api page for creating a token. With an internal TANDOOR_URL such as http://web_recipes:8080, set TANDOOR_MCP_TANDOOR_PUBLIC_URL to the address users open Tandoor at, so the link opens from a browser.

Without Docker, run the npm package with the same settings:

TANDOOR_URL=https://tandoor.example.com \
TANDOOR_MCP_TRANSPORT=http \
TANDOOR_MCP_PUBLIC_URL=https://mcp.example.com/mcp \
TANDOOR_MCP_SECRET_KEY=<64 hex characters> \
TANDOOR_MCP_TRUST_PROXY=1 \
npx -y @cliftonz/tandoor-recipes-mcp

Expose it over HTTPS

Claude and ChatGPT need a public HTTPS URL. Put a reverse proxy or a tunnel in front of the server. Whatever you use must:

  • Forward the whole host, not only /mcp. The OAuth routes live at the root.

  • Pass the original Host header through.

  • Set X-Forwarded-For, and you set TANDOOR_MCP_TRUST_PROXY to match.

Caddy

mcp.example.com {
	reverse_proxy 127.0.0.1:3737
}

Caddy passes Host through unchanged and sets X-Forwarded-For. Set TANDOOR_MCP_TRUST_PROXY=1. If Caddy runs in the same compose network, use reverse_proxy tandoor-mcp:3737.

nginx

server {
    listen 443 ssl;
    server_name mcp.example.com;
    # ssl_certificate and ssl_certificate_key go here

    location / {
        proxy_pass http://127.0.0.1:3737;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

proxy_set_header Host $host; is required. Without it, nginx sends the upstream name as Host, and the server answers 403 unless that name is localhost or a loopback address. The log line host_rejected includes a hint about this. Responses are plain JSON, so no SSE or buffering settings are needed. Set TANDOOR_MCP_TRUST_PROXY=1.

Cloudflare Tunnel

A tunnel needs no open port. The example compose file has an optional cloudflared service.

  1. In the Cloudflare dashboard, go to Networking > Tunnels and select Create a tunnel. Copy the tunnel token.

  2. Uncomment the cloudflared service and set TUNNEL_TOKEN to the token.

  3. In the tunnel's Routes tab, select Add route > Published application. Choose your subdomain and domain, and set Service URL to http://tandoor-mcp:3737.

  4. Leave HTTP Host Header empty, so the server sees your public hostname.

Set TANDOOR_MCP_TRUST_PROXY=1. You can remove the ports: entry from tandoor-mcp.

Tailscale Funnel

On the host where port 3737 is published on 127.0.0.1:

tailscale funnel --bg 3737

The public URL is https://<device-name>.<tailnet-name>.ts.net, so set TANDOOR_MCP_PUBLIC_URL to https://<device-name>.<tailnet-name>.ts.net/mcp. Funnel keeps the Host header and sets X-Forwarded-For. Set TANDOOR_MCP_TRUST_PROXY=1. tailscale funnel reset turns it off.

Access gateways

Warning: If you put an access gateway in front, such as Cloudflare Access, Authelia or another forward-auth proxy, it must let these routes through without its own login. Otherwise Claude and ChatGPT cannot connect.

  • POST /mcp (your TANDOOR_MCP_HTTP_PATH)

  • GET /.well-known/oauth-protected-resource/mcp

  • GET /.well-known/oauth-authorization-server

  • POST /register

  • POST /token

  • POST /revoke

  • GET and POST /authorize

  • POST /consent

/authorize and /consent open in the user's own browser. The others are called by the app's servers. The simplest rule is to bypass the gateway for /mcp, /register, /token, /revoke, /authorize, /consent and /.well-known/*.

Connect a client

Use your public URL, for example https://mcp.example.com/mcp.

Claude

On a Free, Pro, Max or Ultra plan:

  1. Go to Customize > Connectors.

  2. Click Add custom connector.

  3. Enter the URL.

  4. If the dialog asks for the OAuth client, choose Use Claude's published identity or Register automatically. The server supports both. Do not enter a client ID or secret.

  5. Click Add. When you connect, the sign-in page opens in your browser.

On a Team or Enterprise plan, an Owner adds it under Organization settings > Connectors: select Add, then Custom, enter the URL, and click Add. Each member then finds it under Customize > Connectors and clicks Connect.

You can also share a link that opens the dialog with the name and URL filled in. Percent-encode the URL:

https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=Tandoor&connectorUrl=https%3A%2F%2Fmcp.example.com%2Fmcp

Owners can use the same parameters on https://claude.ai/admin-settings/connectors. The user still reviews and confirms before anything is added.

Claude Code

claude mcp add --transport http tandoor https://mcp.example.com/mcp

Then run /mcp in Claude Code and follow the sign-in steps in your browser.

ChatGPT

  1. Go to chatgpt.com/plugins.

  2. Select the plus button, then Add custom MCP server.

  3. Enter a name and description.

  4. Under Connection, enter the URL, including /mcp.

  5. Configure authentication. The server uses OAuth and supports both ways ChatGPT registers itself: a client ID metadata document and dynamic client registration. Review the risk warning and select I understand and want to continue.

  6. Select Create as a plugin.

Your ChatGPT account or workspace policies decide whether you can add custom MCP servers.

The sign-in page

The page is titled Connect to Tandoor. It names the app that wants access and the Tandoor URL, and shows where you return after you approve. Paste a Tandoor API token into Tandoor API token and select Approve, or Deny.

Create the token on your Tandoor's API settings page, /settings/api. The token decides what the app can do: a read-write token allows changes, a read-only token allows reads only.

If Tandoor rejects the token, the page says so and you can try again. The form expires after 10 minutes, and each IP address gets 10 attempts a minute.

Operate it

  • Back up oauth.json and the secret key separately. oauth.json in the data folder holds the registered apps, the connections, the encrypted Tandoor tokens and hashes of the tokens the server issued. Anyone with both the file and the key can read the stored Tandoor tokens.

  • Revoke everyone: stop the server, delete oauth.json, and start it again. Every user has to reconnect.

  • Revoke one user's access: delete their API token in Tandoor. Their tool calls then fail in Tandoor.

  • Rotate the secret key: the server refuses to start when the key cannot decrypt oauth.json (cannot read OAuth store). Rotation means stopping the server, deleting oauth.json, setting the new key and starting again. Every user has to reconnect.

  • Connections end on their own after 30 days without use, or when Tandoor rejects the stored token with a 401. In the second case the server ends every connection that uses that token, and the tool call returns "Tandoor rejected your token. Reconnect this connector to sign in again." along with a sign-in challenge for the app. App registrations that never finish signing in are removed after 24 hours.

  • Run one server process per data folder. Each process keeps oauth.json in memory and rewrites it on every change, so two processes overwrite each other.

  • Health check: GET /healthz returns {"status":"ok"} without auth. The Docker image checks it every 30 seconds.

  • Logs go to standard error (docker compose logs tandoor-mcp). The startup line shows the public URL, auth=oauth, the Tandoor URL and version, and the sections. Request events look like [tandoor-mcp] http reqId=... level=warn event=host_rejected .... Other events include origin_rejected, forwarded_header_untrusted (a proxy sent X-Forwarded-For but TANDOOR_MCP_TRUST_PROXY is not set), tandoor_check_failed, cimd_fetch_failed, payload_too_large and shutdown. PRIVACY.md lists what the logs contain.

  • Rate limits are per IP address: failed access tokens, sign-in form submissions, and the OAuth routes. Behind a proxy, set TANDOOR_MCP_TRUST_PROXY, or every visitor shares one limit.

Firewall allowlisting

You can limit who reaches the server-to-server routes (/mcp, /.well-known/*, /register, /token, /revoke):

Do not limit /authorize and /consent this way. They come from each user's own browser. Claude Code and the MCP Inspector also run on the user's computer, so their requests come from the user's address.

The server itself makes outbound requests to your Tandoor, to the app's client document (such as one on claude.ai or chatgpt.com) when an app uses its published identity, and to web addresses users import from.

Test it

Check the health endpoint and the metadata:

curl https://mcp.example.com/healthz
curl https://mcp.example.com/.well-known/oauth-protected-resource/mcp

Then connect with the MCP Inspector. It runs the sign-in flow in your browser:

npx @modelcontextprotocol/inspector --server-url https://mcp.example.com/mcp --transport http

Remote mode security

  • The sign-in routes are reachable from the internet. Anyone who can reach the URL can start signing in, but only a valid Tandoor token completes it.

  • The Tandoor token is the real credential. Whoever signs in with a token gets that token's full Tandoor access.

  • The secret key protects the stored tokens. The server stores only hashes of the tokens it issues.

  • Removing a connection in Claude or ChatGPT does not delete the Tandoor token. Delete it in Tandoor too.

  • Tandoor content is untrusted input to the assistant.

SECURITY.md has the full threat model and how to report a problem.

Environment variables

Var

Required

Default

Purpose

TANDOOR_URL

yes

none

Base URL of your Tandoor instance.

TANDOOR_TOKEN

yes, except in remote mode

none

API token with write access. Remote mode refuses to start when it is set.

TANDOOR_MCP_TRANSPORT

no

stdio

stdio or http.

TANDOOR_MCP_HTTP_PORT

no

3737

HTTP-mode port.

TANDOOR_MCP_HTTP_TOKEN

no

none

HTTP-mode bearer token. If unset, HTTP transport runs without auth. Not allowed in remote mode.

TANDOOR_MCP_<SECTION>

no

per section

One variable per tool section, such as TANDOOR_MCP_RECIPES. See Tool sections for every variable, its values, and its default.

TANDOOR_MCP_INCLUDE_ONLY

no

none

Comma-separated allowlist (glob * supported). E.g. list_*,get_*,create_meal_plan.

TANDOOR_MCP_EXCLUDE

no

none

Comma-separated denylist. E.g. merge_*,delete_* to hide destructive tools.

TANDOOR_MCP_LOG

no

none

Stderr trace mode. request, response, error, all, or comma list. Bearer token redacted.

TANDOOR_MCP_STASH_ENABLED

no

1

Park large tool results in an in-memory cache and return a {stashed:true, handle, shape} summary; the LLM calls jq_query to extract subsets. Set 0 to disable. Auto-disabled in HTTP mode.

TANDOOR_MCP_STASH_THRESHOLD

no

25000

Stash payloads strictly larger than this many bytes.

TANDOOR_MCP_STASH_MAX_ENTRIES

no

32

LRU cap on stashed handles.

TANDOOR_MCP_STASH_MAX_BYTES

no

32000000

Total-bytes cap on the stash; LRU eviction kicks in past this budget.

TANDOOR_MCP_STASH_TTL_MS

no

600000

Per-entry TTL in milliseconds (default 10 minutes).

TANDOOR_MCP_DOWNLOAD_ROOT

no

none

Existing folder that save: true writes downloads into. Stdio mode only. See Downloading files.

The other HTTP settings and the remote-mode settings are in Remote mode settings.

INCLUDE_ONLY and EXCLUDE run before the section settings and give finer control ("give me only read tools" or "hide destructive ops from this agent").

Section values can also come from saved sections.

The Claude plugin and the desktop extension pass their settings as CLAUDE_PLUGIN_OPTION_<KEY>, such as CLAUDE_PLUGIN_OPTION_TANDOOR_URL or CLAUDE_PLUGIN_OPTION_RECIPES. A non-empty plugin setting wins over the variable it replaces. An empty one falls back to that variable.

Downloading files

download_recipe_file({recipe_id}) returns the file Tandoor stored for a recipe synced from a Storage backend (Dropbox, Nextcloud, or Local). It is in the recipes section's full tier. download_file({file_id}) returns a user file uploaded to Tandoor. It is in the admin section.

Files up to 5 MiB come back inline, after a text block with {filename, mime, size}. Images (PNG, JPEG, GIF, and WebP) come back as an MCP image block. Other files come back as an embedded resource block. A larger file returns an error that tells the model to retry with save: true.

To save a file to disk instead, set TANDOOR_MCP_DOWNLOAD_ROOT to an existing folder and call the tool with save: true. The tool streams the file into that folder and returns {path, size, mime}. Saving works over stdio only, because over HTTP the folder is on the server machine. The tool removes unsafe characters from the filename. It never overwrites a file: if the name is taken, it adds (2), (3), and so on.

Tandoor compatibility

Minimum: Tandoor server 2.6.0.

The 3.0.0 tools target the endpoints in the vendored Tandoor 2.6.15 OpenAPI spec (see tandoor api specification.yaml, info.version header). Older 2.x instances return 404 on the tools for newer endpoints, such as named shopping lists.

To check your instance version from an LLM session:

> Ask: what version of Tandoor am I connected to?
> Claude calls: get_version
> Returns: { mcp: "3.0.0", protocol: "...", tandoor: "2.6.15" }

The server also probes /api/server-settings/current/ at boot and writes a WARNING to stderr if the connected instance is older than 2.6.0.

Migration from 2.x

3.0.0 removes TANDOOR_MCP_PROFILE and the old tool-group names. The per-section settings in Tool sections replace both.

  • TANDOOR_MCP_PROFILE is ignored. When it has a value, the server prints one stderr warning.

  • TANDOOR_MCP_PROFILE=full: set every tiered section to full and every toggle section to on.

  • Claude Code plugin users: the plugin used to default to full (every tool). It now starts with the section defaults. To get more tools back, set recipes, meal_plan, shopping, inventory, foods, cooklog, recipe_books, ai, import_export, household_space, and admin in the plugin settings.

  • Old group names are gone, with no aliases. Use the section names in enable_tool_group. The always-on group is now always (was core). The CHANGELOG lists every removed name.

Migration from 1.4.0

  • Stdio users: nothing required. No breaking changes, no config edits.

  • HTTP users: opt in with TANDOOR_MCP_TRANSPORT=http. Set TANDOOR_MCP_HTTP_TOKEN and expect the jq stash + dynamic gating to be off (both are stdio-session assumptions).

Tool sections

Each section has one env var. The server trims each value and ignores case. An unset, empty, or whitespace-only variable means the saved setting for this TANDOOR_URL if there is one, otherwise the default. If any section variable is invalid, the server stops at startup with one error that names every invalid variable and its valid values.

Tiered sections take off, simple, or full and default to simple. full includes everything in simple.

Section

Env var

simple

full adds

recipes

TANDOOR_MCP_RECIPES

Browse, search, get, related recipes, create, update, import from URL, read keywords.

Delete, steps, ingredients, images, batch update, keyword writes, custom filters, file links, share links.

meal-plan

TANDOOR_MCP_MEAL_PLAN

Meal plan create, read, update, and delete. Read meal types.

Auto-plan, bulk create, meal type writes, iCal export.

shopping

TANDOOR_MCP_SHOPPING

List the named shopping lists. Shopping entry create, read, update, delete, and check. bulk_update_shopping_entries checks entries and adds, removes, sets, or clears their lists in one call. Add a recipe's ingredients or a single food as shopping entries.

Named shopping list get, create, update, and delete, and their delete previews. Deleting a list removes only its links; the foods, entries, and supermarkets stay. Shopping-list-recipe create, read, update, and delete. Supermarkets, categories, and category relations.

inventory

TANDOOR_MCP_INVENTORY

List locations, list entries, add, consume, and move. add_inventory_item always creates a new entry. consume_inventory_item stops at 0 and warns when you consume more than the entry holds. move_inventory_item moves a whole entry.

Location create, get, update, and delete. Entry get, update, and delete. The read-only inventory log. Delete previews. Deleting a location also deletes its entries and the log rows of every entry that was ever in it, including entries moved elsewhere since. Deleting an entry deletes its log rows.

foods

TANDOOR_MCP_FOODS

List, get, create, and update foods, including their shopping lists. Parse an ingredient. List units.

Delete, merge, move, FDC lookup and search, batch update (including shopping list changes), unit CRUD, unit merge, food inherit fields, unit conversions, properties, and property types.

Toggle sections take off or on and default to off.

Section

Env var

Contents

cooklog

TANDOOR_MCP_COOKLOG

Cook-log entries: when and how often a recipe was made.

recipe-books

TANDOOR_MCP_RECIPE_BOOKS

Recipe books (collections) and their entries.

ai

TANDOOR_MCP_AI

AI providers, AI recipe import from images, AI step sort and property estimation, AI logs.

import-export

TANDOOR_MCP_IMPORT_EXPORT

Recipe import and export, import queues, bookmarklet and open-data imports, their logs.

household-space

TANDOOR_MCP_HOUSEHOLD_SPACE

Spaces, memberships, households and household assignment, users, groups, invite links, user preferences. Only the space owner can use the household tools and update_user_space; Tandoor answers space admins with a 403.

admin

TANDOOR_MCP_ADMIN

Server settings, access tokens, storages, syncs, connectors, automations, user files, view logs, search settings, localization.

A delete preview (preview_*_delete_*) belongs to the same section and tier as its delete tool.

These tools are always on, whatever the section settings: list_tool_groups, enable_tool_group, disable_tool_group, get_version, jq_query, jq_stash_stats, get_guard_stats, and get_current_space. Every tandoor:// resource and every prompt is also always available. list_tool_groups reports them as the always group.

The server applies the settings in this order:

  1. TANDOOR_MCP_INCLUDE_ONLY and TANDOOR_MCP_EXCLUDE filter the tool list. EXCLUDE is a hard block: nothing can enable an excluded tool.

  2. A section env var that is set and not empty or whitespace-only decides that section.

  3. For a section whose env var is unset, empty, or whitespace-only, the saved section for this TANDOOR_URL decides.

  4. Every other section takes its default.

The result decides which of the remaining tools are visible at startup. An off section is hidden.

In stdio mode the LLM can change sections during a session:

  • enable_tool_group({group, tier?}) widens a section: off to simple or full, or simple to full. It never narrows a section. For a tiered section, tier is simple or full and defaults to full. Passing tier for an on/off section is an error.

  • disable_tool_group({group}) sets a section to off. It cannot disable always.

  • enable_tool_group({group: "always"}) succeeds and changes nothing.

If you see only some tools in Claude Desktop or Codex, ask the model to enable a section, for example "enable the cooklog section". If the new tools do not appear, restart the app. If the change was saved, it applies on the next start.

A section with no registered tools does not count as a section at runtime. That covers any section that INCLUDE_ONLY or EXCLUDE empties. enable_tool_group and disable_tool_group reject it as unknown, and list_tool_groups and the server instructions leave it out.

From an active session, call list_tool_groups for a live listing of sections and their tools.

Saved sections

When enable_tool_group or disable_tool_group changes a section, it saves the change, so the change survives a restart. disable_tool_group saves an explicit "off". The server saves sections per Tandoor instance, keyed by TANDOOR_URL. The key is the URL origin only: the scheme, host, and port, lowercased, with a default port dropped. The server ignores any path, query, or trailing slash, so https://host/tandoor and https://host share one entry. These are the same rules the server applies to TANDOOR_URL, including adding https:// to a URL without a scheme.

The server matches keys in the file by the same rules, so a key you write by hand, such as "https://Tandoor.example.com/tandoor", still matches. A save updates that entry under its key as written.

The file is $XDG_CONFIG_HOME/tandoor-mcp/sections.json. When XDG_CONFIG_HOME is unset or is not an absolute path, the file is ~/.config/tandoor-mcp/sections.json. The path is the same on every OS.

{"https://tandoor.example.com": {"recipes": "full", "meal-plan": "full", "cooklog": "on"}}

Inside each entry, the keys are the section names from the tables above: recipes, meal-plan, shopping, inventory, foods, cooklog, recipe-books, ai, import-export, household-space, and admin. Like the env vars, saved values ignore case and surrounding spaces, so "FULL" works.

  • HTTP mode reads saved sections at startup but never changes them.

  • A missing file is normal and gives no warning.

  • If the file exists but cannot be read, is not valid JSON, has any invalid section value, or has two or more keys that match the same instance, the server ignores the whole file and starts from the env settings. It prints a warning to stderr that names the file.

  • If you save a change while the file is invalid, the server replaces the file with a new one that holds only that change.

  • If a save succeeds and the section's env var is set, the tool result notes that the env var will override the saved value on restart.

  • If saving fails, the change still applies for the current session. The tool result says that the change was not saved.

  • The server ignores saved entries for sections that are filtered out or no longer exist, and keeps them in the file.

  • The server ignores a key it cannot parse as a URL, and keeps it in the file.

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})

Preview a destructive delete before running it:

You: "Delete the 'Test Keyword' keyword."

Claude:

  1. preview_keyword_delete_protecting({id: <k>}) to see what recipes still reference it

  2. If safe: delete_keyword({id: <k>})

  3. If not safe: reports the reference list back to you before proceeding

Destructive tools

Destructive tools (delete_*, merge_*, switch_active_space, create_access_token, create_invite_link) are irreversible or expose escalation surface. Their descriptions instruct the model to:

  • For deletes on tree-shaped resources, call the matching preview_*_delete_{cascading,nulling,protecting} first.

  • For merges, verify numrecipe counts and base-unit compatibility first.

  • For token / invite creation, warn the user before generating the call. Every such description leads with an explicit ESCALATION SURFACE line.

Operators who want them gone entirely can set TANDOOR_MCP_EXCLUDE="delete_*,merge_*,switch_active_space,create_access_token,create_invite_link". The permission config in Recommended Claude Code permissions makes Claude Code ask before any destructive call.

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 to Sunday meal plan entries, slimmed to {id, date, meal_type, recipe_name, servings, note}

tandoor://pantry/on-hand

Inventory entries by location, plus on-hand foods with no entry; at most 500 of each

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 at most 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

Contributing

See CONTRIBUTING.md for how pull requests are reviewed, credited, and merged.

Support, security and privacy

  • SUPPORT.md: where to ask questions and what to include in a bug report.

  • SECURITY.md: supported versions, how to report a vulnerability, and the remote-mode threat model.

  • PRIVACY.md: what the server stores, where data goes, and what it logs.

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.

  • Storage token / password and AI-provider api_key are redacted in slim reads. format: "full" still surfaces them for operator inspection. Default (LLM-facing) responses never leak credentials into the model's context.

  • Keyword payloads are capped at 50 entries and projected to {id, name} before being forwarded into writes; stops amplification and mass-assignment exposure.

  • Every mint-a-token / grant-access tool description leads with an ESCALATION SURFACE warning. create_access_token, update_access_token, create_invite_link, update_invite_link, and authenticate all warn in-context that the returned token bypasses this MCP's own bearer redaction.

  • Bearer tokens are redacted from every error message and log line.

  • HTTP transport binds to 127.0.0.1 by default. TANDOOR_MCP_HTTP_HOST changes the address. Each request gets a fresh MCP session, so no session state builds up across requests.

  • Remote mode uses OAuth with per-user Tandoor tokens. Stored Tandoor tokens are encrypted with TANDOOR_MCP_SECRET_KEY, issued tokens are stored only as hashes, and Host and Origin headers are checked. See Remote mode security and SECURITY.md.

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 one exposed to the public internet with anonymous sharing, the hardening above matters.

License

MIT

Available Tools

46 tools
add_inventory_itemAdd inventory itemA

Add food to inventory. Required: food_id, unit_id, amount (> 0), location_id. Optional: expires (YYYY-MM-DD), sub_location, note, code. Always creates a new entry, even when the same food already has an entry at that location.

NameRequiredDescriptionDefault
codeNo
noteNo
amountYes
formatNo
expiresNo
food_idYes
unit_idYes
location_idYes
sub_locationNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly=false, destructive=false and idempotent=false; the description reinforces this by explicitly warning that repeated calls always produce a new entry rather than merging. What is missing is any statement about failure behavior (e.g., invalid food_id or location_id) or whether permissions are required.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the action and immediately followed by required/optional field lists. The required/optional enumeration partly restates the schema, which is mild redundancy, but it makes the definition scannable without padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter mutation tool with no output schema and no per-field schema descriptions, the definition covers the core write semantics but leaves gaps: what format controls, where the ID values come from, and what the tool returns or errors on. It is adequate to call correctly in the happy path but not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage across 9 parameters, the description carries the load well: it enumerates all four required fields and four of the five optional ones, plus the YYYY-MM-DD format for expires and the >0 constraint on amount. The only undocumented parameter is format (slim/full), and the description never explains that the *_id values come from list_foods, list_units and list_inventory_locations.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Add food to inventory") and clarifies that it always creates a new entry rather than updating. It does not explicitly name the sibling alternatives (consume_inventory_item, move_inventory_item), but the create semantics are unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The line "Always creates a new entry, even when the same food already has an entry at that location" gives useful usage context for avoiding accidental duplicates. However, there is no explicit guidance on when to use this versus consume/move/update flows, or on prerequisites such as the food existing via create_food.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_recipe_to_shopping_listAdd recipe to shopping listA
Destructive

Add a recipe's ingredients to the shopping list at N servings. Omit ingredients[] to add all. Set servings=0 with list_recipe (id) to delete that shopping-list-recipe.

NameRequiredDescriptionDefault
idYesRecipe ID
servingsNoDefault 1. Use 0 with list_recipe to delete.
ingredientsNoIngredient IDs to include. Omit for all.
list_recipeNoExisting shopping-list-recipe id to update

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this as a non-read-only, non-idempotent, destructive write, so the safety profile is covered. The description adds the important behavioral detail that the tool doubles as a delete path via servings=0 with list_recipe. It says nothing about duplicate handling, whether the list is appended versus overwritten, or what happens to already-checked entries.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short, front-loaded sentences with no filler. The core add behavior comes first, followed by the two conditional exceptions, which is the right order for an agent skimming the definition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter mutation tool with full schema coverage and annotations, the description covers the add, all-ingredients, and delete workflows. It stops short of describing the update path through list_recipe or duplicate/append behavior, which a cautious agent might want before calling a destructive write.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3 and the schema already describes id, servings, ingredients, and list_recipe. The description reinforces the ingredients-omission and servings=0 deletion semantics but adds no syntax or format detail beyond what the schema states. The interaction between servings scaling and list_recipe updating is left implicit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: "Add a recipe's ingredients to the shopping list at N servings," which tells an agent exactly what the tool does. It does not name a sibling alternative (e.g., create_shopping_entry or food_shopping_update), so differentiation has to be inferred from the resource being a recipe.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states two concrete conditions: omit ingredients[] to include all ingredients, and use servings=0 with list_recipe to delete an existing shopping-list-recipe. That is clear how-to-use guidance for the parameters, but there is no when-to-use guidance relative to sibling tools that also write shopping entries.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

bulk_check_shopping_entriesBulk check shopping entriesB
Idempotent

Bulk check or uncheck many shopping entries by ID list.

NameRequiredDescriptionDefault
idsYes
checkedYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a non-read-only, idempotent, non-destructive mutation, so the safety profile is covered. The description adds the core behavior that it sets the checked state in bulk, but it omits important bulk-write traits such as partial-failure handling, permission requirements, and return behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence with no filler; every word contributes to stating the operation and its inputs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter bulk mutation with rich annotations and no output schema, the description covers the core operation adequately. It omits bulk-write details such as partial-failure behavior and whether all IDs must belong to the same shopping list.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It maps 'ids' to an ID list and 'checked' to check/uncheck, clarifying both parameters' meaning, but it does not specify edge cases such as duplicate or invalid IDs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb phrase ('Bulk check or uncheck') and names the resource ('shopping entries') plus the selector ('by ID list'). It does not explicitly differentiate from siblings such as bulk_update_shopping_entries or update_shopping_entry, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, prerequisites, or alternatives are provided. It does not say when to choose this over update_shopping_entry or bulk_update_shopping_entries, so the agent must infer that this is for setting only the checked flag on multiple entries.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

bulk_update_shopping_entriesBulk update shopping entriesA
Idempotent

Update many shopping entries in one call. Required: ids (entry ids; ids that do not exist or are not visible to you are skipped). Give checked, a list change, or both. checked: true checks every entry and sets completed_at to now, also on entries already checked; without checked, checked and completed_at stay as they are. List changes do not update the entries' updated_at. List changes: shopping_lists_add and shopping_lists_remove (may be combined), shopping_lists_set (replaces the lists; must not be empty) or shopping_lists_remove_all: true (takes every list off). set and remove_all must be used alone. Empty arrays and shopping_lists_remove_all: false count as no change and are not sent. An id may not appear in both shopping_lists_add and shopping_lists_remove. Every list id is checked against list_shopping_lists first; unknown or repeated ids are rejected and nothing is written.

NameRequiredDescriptionDefault
idsYes
checkedNo
shopping_lists_addNo
shopping_lists_setNo
shopping_lists_removeNo
shopping_lists_remove_allNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=true), yet the description still adds real behavioral context: nonexistent or invisible ids are silently skipped, list changes do not bump updated_at, and unknown or repeated list ids cause rejection with nothing written. The only gap is that it never says what the response looks like. Minor tension exists between the always-reset completed_at behavior and idempotentHint, which the author does at least disclose.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It front-loads the required parameter and the checked/list-change decision, then moves through constraints in a logical order. The prose is telegraphic and dense, with several run-on clauses, but nearly every sentence states a real constraint an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a six-parameter bulk mutation with no output schema, the description covers inputs, atomicity, and side effects well. It stops short of stating the return value or partial-success semantics beyond 'nothing is written', which leaves the agent guessing about what a successful call hands back.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description carries the full burden and does so thoroughly: it explains ids, checked (including completed_at side effect), all four list-mutation parameters, the add/remove mutual exclusion, and that empty arrays or remove_all=false are treated as no change. This is effectively a prose specification of a completely undocumented schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource plus scope: 'Update many shopping entries in one call.' That separates it from the singular update_shopping_entry, and the detailed list-mutation semantics distinguish it from bulk_check_shopping_entries. It never names a sibling explicitly, so an agent must infer the routing rather than read it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Give checked, a list change, or both' tells the agent the valid invocation shapes, and 'set and remove_all must be used alone' is an explicit exclusion. However, there is no guidance on when to prefer this over bulk_check_shopping_entries or looping update_shopping_entry, so usage is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

consume_inventory_itemConsume inventory itemA

Use up some or all of an inventory entry. Identify it by entry_id, or by food_id with optional location_id (errors listing the candidates when several entries match). Give exactly one of amount (> 0) or all: true. Optional unit_id must match the entry unit; there is no unit conversion. The amount never goes below 0: consuming more than is on hand sets it to 0 and returns a warning. Never deletes the entry; at 0 (including after all: true) it is hidden from list_inventory_entries unless include_empty is true. Not atomic: two concurrent consumes of one entry can lose an update.

NameRequiredDescriptionDefault
allNo
amountNo
formatNo
food_idNo
unit_idNo
entry_idNo
location_idNo

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only assert readOnlyHint=false, destructiveHint=false, idempotentHint=false; the description goes far beyond by disclosing that the entry is never deleted, that over-consumption clamps to 0 and returns a warning, and that zeroed entries disappear from list_inventory_entries unless include_empty is true. It also volunteers a genuine hazard the annotations cannot express: the operation is not atomic and concurrent consumes can lose an update. That is exactly the context an agent needs before retrying or parallelizing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but disciplined: identification, exclusivity rule, unit constraint, clamping behavior, visibility side effect, then the concurrency caveat, roughly in priority order. Every sentence carries operational weight. The nested parentheticals make it slightly slower to parse than it needs to be, but nothing is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation with no output schema and no annotation coverage of side effects, the description supplies the failure modes, the clamping semantics, and the visibility change that an agent must anticipate. What is missing is any statement about the return payload's shape beyond "a warning", and the purpose of the format parameter, which is the one loose end for a tool with this many knobs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage the description carries the full burden, and it explains six of the seven parameters meaningfully (entry_id, food_id, location_id, amount>0, all: true, unit_id must match with no conversion). The gap is format (slim/full), which is neither described here nor in the schema, leaving one enum unexplained. Strong compensation overall, but not complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Use up some or all of an inventory entry" is a specific verb+resource pair that is immediately distinguishable from add_inventory_item and move_inventory_item among its siblings. The description also states the scoping rule (never deletes, floors at 0), so an agent knows the operation is a partial-state mutation rather than a create/delete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit selection rules for identifying the entry (entry_id, or food_id plus optional location_id, with an error listing candidates on ambiguity) and an exclusive-choice rule for amount vs all: true, plus the constraint that unit_id must match with no conversion. What it omits is a pointer to any alternative tool (e.g. move_inventory_item when relocating rather than consuming), so it stops short of naming when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_foodCreate foodA
Idempotent

Create food. Required: name. Optional: plural_name, description, food_onhand, fdc_id, supermarket_category_id, shopping_list_ids (ids from list_shopping_lists). If a food with this name exists, Tandoor returns it instead of creating one. With shopping_list_ids (including []), the tool looks up the name first and, if a food with that name exists (ignoring case and surrounding spaces), refuses and changes nothing; use update_food. Tandoor also returns an existing food whose plural name matches; the tool detects that from the create reply and refuses the same way, setting no lists. With non-empty shopping_list_ids, the tool creates the food first and then sets its lists, because Tandoor cannot set lists while creating a food. With any shopping_list_ids (including []), if a step after the create fails, the error gives the new food's id and says not to retry. Changing a food's lists does not change its existing shopping entries. add_recipe_to_shopping_list copies the food's lists onto new entries. create_shopping_entry without shopping_list_ids copies them when the user preference shopping_update_food_lists is on. bulk_create_shopping_list_recipe_entries without shopping_list_ids copies each food's lists whatever the user preference. Every list id is checked against list_shopping_lists first; unknown or repeated ids are rejected and nothing is written. If the lists after the write differ from the request, the tool errors and names the missing and the extra lists.

NameRequiredDescriptionDefault
nameYes
fdc_idNo
formatNo
descriptionNo
food_onhandNo
plural_nameNo
shopping_list_idsNo
supermarket_category_idNo

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, idempotentHint=true), it discloses the non-obvious traits: returning an existing food instead of creating, refusing and changing nothing on name/plural-name collisions, creating then setting lists because Tandoor cannot do both at once, rejecting unknown or repeated list ids before any write, and telling the agent not to retry after a partial failure. It also explains downstream list-copying side effects in related tools. This is exactly the behavioral context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening is well front-loaded (verb, required, optional). But the remainder is a dense run-on chain of conditionals covering cross-tool list-copying behavior, with some tangential material (add_recipe_to_shopping_list, shopping_update_food_lists preference) that an agent creating a food rarely needs. Information density is high but readability suffers.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter mutation tool with no output schema and zero schema descriptions, the description covers collision, refusal, ordering, and failure semantics thoroughly. The remaining shortfall is the undocumented `format` parameter and no indication of what the create reply contains, which matters since the tool inspects that reply to detect plural-name matches.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, and it does well for shopping_list_ids (provenance via list_shopping_lists, empty-list semantics, validation). However, it merely lists plural_name, description, food_onhand, fdc_id, and supermarket_category_id without explaining their meaning or effect, and the `format` enum (slim/full) is never mentioned at all, leaving a real gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource ("Create food") and immediately scopes it by enumerating the required and optional inputs. It clearly distinguishes itself from siblings by naming update_food and list_shopping_lists as the alternate paths, so an agent can route without opening another schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete conditions: if a food with this name exists, Tandoor returns it; with shopping_list_ids and an existing name, the tool refuses and the agent should use update_food. That is strong when-to-use routing. It lacks a plain statement of when to prefer create_food over update_food outside the collision case, but the conditional guidance is unusually explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_meal_planCreate meal planC

Create meal plan. Required: from_date (ISO), meal_type_id, servings. Optional: recipe_id, title, note, addshopping

NameRequiredDescriptionDefault
noteNo
titleNo
to_dateNo
servingsYes
from_dateYes
recipe_idNo
addshoppingNo
meal_type_idYes

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a non-readonly, non-destructive, non-idempotent write, so safety is partly covered. But the description adds nothing beyond a parameter list and never explains the notable side effect implied by 'addshopping' (adding ingredients to a shopping list) or whether a meal plan can span multiple days via to_date. For a mutation tool this leaves real behavioral questions unanswered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the verb and structured as required-then-optional, so there is no wasted wording. The brevity is under-specification rather than tight editing, though, and the required/optional enumeration duplicates the schema's own required array.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 8 parameters, zero schema descriptions, no output schema, and a side-effecting write operation, the definition should do far more than list names. It neither covers to_date nor explains return behavior, so an agent cannot confidently call it for anything but the simplest case.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 8 parameters, so the description must carry the meaning and it only partly does. It does add a useful format hint for from_date '(ISO)', but it never explains servings (per person? per plan?), what addshopping actually triggers, what happens when recipe_id is omitted, and it omits the to_date parameter entirely even though it exists in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with the specific verb+resource 'Create meal plan', which cleanly separates it from the sibling update_meal_plan, delete_meal_plan and get_meal_plan. It does not, however, state what a meal plan is scoped to (current space, user) or contrast itself with any alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance: nothing says when a caller should create a plan versus updating one, nor any prerequisite such as the meal_type_id or recipe_id having to exist first. The only 'guidance' is the required/optional parameter split, which the schema already encodes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_recipeCreate recipeC

Create recipe. Required: name, steps[{instruction, ingredients[{food, amount, unit?}]}]. Optional: description, servings, working_time, waiting_time, keywords[]

NameRequiredDescriptionDefault
nameYes
stepsYes
formatNoResponse detail level. Default "slim".
privateNo
internalNo
keywordsNo
servingsNo
nutritionNo
propertiesNo
source_urlNo
descriptionNo
waiting_timeNo
working_timeNo
servings_textNo
show_ingredient_overviewNo

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already state it is a non-destructive, non-idempotent write with no open-world access, so the baseline bar is low, yet the description adds nothing beyond them. It does not say whether duplicate names are rejected, what happens with private/internal flags, or what the response contains.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Compact and front-loaded: the required parameters come before the optional ones, and the nested syntax is compressed into bracket notation with zero wasted words. The terse notation is dense but readable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 15-parameter nested-object creation tool with no output schema and no annotations about response shape, the description is far too thin. It leaves the majority of parameters undocumented and says nothing about what the created recipe looks like or how defaults are applied.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 7%, so the description must compensate, and it does partially by marking name and steps as required and sketching the nested steps/ingredients shape with unit optional. However, it omits 8 of the 15 parameters (format, private, internal, nutrition, properties, source_url, servings_text, show_ingredient_overview) and the per-step 'time' and ingredient 'note' fields, leaving large gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Create recipe'), which distinguishes it from update_recipe and get_recipe. It does not, however, distinguish it from import_recipe_from_url or explain how it relates to create_meal_plan.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description only lists required and optional fields; it gives no guidance on when to use create_recipe instead of import_recipe_from_url or create_meal_plan, and no prerequisites are stated. Usage is left entirely implied by the tool name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_shopping_entryCreate shopping entryA

Create a shopping list entry. Required: amount, food_id. Optional: unit_id, checked, list_recipe, ingredient, order, delay_until, mealplan_id (links to existing/new ShoppingListRecipe for that mealplan), shopping_list_ids. shopping_list_ids (ids from list_shopping_lists) puts the entry on exactly those lists; the food's lists are not added. When shopping_list_ids is omitted, Tandoor copies the food's lists onto the new entry if the user preference shopping_update_food_lists is on. With [], the tool clears any lists Tandoor copied, so the entry is on no list. add_recipe_to_shopping_list always copies each food's lists; food_shopping_update never does. Changing a food's lists later does not change existing entries. Every list id is checked against list_shopping_lists first; unknown or repeated ids are rejected and nothing is written. If the lists after the write differ from the request, the tool errors and names the missing and the extra lists.

NameRequiredDescriptionDefault
orderNo
amountYes
formatNo
checkedNo
food_idYes
unit_idNo
ingredientNo
delay_untilNo
list_recipeNo
mealplan_idNo
shopping_list_idsNo

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnly=false, idempotent=false, destructive=false), the description discloses hidden behavior: dependence on the user preference shopping_update_food_lists, the fact that list ids are validated before any write, that unknown or repeated ids reject the whole call, and that a post-write list mismatch produces a named-difference error. That is exactly the kind of side-effect and failure detail the annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The required/optional inventory is helpfully front-loaded, but the body is a dense wall of nested clauses that circles back to shopping_list_ids twice and spends sentences on Tandoor internals (later food-list edits not affecting existing entries) that are marginal for invocation. It is information-rich but not tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter mutation tool with no output schema and no field-level schema docs, the description is largely sufficient: it covers required inputs, the list-resolution contract, and error behavior. The remaining gap is that several optional parameters and the format enum are left undefined, so an agent cannot construct every valid call from the description alone.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage across 11 parameters, the description compensates well for the hardest ones: shopping_list_ids gets a full semantic model (validate, copy, treat [] as clear) and mealplan_id explains the link to ShoppingListRecipe. However, `format` (the one enum parameter, slim/full) is never mentioned, and order, checked, delay_until, ingredient and list_recipe are only named without meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb and resource ('Create a shopping list entry'), and the rest distinguishes it from the two sibling tools that also touch shopping lists by contrasting their list-copying behavior. An agent can identify what this does relative to add_recipe_to_shopping_list and food_shopping_update without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly establishes the required/optional split and explains the decision point for shopping_list_ids (omit vs explicit ids vs []), with sibling comparisons that help selection. It stops short of an explicit 'use this instead of update_shopping_entry when...' statement, so routing against the other write tools is left partly to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_meal_planDelete meal planC
DestructiveIdempotent

Delete meal plan by ID

NameRequiredDescriptionDefault
idYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the safety profile is covered structurally. The description adds nothing beyond that: it does not say whether the delete is permanent or soft, whether child entries cascade, or what happens when the ID does not exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Five words, front-loaded with the verb and free of boilerplate. It is tight rather than padded; the shortfall is under-specification, not verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation the definition is thin: one undocumented parameter, no output schema, and no statement of consequences or error behavior. The annotations cover the read/write and idempotency signals, but an agent still lacks the information needed to call this safely in a multi-step workflow.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the meaning of the single required parameter — and it offers only the redundant phrase "by ID". It never clarifies that the ID must reference an existing meal plan, nor does it address the number type the schema declares.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Delete meal plan") plus the lookup key ("by ID"), which cleanly separates it from get_meal_plan and update_meal_plan in the sibling list. It lacks any qualification of scope (soft vs. permanent delete) but the core action is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this versus update_meal_plan or get_meal_plan, and no preconditions such as needing a prior get_meal_plan lookup to obtain the ID. The agent must infer everything from the name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_shopping_entryDelete shopping entryC
DestructiveIdempotent

Delete a shopping entry by ID.

NameRequiredDescriptionDefault
idYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the safety profile is covered by structured data. The description adds nothing beyond that: it does not say whether the deletion is permanent or recoverable, what happens if the ID does not exist, or whether it errors on a missing entry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler or redundancy. It is efficient, though the brevity edges into under-specification rather than pure conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a destructive mutation with no output schema and no annotation-independent context in the description. An agent is left not knowing the outcome of a successful deletion, the failure mode for an unknown ID, or whether dependent shopping list totals are affected.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden, yet it only says 'by ID' without clarifying that the number is the shopping entry identifier, where that ID comes from (e.g., list_shopping_entries), or any format constraints. This is minimal compensation for an undocumented parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource ('Delete a shopping entry') plus a scoping constraint ('by ID'), which clearly separates it from get_shopping_entry and update_shopping_entry. It stops short of explicitly naming a sibling or distinguishing itself from bulk deletion, so it is clear but not maximally differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this instead of bulk_check_shopping_entries, bulk_update_shopping_entries, or update_shopping_entry, and no stated preconditions such as needing the entry to exist. The agent must infer all of this from the tool name and siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

disable_tool_groupDisable tool groupA
Idempotent

Turn a section off so all its tools disappear from tools/list. The SDK emits tools/list_changed automatically. The "always" section cannot be disabled. Use this to free context budget once a workflow no longer needs a section.

NameRequiredDescriptionDefault
groupYesName of the section to turn off. The "always" section cannot be disabled.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false), and the description adds context beyond them: the group's tools vanish from tools/list and the SDK emits tools/list_changed automatically, so the agent knows the tool-list changes without re-listing. It stops short of saying what happens on an unknown group name, whether the change persists across sessions, or what is returned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with the primary effect, then the automatic notification, then the constraint, then the use case. Nothing is redundant or padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter, non-destructive, idempotent toggle with annotations and no output schema, the description covers effect, side-effect notification, and the one restriction. Only the error/return behavior for an invalid group name is left implicit, a minor gap given no output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single 'group' parameter is already described there, including the fact that 'always' cannot be disabled. The description restates the same constraint and adds no naming-format or discovery guidance, so the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('turn a section off') and resource ('tool group'), plus the concrete effect: all its tools disappear from tools/list. That effect alone separates it unambiguously from enable_tool_group in the sibling list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger: 'Use this to free context budget once a workflow no longer needs a section.' It also states the exclusion that the "always" section cannot be disabled. It does not name enable_tool_group as the inverse operation, so routing is clear but not fully spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

enable_tool_groupEnable tool groupA
Idempotent

Widen a section so its tools become visible in tools/list. For a tiered section, tier "simple" or "full" (default full) picks how much to show; on/off sections take no tier. Enabling never narrows a section: asking for simple on a section already at full leaves it at full. The SDK emits tools/list_changed automatically; the client refreshes its tool list mid-conversation. Be sparing: every enabled tool adds its schema to your context budget. Run list_tool_groups first to see what is available.

NameRequiredDescriptionDefault
tierNoTier for a tiered section (default full). Not accepted for on/off sections.
groupYesName of the section to enable. Run list_tool_groups to see available sections.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=false) it discloses the actual side effect: the SDK emits tools/list_changed and the client refreshes mid-conversation. It also states the monotonicity rule — enabling never narrows, so simple on an already-full section leaves it at full — which concretely explains the idempotentHint rather than restating it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Five short sentences, front-loaded with the effect before the arguments and the cost warning. The SDK/tools-list_changed sentence carries two clauses but each conveys a distinct consequence, so nothing is padding; it could be slightly tighter but is not bloated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter, non-destructive operation with annotations and no output schema, the description covers effect, arguments, side effects, and prerequisite. The remaining gap is what the call itself returns (a confirmation, or the refreshed tool list) — minor since the tool list refresh is already explained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, and the description goes past it by explaining tier semantics: default full, rejected for on/off sections, and the non-narrowing behavior when the requested tier is lower than the current one. It does not add anything about the group parameter beyond what the schema already says.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

It states a concrete effect: widening a section so its tools appear in tools/list, which is clearly not what disable_tool_group or list_tool_groups does. The only friction is terminology — the tool is named *_tool_group but the body consistently says "section," so the agent must map group=section on its own.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It names a prerequisite ("Run list_tool_groups first") and a selection rule for the tier argument (simple/full, default full, not accepted on on/off sections). It also gives a usage constraint — "Be sparing: every enabled tool adds its schema to your context budget" — which tells the agent when not to call it, something most definitions omit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

food_shopping_updateUpdate food on shopping listsA
Destructive

Add a food to active shopping lists with optional amount/unit. Pass delete=true to remove this food from all active lists.

NameRequiredDescriptionDefault
idYes
amountNo
deleteNo
unit_idNo

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and non-idempotent, and the description adds the critical scope detail that deletion applies to ALL active lists, not just one. It does not state what happens when the food is absent from a list or whether amount/unit_id are ignored in delete mode.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the primary add behavior and followed by the destructive mode. 'this food' is mildly ambiguous in a standalone description but costs little.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter mutation with no output schema, the description covers the modes and destructive scope but leaves gaps: error behavior for unknown ids, whether the operation is a no-op when the food is not listed, and the relationship between amount and unit_id.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate; it explains amount, unit, and delete, and implies id refers to the food. But 'id' is never explicitly identified as a food id, and there is no statement of whether unit_id is required when amount is supplied.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the resource (a food on active shopping lists) and both modes: add with optional amount/unit, or remove via delete=true. It is clear, though the name 'update' slightly undersells the add/remove duality, and no sibling tools (create_shopping_entry, update_shopping_entry) are named to distinguish it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives the trigger for the delete mode ('Pass delete=true to remove...'), which is useful, but provides no guidance on when to prefer this over create_shopping_entry or update_shopping_entry, and no prerequisites such as the food already existing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_current_spaceGet current spaceC
Read-onlyIdempotent

Get the space currently active for this API token.

NameRequiredDescriptionDefault
formatNo

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and closed-world behavior, so the safety profile is covered. The description adds only that the result depends on the calling token's active space, which is genuinely useful context, but says nothing about the response shape or whether the space can change between calls.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One front-loaded sentence with no filler. It is as short as it can be, though its brevity is arguably under-specification rather than disciplined conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description carries the burden of explaining what a 'space' is and what the caller receives, and it does neither. The only parameter is also left unexplained, leaving an agent unable to predict the result or choose a format.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the single 'format' parameter (enum slim/full) is completely undocumented in both schema and description. The description does not explain what slim versus full returns, which is exactly the information an agent needs to choose a value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get the space') with the scoping qualifier 'currently active for this API token', which no sibling tool duplicates. It is clear what the tool returns conceptually, though what a 'space' contains is never defined.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to call this versus other context/introspection tools (e.g. get_version) or what an agent should do with the result. The token-scoping hint implies a purpose but does not state a use condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_foodGet foodC
Read-onlyIdempotent

Get food by ID.

NameRequiredDescriptionDefault
idYes
formatNo

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, non-destructive, and closed-world, so safety is covered structurally. The description adds nothing beyond that — notably it never explains what the 'format' flag does (slim vs full responses), which is the one genuinely behavioral detail worth disclosing for a read tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four words, front-loaded, with zero filler. It is terse rather than padded, so the only criticism is under-specification rather than verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter read tool with full annotation coverage and no output schema, the minimal description is nearly adequate. The unresolved gap is the 'format' parameter and any statement of what is returned or what happens on a missing ID.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden and fails: it only restates that 'id' identifies the food and says nothing about the optional 'format' parameter or what 'slim' versus 'full' return. The enum values are visible in the schema but their effect is undefined anywhere.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a concrete verb and resource ('Get food by ID'), so the basic action is clear. However, it offers no differentiation from siblings such as list_foods, create_food, or update_food, and does not clarify whether 'food' is a catalog item, inventory entry, or recipe ingredient.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this lookup versus list_foods or search_recipes, and no mention of prerequisites or fallback behavior when the ID does not exist. The agent must infer usage entirely from the name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_guard_statsGet guard statsA
Read-onlyIdempotent

Inspect security-guard rejection counters (PathGuardError, SsrfBlockedError) since process start. Useful for dashboards and "is anything probing me?" checks.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already cover safety (readOnlyHint, idempotentHint, non-destructive, closed-world), so the description only needs to add operational context. It usefully discloses the key scoping fact that counters are "since process start" (i.e., reset on restart), but says nothing about the response shape or whether values are cumulative counts, which matters for a metrics tool with no output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with what is inspected, followed by the practical use case. No filler or redundant restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple parameterless read, the description covers what is measured and the reset window, which is the essential part. However, with no output schema, the description never indicates what the returned object looks like (counter names, nesting, totals), leaving a real gap for an agent trying to consume the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline applies. The schema is empty and fully consistent with a parameterless stats read.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ("Inspect") and a specific resource ("security-guard rejection counters") and even names the concrete counter types (PathGuardError, SsrfBlockedError). It does not need to differentiate from siblings, since none of the listed tools are analogous, but it also doesn't explicitly frame itself against anything else.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives two concrete use contexts: dashboards and "is anything probing me?" checks. That is clear positive guidance, though there are no stated exclusions or pointers to an alternative tool when a deeper security audit is needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_keywordGet keywordC
Read-onlyIdempotent

Get keyword by ID.

NameRequiredDescriptionDefault
idYes
formatNo

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this as read-only, idempotent, non-destructive, and closed-world. The description adds no behavioral context such as what the 'format' parameter changes, what fields are returned, or how missing IDs behave.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The single sentence is front-loaded and free of filler. However, brevity here veers into under-specification rather than efficient communication.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with annotations and no output schema, the description is too sparse. It leaves the 'format' parameter unexplained and provides no clue about return shape or when to prefer this over list_keywords.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter meaning, but it only restates that lookup is by ID. The 'format' parameter with its slim/full enum is completely undocumented and its effect is undefined.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Get') and resource ('keyword') scoped to lookup by ID. It is clear what the tool does, but it does not distinguish itself from the sibling list_keywords tool or clarify why one would retrieve a single keyword.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus list_keywords or other lookup tools. The only implied usage is retrieving a known ID, but that is not stated as a condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_meal_planGet meal planC
Read-onlyIdempotent

Get meal plan by ID

NameRequiredDescriptionDefault
idYes

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered by structured fields. The description adds nothing beyond that — no note on what happens if the ID does not exist, no auth/space context, no mention of shape or size of the returned plan.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four words, zero padding and front-loaded, which is structurally sound. However, the brevity comes at the cost of under-specification rather than true conciseness — nothing beyond the title is conveyed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple and annotations carry the behavioral profile, but with no output schema the description should at least sketch what a meal plan record looks like or how a missing ID is surfaced. Neither is present, leaving the agent to call blind.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter has 0% schema description coverage, so the schema offers only 'number' with no meaning attached. 'By ID' merely confirms the id parameter identifies a meal plan; it gives no hint about where to obtain such an ID (e.g., from list_meal_plans) or whether the number is a global or space-scoped identifier.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Get') and resource ('meal plan') with a scoping qualifier ('by ID'), which distinguishes it from the sibling list_meal_plans. It is not a tautology, but it does not name the alternatives or clarify what a meal plan record contains.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this versus list_meal_plans (find one) or update_meal_plan/delete_meal_plan (operate on one). The agent must infer from the tool name alone that this is the single-record lookup path.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_meal_typeGet meal typeC
Read-onlyIdempotent

Get a meal type by ID.

NameRequiredDescriptionDefault
idYes
formatNo

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is fully covered elsewhere. The description adds nothing beyond that - no note on behavior for a missing ID (error vs empty), no indication of whether the lookup is cached or scoped to the current space.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler or redundancy. It is efficient, though its brevity comes at the cost of the missing detail noted elsewhere.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter read tool with rich annotations and no output schema, the description is still too thin: the slim/full format switch and the missing-ID behavior are the two things an agent most needs and neither is covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden, yet it only vaguely implies that 'id' identifies the meal type. The 'format' enum (slim vs full) is entirely unexplained - an agent cannot tell what changes between the two shapes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb (get) and resource (meal type) plus the lookup key (ID), which is clear enough to distinguish a single-item fetch from the sibling list_meal_types. It does not explicitly name that sibling, so it stops short of the 5 tier.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this versus list_meal_types or how to obtain a valid ID. No prerequisites, no exclusions, no mention of what to do when the ID is unknown.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_recipeGet recipeA
Read-onlyIdempotent

Get recipe by ID. Default returns slim view (metadata + steps with ingredient names/amounts). Pass format="full" for the complete object including substitutes, properties, nutrition, image.

NameRequiredDescriptionDefault
idYesRecipe ID
formatNoResponse detail level. Default "slim".

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered. The description adds real behavioral value by disclosing the default slim payload and what the 'full' format unlocks (substitutes, properties, nutrition, image), which shapes whether an agent needs a follow-up call. It omits error behavior for a missing ID.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the default behavior front-loaded and the opt-in escalation second. Every clause carries information an agent would otherwise have to discover by calling the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully compensates by describing the return shape at both detail levels. For a 2-parameter read tool with full annotations this is nearly complete; only missing-recipe behavior and pagination/limits are unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, and the description does add genuine meaning for 'format' by enumerating what slim returns versus what full adds. The 'id' parameter, however, gets no elaboration beyond the schema's 'Recipe ID'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Get recipe by ID') and immediately clarifies the two response modes, which lets an agent distinguish it from list_recipes/search_recipes siblings by its ID-keyed, single-record scope. It stops short of naming any sibling explicitly, so the differentiation is inferable rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: call this when you already have a recipe ID. There is no explicit guidance on when to prefer it over search_recipes or list_recipes, nor any note about what to do if the ID is unknown. Adequate but leaves the alternative-selection reasoning to the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_shopping_entryGet shopping entryC
Read-onlyIdempotent

Get a shopping list entry by ID.

NameRequiredDescriptionDefault
idYes
formatNo

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered elsewhere. The description adds nothing beyond that — no note on what is returned, whether missing IDs error or return null, or what the format variants change.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler or redundancy. It is efficiently written, though its brevity reflects under-specification rather than tight editing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with no output schema, the description should at minimum explain the format parameter's effect and the not-found behavior. Neither is present, and with 0% schema coverage nothing else fills the gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for two parameters, so the description carries the full burden and largely fails: it clarifies only that the required id is the entry identifier. The optional "format" enum (slim vs full) — the one parameter whose meaning an agent cannot guess — is never mentioned.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ("Get") and resource ("a shopping list entry") plus the lookup key ("by ID"), so an agent knows exactly what the call retrieves. It does not contrast itself with siblings such as list_shopping_entries or the update/delete variants, so sibling differentiation is left implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use or when-not-to-use guidance: nothing says to prefer list_shopping_entries when the ID is unknown, or that this is the single-entry counterpart of the list tool. The only hint is the phrase "by ID," which weakly implies a known identifier is required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_versionGet versionA
Read-onlyIdempotent

Report this MCP server's name/version and the Tandoor server version + compatibility status detected at startup (ok | unsupported | unknown). No arguments; answers from cached startup state without a network call.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the bar is lower. The description still adds real value beyond them: it discloses that results come from startup-cached state rather than a live call, and enumerates the compatibility values (ok | unsupported | unknown). It stops short of warning that cached state may be stale after a server change.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence carrying purpose, return contents, the status enum, and the no-network behavior. Nothing is redundant with the name or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description must convey return values, and it does: server name/version, Tandoor version, and a three-valued compatibility status. For a zero-argument read tool with full annotation coverage, nothing needed for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so the baseline is 4. The description confirms 'No arguments', which matches the empty schema exactly and removes any doubt an agent might have about needing a server identifier.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Report) and precisely names the three things returned: the MCP server's name/version, the Tandoor server version, and the compatibility status. No sibling tool in the list does anything similar, so an agent can select it unambiguously.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes the use case clear (diagnostic/version lookup) and notes that it takes no arguments and causes no network call, which implies it is the cheap first step. It does not explicitly state when *not* to use it or name an alternative, but no sibling overlaps.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

import_recipe_from_urlImport recipe from URLA

Import a recipe from a URL. Tries Tandoor's built-in scraper first, then fetches the page and extracts schema.org JSON-LD as a real fallback (works when Tandoor can't reach the URL or doesn't support the site). On total failure, throws with an attempts log — pass create_stub_on_failure=true to write an empty placeholder recipe instead. If all stages fail, recommend: (1) retry with create_stub_on_failure=true to capture the URL as a stub you can fill in later; (2) if the page is an image/PDF, use import_recipe_from_image (AI provider required); (3) if the URL is paywalled or JS-rendered, fall back to manual create_recipe with fields you can see.

NameRequiredDescriptionDefault
urlYesRecipe URL to import
nameNoOptional name for the stub recipe (only used if create_stub_on_failure=true and both scrapers fail)
formatNoResponse detail level. Default "slim".
create_stub_on_failureNoDefault false. When true AND both scraper attempts fail, create a minimal empty recipe pointing at the URL instead of throwing.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (which only say non-read-only, open-world, non-idempotent, non-destructive), the description discloses the internal fallback chain, the failure mode ('throws with an attempts log'), and the side effect of create_stub_on_failure writing an empty placeholder recipe. That is exactly the mutation and error behavior an agent needs before calling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The mechanism and its fallback are front-loaded, followed by a numbered recovery list that is easy to scan. The three numbered fallbacks are somewhat verbose for an agent that mainly needs the primary path, but each item maps to a real alternative tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, the description covers mechanism, failure behavior, stub creation, and recovery paths thoroughly. The only gap is that it never hints at what a successful response contains (e.g. what slim vs full return), which the agent must infer from the format enum.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter meaning the schema states only locally: create_stub_on_failure applies only when all stages fail, and name is only consumed in that stub path. It does not explain the slim/full format values beyond the enum, keeping it just short of a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource ('Import a recipe from a URL') and immediately distinguishes this tool's mechanism (Tandoor scraper, then schema.org JSON-LD fetch) from sibling importers such as import_recipe_from_image and the manual create_recipe. An agent can tell exactly what this tool does and does not cover.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit routing rules: use import_recipe_from_image for image/PDF pages (AI provider required), fall back to create_recipe for paywalled or JS-rendered URLs, and retry with create_stub_on_failure=true to capture a stub. When-to-use, when-not, and named alternatives are all present.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

jq_queryQuery stashed result with jqA
Read-onlyIdempotent

Run a jq filter against a previously stashed tool result and return the focused subset. Use this when a prior tool returned {stashed:true, handle, shape, sample_filters} instead of the full payload. Treat the stash like a JSON document the user already paid for — extract only what you need. Common filters: ".results | length", ".results[] | select(.id == 42)", ".results | map({id, name})", "keys", ".count".

NameRequiredDescriptionDefault
filterYesjq filter to apply to the stashed value. Examples: ".results | length", ".results[0]", ".results | map({id, name})", "keys", ".count".
handleYesStash handle from a prior tool result, e.g. "stash_<uuid>".

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context beyond that: the input is a previously stashed payload, the operation extracts only what is needed, and examples show the expected output shapes. It does not cover failure modes such as invalid filters or expired handles, so it stops short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the triggering condition before the filter examples. Every sentence is relevant, though the example filter list partially duplicates the schema's `filter` description, so it is slightly redundant rather than wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the burden of explaining returns and does so ('return the focused subset'), and it explains the stash lifecycle context that makes the handle meaningful. Missing are notes on what happens with an invalid filter or a stale handle, which would matter for a two-required-param query tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%: both `handle` (with a UUID pattern) and `filter` are fully documented in the schema, including examples. The description adds only the framing that the handle comes from a prior tool result, and its filter examples largely duplicate those already in the schema. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: run a jq filter against a previously stashed tool result, returning a focused subset. The concept of a 'stash' is defined well enough (a JSON document produced by a prior tool) that it is clearly distinct from the sibling jq_stash_stats, which reports on stashes rather than querying them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger condition: use this when a prior tool returned `{stashed:true, handle, shape, sample_filters}` instead of the full payload. That is a strong, checkable when-to-use signal. It does not name alternatives (e.g., jq_stash_stats) or state any when-not cases, which keeps it short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

jq_stash_statsShow stash statsA
Read-onlyIdempotent

Inspect the in-memory stash (count + total bytes). Diagnostic; not normally needed.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and a closed world, so the safety profile is fully covered by structured data. The description adds genuine context beyond that: the stash is in-memory, the response is a count plus byte total, and the tool is diagnostic in nature. It stops short of saying whether the stash is process-local or what counts toward the byte total, hence not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short clauses, zero filler, and the core resource is front-loaded ahead of the caveat. Nothing could be removed without losing either the purpose or the usage warning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-argument read-only diagnostic with no output schema, the description is nearly sufficient: it explains the resource, the return shape, and the intended (rare) usage. A small gap remains in not clarifying scope — whether the stash is shared across the space or local to the request.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the schema is trivially complete and there is nothing for the description to compensate for. Baseline for a no-parameter tool applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("inspect the in-memory stash") and even names the return shape (count + total bytes), which is more than the title provides. It doesn't explicitly contrast itself with nearby sibling diagnostics like get_guard_stats, but the resource is distinct enough to be identifiable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Diagnostic; not normally needed" gives a useful when-not-to-use signal that will keep an agent from calling it during normal recipe/shopping workflows. However, no alternative tool is named and no positive condition for when it IS appropriate is given, leaving the agent to infer that it is a troubleshooting-only call.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_foodsList foodsC
Read-onlyIdempotent

List foods. Optional: query (case-insensitive name match), root (parent id, 0 for top-level), tree (id), random, limit, page, page_size.

NameRequiredDescriptionDefault
pageNo
rootNo
treeNo
limitNo
queryNo
formatNo
randomNo
page_sizeNo
root_treeNo
updated_atNo

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is fully covered by structured data. The description adds nothing behavioral beyond that: no pagination behavior, no default page size, no statement about what happens when query matches nothing, and no note on how tree/root interact.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The definition is compact and front-loaded, with the purpose first and parameters after. It is telegraphic to the point of being fragmentary, but no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter tool with zero schema descriptions and no output schema, this description is too thin. Three parameters go undocumented and pagination/return-shape behavior is unstated, leaving the agent to guess at how to combine tree, root, and root_tree.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description carries the full documentation burden. It gives useful glosses for query (case-insensitive name match), root (0 for top-level), tree, limit, page, and page_size, but omits format (an enum with slim/full), root_tree, and updated_at entirely, and the gloss for random ("random") conveys no meaning about expected value or format.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

"List foods" states a verb and resource, so the basic purpose is clear, but it essentially restates the title and gives no hint of how it differs from siblings like get_food or list_recipes. An agent knows it lists foods, but not the scope (all foods? tree of foods? filtered?) without reading the parameter hints.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no prerequisites, and no mention of alternatives such as get_food for a single item or search_recipes for the recipe equivalent. The agent must infer usage entirely from the parameter glosses.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_inventory_entriesList inventory entriesA
Read-onlyIdempotent

List inventory entries (what is on hand, where). Optional: location_id, food_id, include_empty (entries with amount 0 or less are hidden unless true), page, page_size.

NameRequiredDescriptionDefault
pageNo
formatNo
food_idNo
page_sizeNo
location_idNo
include_emptyNo

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnly, idempotent, and non-destructive, so the description's main added value is the non-obvious default that entries with amount 0 or less are hidden unless include_empty is true. That is a genuinely useful behavioral disclosure, though pagination behavior and any result ordering remain unstated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact clauses with the purpose front-loaded and the parameter list kept terse. Nothing is redundant, though the bare comma-separated name list is less scannable than a structured list would be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 6 parameters, no schema descriptions, and no output schema, the description leaves the format enum and pagination defaults undocumented. It covers the filtering semantics well enough to call the tool but not fully enough to use it confidently.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter meaning. It explains include_empty well and lists location_id, food_id, page, and page_size by name only, and it omits the 'format' parameter (slim vs full) entirely.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ("List inventory entries") and adds a clarifying gloss, "what is on hand, where," that distinguishes it from sibling tools like list_inventory_locations and list_foods. It does not explicitly name a sibling it is not, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: listing entries with optional filters by location and food. There is no explicit when-to-use statement, no mention of when to prefer list_inventory_locations, search_recipes, or a get_* tool, and no prerequisites described.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_inventory_locationsList inventory locationsC
Read-onlyIdempotent

List inventory locations (pantry, fridge, freezer and so on). Optional: page, page_size.

NameRequiredDescriptionDefault
pageNo
formatNo
page_sizeNo

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered elsewhere. The description adds no behavioral context of its own — nothing about ordering, result size, or whether locations are user-defined or fixed system values.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short sentence plus a parameter note — tightly front-loaded with no padding. The terseness borders on under-specification rather than wastefulness, but structure itself is clean.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with zero schema descriptions, one undocumented enum, and no output schema, the description should explain what a 'location' object contains and what slim vs full returns. It does neither, leaving the agent to guess at the payload shape.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 3 parameters, so the description must compensate and largely fails: it names 'page' and 'page_size' but gives no defaults, bounds, or type info, and omits the 'format' enum (slim/full) entirely — the one parameter whose meaning is least obvious from its name.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List inventory locations') and clarifies the domain with parenthetical examples (pantry, fridge, freezer). It reads clearly against siblings like list_inventory_entries, though it doesn't explicitly say how locations differ from entries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, no exclusions, and no reference to the closely related siblings (list_inventory_entries, add_inventory_item). The agent must infer from the name alone that this is a lookup/ID-discovery call.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_keywordsList keywordsC
Read-onlyIdempotent

List keywords (recipe tags). Optional: query, root, tree, random, limit, page, page_size.

NameRequiredDescriptionDefault
pageNo
rootNo
treeNo
limitNo
queryNo
formatNo
randomNo
page_sizeNo
root_treeNo
updated_atNo

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so the safety profile is fully covered. The description adds only the semantic gloss "recipe tags" and a bare parameter list; it says nothing about pagination behavior, result ordering, or how tree/root modes change what is returned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with the purpose front-loaded, so there is no padding. However, the brevity is under-specification rather than efficiency: the parameter dump conveys almost no usable information for its length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 10 optional parameters, 0% schema coverage, and no output schema, this description is far too thin to let an agent call the tool correctly. It omits three parameters entirely and gives no return-shape or paging context; only the annotations rescue basic safety expectations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 10 parameters, so the description carries the full burden and names 7 of them without any meaning attached. Worse, the omitted parameters (format, root_tree, updated_at) appear nowhere, and the ambiguous ones (tree vs root, random, limit typed as string) get no explanation of expected values.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

"List keywords" states a specific verb and resource, and the parenthetical "(recipe tags)" usefully disambiguates what a keyword is in this domain. It does not distinguish itself from the sibling get_keyword or explain how keyword listing relates to recipe listing, so it falls short of 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The only guidance is "Optional: query, root, tree, random, limit, page, page_size," which is a parameter inventory rather than a statement of when to use this tool. There is no mention of when to prefer get_keyword, when to use tree versus flat listing, or any precondition for calling it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_meal_plansList meal plansC
Read-onlyIdempotent

List meal plans. Optional: from_date, to_date (YYYY-MM-DD), page, page_size

NameRequiredDescriptionDefault
pageNo
to_dateNo
from_dateNo
page_sizeNo

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. Beyond that the description adds nothing: no default page size, no maximum, no ordering, and no indication of what a meal plan record contains or whether date filtering applies to plan dates or contained entries.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, front-loaded fragments with no filler; the parameter list is compact. The opening sentence duplicates the title, which is the only wasted space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and a zero-coverage input schema, the description carries most of the burden and leaves key questions open: pagination defaults, result ordering, and what fields a meal plan exposes. Adequate to invoke, but not complete enough for reliable use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It names all four parameters and supplies the YYYY-MM-DD format for from_date/to_date, which is genuinely useful, but page and page_size get no semantics (defaults, limits) and the date-range inclusivity is unstated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

"List meal plans" states a verb and resource, so an agent can tell it is a read/list operation rather than get/create/update/delete. However, the sentence is essentially a restatement of the title and name, and it draws no distinction from siblings like get_meal_plan or search_recipes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this versus get_meal_plan (single plan) or other list tools, and no mention of prerequisites or paging strategy. Usage is only implied by the verb "List".

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_meal_typesList meal typesA
Read-onlyIdempotent

List available meal types (breakfast, lunch, dinner, etc.)

NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered by structured data. The description's only addition beyond that is the example value set, which helps set expectations about the result domain but says nothing about ordering, completeness, or whether the list is fixed or space-configurable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence with the resource and examples front-loaded and no wasted words. It is minimally structured (one fragment plus parenthetical) but nothing needs to be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter list tool with full annotation coverage, the description is nearly sufficient, but with no output schema the agent gets no hint about the shape of each meal type (id plus name?) or the ordering of results. One clause on the return shape would close the remaining gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4 and the schema has nothing that needs explaining. The description correctly implies no input is needed, matching the empty input schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('List') and resource ('meal types') and parenthetically enumerates representative values (breakfast, lunch, dinner), so an agent immediately knows the returned domain. It does not, however, distinguish this from the sibling get_meal_type, which fetches a single meal type.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: an agent can infer this is the discovery/enumeration call, but there is no explicit 'use this when you need valid meal type values' framing and no mention of get_meal_type as the single-item alternative. No prerequisites or exclusions are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_recipesList recipesA
Read-onlyIdempotent

List/search recipes with extensive filtering. Default returns slim results (id, name, description, servings, rating, keywords). Pass format="full" for raw API response. sort_order options: score,-score,name,-name,lastcooked,-lastcooked,rating,-rating,times_cooked,-times_cooked,created_at,-created_at,lastviewed,-lastviewed. If filtering by food/keyword/book NAMES (not ids), prefer search_recipes — it resolves names to ids for you and reports unresolved names in _meta.unresolved so you know what was dropped. If this returns an empty result set, recommend: broaden the query, drop restrictive filters, or try search_recipes if you were passing names.

NameRequiredDescriptionDefault
newNo
pageNo
booksNo
foodsNo
queryNo
unitsNo
filterNoID of a saved CustomFilter
formatNoResponse detail level. Default "slim".
randomNo
ratingNo
makenowNoOnly recipes makeable with on-hand foods
books_orNo
foods_orNo
internalNo
keywordsNo
books_andNo
createdbyNo
createdonNo
foods_andNo
page_sizeNo
updatedonNo
num_recentNo
rating_gteNo
rating_lteNo
sort_orderNo
keywords_orNo
timescookedNo
books_or_notNo
cookedon_gteNo
cookedon_lteNo
foods_or_notNo
keywords_andNo
viewedon_gteNo
viewedon_lteNo
books_and_notNo
createdon_gteNo
createdon_lteNo
foods_and_notNo
updatedon_gteNo
updatedon_lteNo
keywords_or_notNo
timescooked_gteNo
timescooked_lteNo
keywords_and_notNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds genuinely non-obvious behavior: the default slim payload's exact fields, that format="full" returns the raw API response, the complete sort_order vocabulary, and that unresolved names are silently dropped in the sibling tool. It does not mention pagination defaults or result-size limits despite page/page_size params.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the default return shape and the format toggle, then routing, then failure recovery — a sensible order. The inline sort_order enumeration is long but is high-value information an agent would otherwise have to guess at; there is little filler elsewhere.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 44-parameter filter tool with no output schema, the description does well on output shape and tool routing, which is the highest-risk area. It falls short on the filter-semantics surface: the AND/OR/NOT array variants and the multiple date-range parameters are the main source of incorrect calls and are not addressed at all.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 7% across 44 parameters, so the description must carry weight; it explains format, the sort_order value set, and that books/foods/keywords take ids rather than names. However, the large and easy-to-confuse families (foods_or vs foods_and vs foods_or_not, keywords equivalents, books_or_not, cookedon_/createdon_/updatedon_/viewedon_ range pairs, timescooked_gte/lte, makenow, num_recent, random) receive no explanation, leaving most parameters undocumented anywhere.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb and resource ("List/search recipes with extensive filtering") and immediately positions itself against search_recipes for name-based filtering. It is clear what the tool does, though the dual "list/search" framing leaves the primary intent slightly ambiguous compared with the sibling that is explicitly for searching.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: prefer search_recipes when filtering by food/keyword/book NAMES because it resolves names to ids and reports _meta.unresolved. It also prescribes recovery steps when the result set is empty (broaden query, drop filters, switch tools), covering both when-to-use and what-to-do-on-failure.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_recipes_flatList recipes (flat)A
Read-onlyIdempotent

Lighter alternative to list_recipes; returns minimal recipe metadata suitable for large browse queries. Use list_recipes if you need keywords/foods/steps nested.

NameRequiredDescriptionDefault
formatNoResponse detail level. Default "slim".

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this read-only, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds useful context about the payload shape being stripped of nested fields, but says nothing about pagination, limits, or how 'format' interacts with that payload.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly written sentences that lead with the distinguishing characteristic and end with the routing rule. No filler or restated naming.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the burden of describing returns and does so by contrasting minimal metadata against the nested keywords/foods/steps of list_recipes. Only minor gaps remain around 'format' behavior and result volume/pagination.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single 'format' enum with its default is fully documented in the schema, so baseline 3 applies. The description never mentions 'format' and its 'returns minimal recipe metadata' wording slightly muddies what format=full would produce.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('returns minimal recipe metadata' for a recipe listing) and explicitly positions itself as a lighter variant of list_recipes. An agent can distinguish it from list_recipes from the text alone, though the sibling search_recipes is not addressed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear use condition ('large browse queries') and names the alternative (list_recipes) with the condition that selects it (need keywords/foods/steps nested). No exclusions or guidance relative to search_recipes, which is the main gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_shopping_entriesList shopping entriesA
Read-onlyIdempotent

List shopping list entries (auto-filtered to unchecked + recent by Tandoor). Optional: mealplan, updated_after (ISO), page, page_size, format. Entries cannot be filtered by shopping list; use the shopping_lists field of the results.

NameRequiredDescriptionDefault
pageNo
formatNo
mealplanNo
page_sizeNo
updated_afterNo

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the read-only/idempotent/no-destroy profile, and the description adds real context beyond them: the server-side auto-filter to unchecked and recent entries, which materially affects what an agent will see. It stops short of explaining what 'recent' means or pagination defaults.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with the core behavior front-loaded and zero filler; the parameter list is compact. The structure is efficient, though the parenthetical aside about filtering sits awkwardly at the end rather than near the relevant scope statement.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a five-param, no-output-schema list tool, the description covers the critical filtering behavior and the list-filtering limitation, so an agent can call it. Gaps remain: the meaning of the mealplan number and any pagination defaults are absent, which matters given 0% schema coverage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter meaning and it only partially does — it enumerates all five params and clarifies updated_after is ISO, but leaves 'mealplan' (a number) unexplained and says nothing about page/page_size defaults, even though format's enum is self-documenting in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List shopping list entries') and adds a scope trait — results are auto-filtered to unchecked + recent by Tandoor. It implicitly distinguishes itself from list_shopping_lists by noting entries cannot be filtered by list, though it never names that sibling or get_shopping_entry explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides one useful usage constraint: entries cannot be filtered by shopping list, so callers should read the shopping_lists field of the results instead. It gives no guidance on when to use this versus get_shopping_entry or the bulk_* variants, leaving selection to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_shopping_listsList shopping listsB
Read-onlyIdempotent

List the named shopping lists of this space (for example one per store), as {id, name, description, color}. Every member of the space sees the same lists. Optional: page, page_size.

NameRequiredDescriptionDefault
pageNo
formatNo
page_sizeNo

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is covered. The description still adds real value by disclosing the returned field set {id, name, description, color} and the sharing semantics across space members. It omits ordering and pagination defaults, which keeps it at 4.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the resource and its scope, with no filler. The trailing "Optional: page, page_size" is the one sentence that earns little, since it repeats property names without adding meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully supplies the shape of returned items, so return values are adequately covered. However, for a paginated list tool it leaves defaults, ordering, and the purpose of the slim/full `format` option unexplained, so an agent can call it but not tune it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter meaning, and it largely does not. It names page and page_size only as "Optional" with no defaults or limits, and the `format` parameter with its slim/full enum is not mentioned at all, leaving an agent unable to choose a value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("List the named shopping lists of this space") and adds scope plus an example ("one per store"), which makes it clearly distinct from list_shopping_entries. It never explicitly names a sibling or exclusion, so it stops just short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer this is the enumeration call before touching entries or creating lists, but the description never says when to choose it over list_shopping_entries or list_meal_plans, nor any prerequisites. "Every member of the space sees the same lists" is behavioral context, not selection guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_tool_groupsList tool groupsA
Read-onlyIdempotent

List every tool section with its current mode and the modes it accepts. Tiered sections (off / simple / full) and on/off sections can be widened with enable_tool_group and turned off with disable_tool_group. The "always" section is permanent. When a section changes, its tools appear in or leave tools/list and the SDK emits tools/list_changed so the client refreshes mid-conversation. Use this first to discover what is available before reaching for enable_tool_group.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so safety is covered; the description adds the domain model instead — tiered (off/simple/full) vs on/off sections, the permanent 'always' section, and the fact that mode changes emit tools/list_changed so the client refreshes mid-conversation. That is meaningful context an agent cannot get from annotations or the empty schema. It stops short of describing the exact shape of the returned section entries (no output schema exists), which keeps it below a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with what is returned, then the mode taxonomy, then the side effect, then the call-ordering advice. Every sentence carries distinct information; nothing is repeated from the name or title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no parameters, no output schema, and simple read-only semantics, the description covers everything needed: what is listed, what each entry contains, what the modes mean, which section cannot be changed, and the refresh side effect. An agent can call it correctly on the first try.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4 and there is nothing for the description to disambiguate. The description correctly adds no parameter detail rather than inventing any.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List every tool section') plus exactly what is returned per section ('its current mode and the modes it accepts'). It is clearly distinguished from the sibling mutators enable_tool_group and disable_tool_group, which are named directly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit ordering rule: 'Use this first to discover what is available before reaching for enable_tool_group.' It also implicitly excludes the write path (enable/disable) by pointing at them as follow-ups, so an agent knows which sibling to call next.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_unitsList unitsC
Read-onlyIdempotent

List units. Optional: query, limit, page, page_size, random.

NameRequiredDescriptionDefault
pageNo
limitNo
queryNo
formatNo
randomNo
page_sizeNo
updated_atNo

TDQS

C2.4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is covered without help. The description adds no behavioral context beyond that: no pagination behavior, no ordering defaults, no indication of what random returns.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is short and front-loaded, but the brevity comes at the cost of substance rather than being achieved through efficient wording. The parameter list is bare tokens with no structure or grouping.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With seven parameters, zero schema descriptions, an unexplained enum, and no output schema, the description should carry substantial weight and does not. An agent cannot tell from this definition what a unit is or how to page or filter deterministically.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description merely re-lists five parameter names without meaning. It omits the format enum and the updated_at parameter entirely, and never clarifies the relationship between limit and page_size or what the string-typed random parameter does.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a verb and resource ("List units"), which is at least a statement of function, but "units" is never defined and the phrasing is essentially a restatement of the title. It offers no hint of how this differs from siblings such as list_foods, list_recipes, or list_inventory_entries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no indication of what a unit is in this domain, and no mention of alternatives. The agent is left to infer usage entirely from the name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_inventory_itemMove inventory itemB
Idempotent

Move a whole inventory entry to another location. Required: entry_id, to_location_id. Optional: sub_location (null clears it).

NameRequiredDescriptionDefault
formatNo
entry_idYes
sub_locationNo
to_location_idYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare this is a non-readonly but idempotent and non-destructive operation. The description adds meaningful behavior by noting that sub_location is optional and that null clears it, but it omits error behavior, what happens to the source entry, and the meaning of format.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences are front-loaded with the core action and then the required/optional parameter details. There is no redundant or wasted wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is a low-complexity mutation with annotations covering safety and idempotency, and the description covers the required parameters and null-clearing behavior. However, it omits explanation of the format parameter and any return or error context, which is notable because there is no output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter meaning. It explains three of four parameters, including the useful null-clearing semantics for sub_location, but it never explains the format enum (slim/full), leaving that parameter opaque.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Move a whole inventory entry to another location.' The word 'whole' adds useful scope, distinguishing it from partial inventory adjustments, but it does not explicitly differentiate itself from sibling tools such as add_inventory_item or consume_inventory_item.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies usage through the verb 'Move', but provides no explicit when-to-use or when-not-to-use guidance. It also does not mention alternatives like update or consume tools, so an agent must infer the selection context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

parse_ingredientParse ingredientA
Idempotent

Parse a free-form ingredient string (e.g. "2 cups flour") into amount, unit, unit_id, food, food_id, note. Writes to the database: Tandoor creates any Food or Unit row it does not already have. unit and food are the matched row names, so "cups" can come back as "cup". With no unit, unit is "" and unit_id is omitted. food_id and unit_id pass straight to create_ingredient. Blank text returns Tandoor's 400. Tandoor's parser is heuristic and can misfire on compound descriptions, brand names, or non-English units.

NameRequiredDescriptionDefault
textYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

It discloses the non-obvious side effect that Tandoor writes new Food and Unit rows as a side effect, which goes well beyond the readOnlyHint=false annotation. It also covers edge cases the annotations cannot: blank text yields a 400, missing units return an empty string with unit_id omitted, and the heuristic parser can misfire on compound or non-English input.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence carries distinct information: output shape first, then write side effects, then normalization behavior, then error and reliability caveats. There is no filler, and the most consequential facts (database writes, idempotent-ish normalization) are front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with no output schema, the description supplies the return fields, side effects, normalization rules, error behavior, and reliability limits. An agent has everything needed to call it and interpret the response without further discovery.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% for the single text parameter, but the description compensates with an inline example ("2 cups flour") and the blank-text failure mode. It explains return-field meanings (amount, unit, unit_id, food, food_id, note) rather than additional input semantics, so it does not fully exhaust what could be said about the input string.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence names a specific verb (parse) and resource (free-form ingredient string) and lists the exact output fields, so the agent knows precisely what the call produces. It also implicitly distinguishes itself from create_ingredient and create_food by describing parsing rather than record creation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description establishes the parse-then-create workflow by noting that food_id and unit_id 'pass straight to create_ingredient', which tells the agent this is a preprocessing step. It stops short of explicitly stating when not to use it or naming an alternative for cases like already-structured input, so it falls just below full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_recipesSearch recipesA
Read-onlyIdempotent

High-level recipe search. Accepts food/keyword/book names (not IDs) and resolves them internally — typically collapses 3-4 round-trips into 1. Example: {foods: ["chicken", "broccoli"], exclude_foods: ["peanuts"], keywords: ["weeknight"]}. For complex ID-based filtering, fall back to list_recipes.

NameRequiredDescriptionDefault
pageNo
booksNoRecipe book names — recipe must be in ANY of these
foodsNoFood names the recipe must contain ALL of
queryNoFuzzy match against recipe names
formatNoResponse detail level. Default "slim".
randomNo
makenowNoOnly recipes makeable with currently on-hand foods
keywordsNoKeyword names — recipe must have ANY of these
page_sizeNo
rating_gteNo
rating_lteNo
sort_orderNoscore | -score | name | -name | lastcooked | -lastcooked | rating | -rating | times_cooked | -times_cooked
exclude_foodsNoFood names the recipe must NOT contain any of
timescooked_gteNo
timescooked_lteNo
exclude_keywordsNoKeyword names to exclude

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnly, idempotent, non-destructive, closed-world behavior, so the safety profile is covered. The description adds real behavioral context beyond that: name-to-entity resolution happens server-side, and the tool substitutes for a multi-call sequence. It stops short of describing result-set size, pagination, or the slim-vs-full response tradeoff.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then capabilities, then the worked example, then the fallback pointer — a sensible ordering with no filler. The example is compact and high-signal, though the round-trip claim is slightly promotional and the description never returns to defaults or result limits.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a 16-parameter tool with no output schema and no required parameters, so the description is the only place to explain defaults and response shape — it doesn't. Default 'slim' format, pagination via page/page_size, and the meaning of 'random' are all left to the schema or unstated, which is a meaningful gap for an agent composing a query.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

At 56% schema coverage the schema carries most of the burden, but the description contributes one genuinely non-obvious semantic: foods/keywords/books accept names, not IDs, and are resolved internally — something the schema's 'Food names' phrasing only implies. The example demonstrates AND-semantics for foods and exclusion for exclude_foods, though it leaves query, format, random, makenow, sort_order, rating and timescooked ranges unaddressed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('recipe search') plus a defining mechanism: it takes names and resolves them internally rather than IDs. That single clause separates it cleanly from list_recipes/list_recipes_flat, which are the ID/index-oriented siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Both directions are explicit: use this for name-based lookups, and 'For complex ID-based filtering, fall back to list_recipes.' It also justifies the choice by noting the 3-4 round-trips it collapses, so an agent can weigh it against the alternative without opening either schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_foodUpdate foodA
DestructiveIdempotent

Update food (PATCH). Required: id. Optional properties[] {property_type_id, property_amount} sets one value per property type (amount null = unknown), updating the existing value of that type in place and deleting any duplicate values of that type; remove_property_type_ids[] deletes values by type. Other existing property values are kept. A type may appear once across both lists. properties_food_amount and properties_food_unit_id set the food amount the property values refer to (e.g. 100 g); properties_food_unit_id null clears the unit. Deleting a property row removes it from every food or recipe it is linked to. If a row delete fails, the food is already updated and the tool returns an error naming those rows. shopping_list_ids replaces the food's lists; [] clears them; omit it to keep them. Changing a food's lists does not change its existing shopping entries. add_recipe_to_shopping_list copies the food's lists onto new entries. create_shopping_entry without shopping_list_ids copies them when the user preference shopping_update_food_lists is on. bulk_create_shopping_list_recipe_entries without shopping_list_ids copies each food's lists whatever the user preference. Every list id is checked against list_shopping_lists first; unknown or repeated ids are rejected and nothing is written. If the lists after the write differ from the request, the tool errors and names the missing and the extra lists.

NameRequiredDescriptionDefault
idYes
nameNo
fdc_idNo
formatNo
propertiesNo
descriptionNo
food_onhandNo
plural_nameNo
shopping_list_idsNo
properties_food_amountNo
properties_food_unit_idNo
supermarket_category_idNo
remove_property_type_idsNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=true, and the description goes well beyond them: it discloses that deleting a property row cascades to every food/recipe linked to it, that duplicate values of a type are removed, that list ids are validated against list_shopping_lists with nothing written on rejection, and that a partial failure leaves the food updated while returning an error naming the rows. That is unusually strong disclosure for a mutation, though return/pagination details are absent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the essentials (PATCH, required id) and dense with useful detail, but it sprawls into the list-copying behavior of three other tools, which is tangential to invoking update_food. A single unstructured block of this length makes it hard to locate the parts relevant to a given call.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 13-parameter mutation with no output schema and no schema descriptions, the description covers the dangerous and ambiguous paths thoroughly, including validation and partial-failure behavior. Remaining gaps are the response shape and the meaning of the format enum, which an agent may need to interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden; it explains the non-obvious parameters well (properties[] sets one value per type with null meaning unknown and deletes duplicates, remove_property_type_ids[] deletes by type, properties_food_unit_id null clears the unit, shopping_list_ids [] clears vs omitted keeps). Seven simpler parameters (name, fdc_id, format, description, food_onhand, plural_name, supermarket_category_id) are not addressed, and the slim/full format enum is left unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource and method semantics ("Update food (PATCH)") and immediately names the required field, so the agent knows exactly which resource is mutated and how. The detailed property/shopping-list semantics further separate it from create_food and get_food.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the PATCH framing and the required id, but there is no explicit statement of when to choose this over create_food or update_recipe. The mentions of add_recipe_to_shopping_list, create_shopping_entry and bulk_create_shopping_list_recipe_entries describe side effects of those siblings rather than routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_meal_planUpdate meal planC
Idempotent

Update meal plan. Required: id. All other fields optional

NameRequiredDescriptionDefault
idYes
noteNo
titleNo
to_dateNo
servingsNo
from_dateNo
recipe_idNo
meal_type_idNo

TDQS

C2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=true, and destructiveHint=false, so the safety profile is covered structurally. The description adds nothing beyond that: it does not say that omitted fields are left unchanged (patch semantics), whether setting recipe_id to null detaches a recipe, or whether updating dates can conflict with an existing plan. For a mutation tool this is thin.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, front-loaded sentences with no padding, which is structurally sound. However, the second sentence is largely redundant with the schema's required array, so the brevity reflects under-specification rather than efficiency.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness1/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An 8-parameter mutation tool with 0% schema coverage, no output schema, and no annotations about side effects needs a description that explains field semantics and outcomes. This one provides none of that, leaving the agent unable to safely construct a partial update.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 8 parameters, and the description documents none of their meaning. It only repeats the required/optional split the schema already encodes. Nothing explains the from_date/to_date relationship, the nullable recipe_id, or what meal_type_id and servings affect, so the compensation the low coverage demands is absent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose2/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Update meal plan" restates the tool name and title verbatim without adding scope, distinguishing it from the sibling update_recipe/update_food/update_shopping_entry tools, or clarifying whether this is a partial or full replacement. The only added information, that id is required, belongs to the schema. An agent learns nothing beyond the name itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no mention of prerequisites (does the meal plan need to exist? does recipe_id/meal_type_id need to be valid?), and no reference to alternatives such as create_meal_plan or delete_meal_plan. The agent must infer that this is the edit path for an existing plan from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_recipeUpdate recipeB
DestructiveIdempotent

Update recipe metadata and content. Only provide fields you want to update. All fields optional except id.

NameRequiredDescriptionDefault
idYesRecipe ID
nameNo
stepsNo
formatNoResponse detail level. Default "slim".
privateNo
internalNo
keywordsNo
servingsNo
nutritionNo
propertiesNo
source_urlNo
descriptionNo
waiting_timeNo
working_timeNo
servings_textNo
show_ingredient_overviewNo

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=true and idempotentHint=true, so the agent knows this is a mutating but idempotent call. The description adds the partial-update semantics that annotations do not express. But with destructiveHint=true and nested steps/ingredients arrays, it never says whether supplying steps replaces the whole list or merges, nor whether omitted fields are preserved—the central risk when calling this tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with the key scoping rule (only send fields to change) placed early; no filler or redundancy. It is efficient but undersized for the surface it covers.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a 16-parameter destructive update with nested objects, no output schema, and near-zero schema coverage; the description does not come close to carrying the required burden. An agent cannot learn from it how nested arrays behave, what validation applies, or what the response will look like, which matters because no output schema exists to explain returns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 13% across 16 parameters; only id and format carry inline descriptions. The description's "all fields optional except id" merely restates the required array and adds no meaning for name, steps, nutrition, private, internal, properties, source_url or the timing fields, many of which are nested objects whose merge behavior is undefined.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: "Update recipe metadata and content." An agent can distinguish it from create_recipe, get_recipe and update_meal_plan without opening a schema. It does not explicitly name which sibling to use when a recipe doesn't yet exist, but the verb makes that near-obvious.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Only provide fields you want to update" gives partial-update (PATCH-style) guidance, which is genuinely useful. However, there is no when-to-use-vs-alternatives guidance, no mention of prerequisites or permissions, and no statement about whether use create_recipe for new recipes or how to handle conflict with import_recipe_from_url.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_shopping_entryUpdate shopping entryA
Idempotent

Update a shopping entry (PATCH). Required: id. Other fields optional. When checked is omitted, the tool reads the entry and sends its current checked value again, so a checked entry keeps its completed_at. A check made elsewhere between that read and the write is undone (last write wins). shopping_list_ids puts the entry on exactly those lists; [] clears them; omit it to keep them. Every list id is checked against list_shopping_lists first; unknown or repeated ids are rejected and nothing is written. If the lists after the write differ from the request, the tool errors and names the missing and the extra lists.

NameRequiredDescriptionDefault
idYes
orderNo
amountNo
formatNo
checkedNo
food_idNo
unit_idNo
delay_untilNo
shopping_list_idsNo

TDQS

A3.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing a read-modify-write sequence, the last-write-wins race that can undo a concurrent check, pre-write validation against list_shopping_lists, and a post-write consistency check that errors and names missing/extra lists. These are exactly the non-obvious traits (side effects, failure modes) an agent cannot infer from readOnlyHint/idempotentHint/destructiveHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the required parameter and the mutation semantics, with no filler sentences; every clause conveys a rule an agent needs. It is dense to the point of near-run-on in the checked sentence, which costing it the top mark.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema and 0% parameter coverage put the full burden on the description. Write semantics, validation, and error behavior are covered thoroughly, but a caller still cannot tell what order/amount/delay_until do or what slim vs full controls in the absence of any documented return value.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter meaning, and it only explains 3 of 9 (id, checked, shopping_list_ids). order, amount, format (slim vs full, which likely changes the response shape and matters given no output schema), food_id, unit_id, and delay_until are undocumented in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Update a shopping entry (PATCH)" states a specific verb plus resource and adds the HTTP-method mapping, which tells an agent this is a partial update. It does not explicitly contrast with bulk_update_shopping_entries or food_shopping_update, but the singular scope is clear enough to pick between them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete conditions for the main decision points: omit checked to preserve completed_at, pass [] to clear lists, omit shopping_list_ids to keep them. It stops short of naming alternatives such as bulk_update_shopping_entries for multi-entry changes, so routing guidance is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 46 tool updatesv3.4.0
    • First observedadd_inventory_item
    • First observedadd_recipe_to_shopping_list
    • First observedbulk_check_shopping_entries
    • First observedbulk_update_shopping_entries
    • First observedconsume_inventory_item
    • First observedcreate_food
    • First observedcreate_meal_plan
    • First observedcreate_recipe
    • First observedcreate_shopping_entry
    • First observeddelete_meal_plan
    • First observeddelete_shopping_entry
    • First observeddisable_tool_group
    • First observedenable_tool_group
    • First observedfood_shopping_update
    • First observedget_current_space
    • First observedget_food
    • First observedget_guard_stats
    • First observedget_keyword
    • First observedget_meal_plan
    • First observedget_meal_type
    • First observedget_recipe
    • First observedget_shopping_entry
    • First observedget_version
    • First observedimport_recipe_from_url
    • First observedjq_query
    • First observedjq_stash_stats
    • First observedlist_foods
    • First observedlist_inventory_entries
    • First observedlist_inventory_locations
    • First observedlist_keywords
    • First observedlist_meal_plans
    • First observedlist_meal_types
    • First observedlist_recipes
    • First observedlist_recipes_flat
    • First observedlist_shopping_entries
    • First observedlist_shopping_lists
    • First observedlist_tool_groups
    • First observedlist_units
    • First observedmove_inventory_item
    • First observedparse_ingredient
    • First observedrelated_recipes
    • First observedsearch_recipes
    • First observedupdate_food
    • First observedupdate_meal_plan
    • First observedupdate_recipe
    • First observedupdate_shopping_entry

TDQS

B3/5.0

Scored across 46 tools

Disambiguation4/5

Most tools separate resource and action clearly, and the descriptions distinguish overlapping cases like list_recipes, search_recipes, and list_recipes_flat. Some ambiguity remains around food/list manipulation tools such as create_food, update_food, and food_shopping_update, but the guidance generally resolves it.

Naming Consistency4/5

Almost all tools use a predictable snake_case verb_noun pattern such as list_meal_plans, get_recipe, create_shopping_entry, and delete_meal_plan. A few names deviate, notably food_shopping_update, related_recipes, and jq_stash_stats, so it is not perfectly uniform.

Tool Count2/5

At 46 tools, the surface is far beyond the typical 3-15 range and includes many domains plus utility/diagnostic and tool-group management tools. Tool groups can reduce context load, but the raw tool count is still too heavy for a well-scoped set.

Completeness3/5

Core recipe, meal-plan, shopping-entry, and inventory workflows are covered with several create/read/update operations. However, notable gaps remain: there is no delete_recipe or delete_food, shopping-list CRUD is missing, keywords and units are read-only, and inventory lacks update/delete operations.

Maintenance

ActivityMaintained
ResponsivenessLimited data

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Enables interaction with Tandoor recipe management system to create, manage, and search recipes, as well as create and auto-generate meal plans with automatic ingredient and keyword creation.
    11
    332 npm
    3
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Household-aware kitchen brain for AI agents: manage pantry inventory with freshness tracking, shopping lists, recipe collections with cook notes and per-diner ratings, dietary profiles with allergen safety, and kitchen equipment — all through 27 tools with OAuth 2.1 authentication. Includes a free tool for ingredient-based recipe generation without an account (accounts are free!).
    MIT