Tandoor Recipes MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Tandoor Recipes MCPPlan my dinners for this week and make me a grocery list"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Tandoor Recipes MCP
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_fileanddownload_filereturn a Tandoor file inline, or save it toTANDOOR_MCP_DOWNLOAD_ROOTwithsave: true. See Downloading files.get_external_recipe_file_linkworks again.get_recipe_file_metadatais removed; usedownload_recipe_fileinstead.
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 takeoff,simple, orfull, and toggle sections takeofforon. See Tool sections and Migration from 2.x.Pantry and freezer inventory tools in the
inventorysection, plus a combinedtandoor://pantry/on-handresource.Households: list, get, create, update, and delete households, and
assign_householdto 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-weekandtandoor://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, orfull. Toggle sections takeofforon. In stdio mode the LLM can turn a hidden section on mid-session withenable_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_queryto 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-mcpOr npx without installing:
npx -y @cliftonz/tandoor-recipes-mcpNode 24 or later is required (see engines.node in package.json).
Other ways to get it:
Claude Desktop extension:
tandoor-recipes-mcp.mcpbfrom 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 andlatest. The image starts in remote mode by default.MCP Registry: listed as
io.github.Cliftonz/tandoor-recipe-mcpin the MCP Registry, with the npm package, the.mcpbfile and the Docker image.Claude Code plugin and Codex plugin: see Configure.
Configure
In Tandoor: Settings, API Tokens, Create new token.
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-tandoorFrom a terminal, the same two steps are:
claude plugin marketplace add Cliftonz/tandoor-recipe-mcp
claude plugin install tandoor-recipes-mcp@cliftonz-tandoorClaude 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.
Download
tandoor-recipes-mcp.mcpbfrom the latest GitHub release.Double-click the file. Or, in Claude Desktop, open Settings > Extensions > Advanced settings > Install Extension and select the file.
Enter your Tandoor URL and API token. Claude Desktop stores the token securely.
Optional: set the section settings you want.
Claude Desktop, plugin marketplace
Claude Desktop can also add the plugin:
Open Customize > Plugins > Add > Add marketplace > Add from a repository.
Enter
Cliftonz/tandoor-recipe-mcp.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.jsonWindows:
%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
In the app, open Settings > MCP servers > Add server.
Choose STDIO.
Set the command to
npx.Add the arguments
-yand@cliftonz/tandoor-recipes-mcp.Add the environment variables
TANDOOR_URLandTANDOOR_TOKEN. Add anyTANDOOR_MCP_*section settings you want.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-mcpcodex 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
Open the Plugins page and select Add > Add a marketplace.
Enter the source
Cliftonz/tandoor-recipe-mcp.Open the Tandoor plugin's details and select the plus button.
Restart the app.
From a terminal:
codex plugin marketplace add Cliftonz/tandoor-recipe-mcp
codex plugin add tandoor-recipes-mcp@cliftonz-tandoorCodex 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-tokenlaunchctl 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.
Recommended Claude Code permissions
The repo ships a .claude/settings.json that auto-allows read tools and prompts for everything else. Copy these into your own project's .claude/settings.json to reduce permission friction:
{
"permissions": {
"allow": [
"mcp__tandoor__list_*",
"mcp__tandoor__get_*",
"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 |
| Claude Desktop, Claude Code, any MCP client that spawns the server as a subprocess. | Inherited from parent process. |
| Out-of-Claude callers, local scripts, other agents on the same host. | Optional bearer via |
| 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-mcpThe 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:
The app (Claude or ChatGPT) calls your public URL and gets a
401that points to the server's OAuth metadata.The app identifies itself with its published client document, or registers itself automatically.
The app opens the sign-in page in your browser. You paste a Tandoor API token and select Approve.
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 |
| none (required) | Your Tandoor. It only has to be reachable from the server, so an internal address such as |
|
| The address users open Tandoor at, such as |
|
| Must be |
| none | The HTTPS URL clients connect to, such as |
| none (required in remote mode) | Exactly 64 hex characters (32 bytes). Generate one with |
|
| The folder for |
| none (no proxy trusted) | Set it when a reverse proxy or tunnel sits in front. A hop count such as |
|
| The address the server listens on. |
|
| The port the server listens on. |
|
| The MCP endpoint path. It cannot be, or start with, |
|
| On |
|
| Larger request bodies get a |
|
| 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_TOKENis refused. The server will not start while it is set. Each user brings their own token.TANDOOR_MCP_HTTP_TOKENis 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_groupis off in HTTP mode, so everyone sees the same tools.file_pathuploads are refused. The server's disk is not the user's disk. Usefile_urlinstead. Saving downloads withsave: trueis 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
Hostheader, orlocalhost,127.0.0.1or[::1]. Anything else gets a403, logged ashost_rejected. A browserOriginheader on the MCP path must equal the public URL's origin, or the request gets a403, logged asorigin_rejected.Responses are plain JSON. The server does not hold event streams open, so proxies need no streaming or buffering settings.
GETon the MCP path returns405.
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.
Generate a secret key:
openssl rand -hex 32Copy the
tandoor-mcpservice and thetandoor-mcp-datavolume fromdocker-compose.example.ymlinto your Tandoor compose file, so both services share a network.Set the environment:
TANDOOR_URL: your Tandoor service on the internal network. The example useshttp://web_recipes:8080; replaceweb_recipeswith the name of your Tandoor service.TANDOOR_MCP_TANDOOR_PUBLIC_URL: the address users open Tandoor at, such ashttps://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.
Start it:
docker compose up -d tandoor-mcp
Notes on the example file:
The
/datavolume holdsoauth.json. Keep the volume across upgrades, or everyone has to reconnect.The port is published on
127.0.0.1only (127.0.0.1:3737:3737), so only a proxy or tunnel on the same host can reach it. Remove theports:entry if your proxy reaches the container over the Docker network.Keep
TANDOOR_MCP_HTTP_HOST=0.0.0.0inside the container. Binding a specific address inside the container is not supported: the image's health check calls127.0.0.1, so the container reports unhealthy. Limit exposure with the port mapping instead.stop_grace_period: 15sis longer than the 10-second drain, so requests in progress can finish ondocker 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-mcpExpose 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
Hostheader through.Set
X-Forwarded-For, and you setTANDOOR_MCP_TRUST_PROXYto 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.
In the Cloudflare dashboard, go to Networking > Tunnels and select Create a tunnel. Copy the tunnel token.
Uncomment the
cloudflaredservice and setTUNNEL_TOKENto the token.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.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 3737The 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(yourTANDOOR_MCP_HTTP_PATH)
GET /.well-known/oauth-protected-resource/mcp
GET /.well-known/oauth-authorization-server
POST /register
POST /token
POST /revoke
GETandPOST /authorize
POST /consent
/authorizeand/consentopen 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,/consentand/.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:
Go to Customize > Connectors.
Click Add custom connector.
Enter the URL.
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.
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%2FmcpOwners 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/mcpThen run /mcp in Claude Code and follow the sign-in steps in your browser.
ChatGPT
Go to chatgpt.com/plugins.
Select the plus button, then Add custom MCP server.
Enter a name and description.
Under Connection, enter the URL, including
/mcp.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.
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.jsonand the secret key separately.oauth.jsonin 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, deletingoauth.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.jsonin memory and rewrites it on every change, so two processes overwrite each other.Health check:
GET /healthzreturns{"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 includeorigin_rejected,forwarded_header_untrusted(a proxy sentX-Forwarded-ForbutTANDOOR_MCP_TRUST_PROXYis not set),tandoor_check_failed,cimd_fetch_failed,payload_too_largeandshutdown. 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):
Claude: Anthropic's outbound IP ranges, listed at platform.claude.com/docs/en/api/ip-addresses. On 2026-11-07 they were
160.79.104.0/21and153.61.208.0/20.ChatGPT: OpenAI's ranges for connectors, published at openai.com/chatgpt-connectors.json. The list is long and changes; OpenAI recommends fetching it regularly and updating your allowlist automatically.
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/mcpThen 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 httpRemote 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 |
| yes | none | Base URL of your Tandoor instance. |
| yes, except in remote mode | none | API token with write access. Remote mode refuses to start when it is set. |
| no |
|
|
| no |
| HTTP-mode port. |
| no | none | HTTP-mode bearer token. If unset, HTTP transport runs without auth. Not allowed in remote mode. |
| no | per section | One variable per tool section, such as |
| no | none | Comma-separated allowlist (glob |
| no | none | Comma-separated denylist. E.g. |
| no | none | Stderr trace mode. |
| no |
| Park large tool results in an in-memory cache and return a |
| no |
| Stash payloads strictly larger than this many bytes. |
| no |
| LRU cap on stashed handles. |
| no |
| Total-bytes cap on the stash; LRU eviction kicks in past this budget. |
| no |
| Per-entry TTL in milliseconds (default 10 minutes). |
| no | none | Existing folder that |
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_PROFILEis ignored. When it has a value, the server prints one stderr warning.TANDOOR_MCP_PROFILE=full: set every tiered section tofulland every toggle section toon.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, setrecipes,meal_plan,shopping,inventory,foods,cooklog,recipe_books,ai,import_export,household_space, andadminin the plugin settings.Old group names are gone, with no aliases. Use the section names in
enable_tool_group. The always-on group is nowalways(wascore). 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. SetTANDOOR_MCP_HTTP_TOKENand 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 |
|
|
|
| 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 create, read, update, and delete. Read meal types. | Auto-plan, bulk create, meal type writes, iCal export. |
|
| List the named shopping lists. Shopping entry create, read, update, delete, and check. | 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. |
|
| List locations, list entries, add, consume, and move. | 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. |
|
| 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 |
|
| Cook-log entries: when and how often a recipe was made. |
|
| Recipe books (collections) and their entries. |
|
| AI providers, AI recipe import from images, AI step sort and property estimation, AI logs. |
|
| Recipe import and export, import queues, bookmarklet and open-data imports, their logs. |
|
| Spaces, memberships, households and household assignment, users, groups, invite links, user preferences. Only the space owner can use the household tools and |
|
| 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:
TANDOOR_MCP_INCLUDE_ONLYandTANDOOR_MCP_EXCLUDEfilter the tool list.EXCLUDEis a hard block: nothing can enable an excluded tool.A section env var that is set and not empty or whitespace-only decides that section.
For a section whose env var is unset, empty, or whitespace-only, the saved section for this
TANDOOR_URLdecides.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:offtosimpleorfull, orsimpletofull. It never narrows a section. For a tiered section,tierissimpleorfulland defaults tofull. Passingtierfor an on/off section is an error.disable_tool_group({group})sets a section tooff. It cannot disablealways.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:
Reads
tandoor://pantry/on-handandtandoor://meal-typesCalls
list_recipes({keywords_or: [<vegetarian>], rating_gte: 4, sort_order: '-rating'})Calls
create_meal_planfor each day of the weekCalls
add_recipe_to_shopping_listfor each planReads
tandoor://shopping-list/activeand 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:
import_recipe_from_url({url: "..."}), JSON-LD extraction handles sites Tandoor doesn't know
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:
preview_keyword_delete_protecting({id: <k>})to see what recipes still reference itIf safe:
delete_keyword({id: <k>})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
numrecipecounts 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):
Register a free personal key at api.data.gov/signup; no approval needed, instant.
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_KEYto the Tandoor deployment's env or a secret. Restart the Tandoor pod.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 |
| Monday to Sunday meal plan entries, slimmed to |
| Inventory entries by location, plus on-hand foods with no entry; at most 500 of each |
| Unchecked, recent shopping entries |
| Breakfast/Lunch/Dinner/etc. with IDs |
Prompts
Name | Purpose |
| Plan 7 days of dinners, optionally pantry-biased and keyword-filtered |
| Turn this week's meal plan into a shopping list grouped by aisle |
| Find makeable recipes at most N minutes from on-hand foods |
| 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 testTests 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:e2eVar | Effect |
| Skip cleanup; leave created resources for inspection |
| Skip the URL-import step (offline runners) |
| Override the default recipe URL |
| 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_planare 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. Callget_recipeorlist_meal_typesif you need the human-readable form.Storage
token/passwordand AI-providerapi_keyare 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, andauthenticateall 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.1by default.TANDOOR_MCP_HTTP_HOSTchanges 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, andHostandOriginheaders 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 toolsadd_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.
| Name | Required | Description | Default |
|---|---|---|---|
| code | No | ||
| note | No | ||
| amount | Yes | ||
| format | No | ||
| expires | No | ||
| food_id | Yes | ||
| unit_id | Yes | ||
| location_id | Yes | ||
| sub_location | No |
TDQS
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.
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.
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.
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.
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.
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 listADestructive
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.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Recipe ID | |
| servings | No | Default 1. Use 0 with list_recipe to delete. | |
| ingredients | No | Ingredient IDs to include. Omit for all. | |
| list_recipe | No | Existing shopping-list-recipe id to update |
TDQS
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.
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.
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.
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.
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.
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 entriesBIdempotent
Bulk check or uncheck many shopping entries by ID list.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | ||
| checked | Yes |
TDQS
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.
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.
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.
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.
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.
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 entriesAIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | ||
| checked | No | ||
| shopping_lists_add | No | ||
| shopping_lists_set | No | ||
| shopping_lists_remove | No | ||
| shopping_lists_remove_all | No |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| all | No | ||
| amount | No | ||
| format | No | ||
| food_id | No | ||
| unit_id | No | ||
| entry_id | No | ||
| location_id | No |
TDQS
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.
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.
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.
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.
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.
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 foodAIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| fdc_id | No | ||
| format | No | ||
| description | No | ||
| food_onhand | No | ||
| plural_name | No | ||
| shopping_list_ids | No | ||
| supermarket_category_id | No |
TDQS
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.
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.
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.
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.
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.
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
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | ||
| title | No | ||
| to_date | No | ||
| servings | Yes | ||
| from_date | Yes | ||
| recipe_id | No | ||
| addshopping | No | ||
| meal_type_id | Yes |
TDQS
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.
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.
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.
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.
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.
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[]
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| steps | Yes | ||
| format | No | Response detail level. Default "slim". | |
| private | No | ||
| internal | No | ||
| keywords | No | ||
| servings | No | ||
| nutrition | No | ||
| properties | No | ||
| source_url | No | ||
| description | No | ||
| waiting_time | No | ||
| working_time | No | ||
| servings_text | No | ||
| show_ingredient_overview | No |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| order | No | ||
| amount | Yes | ||
| format | No | ||
| checked | No | ||
| food_id | Yes | ||
| unit_id | No | ||
| ingredient | No | ||
| delay_until | No | ||
| list_recipe | No | ||
| mealplan_id | No | ||
| shopping_list_ids | No |
TDQS
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.
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.
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.
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.
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.
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 planCDestructiveIdempotent
Delete meal plan by ID
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
TDQS
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.
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.
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.
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.
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.
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 entryCDestructiveIdempotent
Delete a shopping entry by ID.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
TDQS
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.
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.
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.
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.
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.
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 groupAIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| group | Yes | Name of the section to turn off. The "always" section cannot be disabled. |
TDQS
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.
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.
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.
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.
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.
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 groupAIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| tier | No | Tier for a tiered section (default full). Not accepted for on/off sections. | |
| group | Yes | Name of the section to enable. Run list_tool_groups to see available sections. |
TDQS
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.
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.
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.
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.
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.
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 listsADestructive
Add a food to active shopping lists with optional amount/unit. Pass delete=true to remove this food from all active lists.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| amount | No | ||
| delete | No | ||
| unit_id | No |
TDQS
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.
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.
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.
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.
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.
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 spaceCRead-onlyIdempotent
Get the space currently active for this API token.
| Name | Required | Description | Default |
|---|---|---|---|
| format | No |
TDQS
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.
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.
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.
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.
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.
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 foodCRead-onlyIdempotent
Get food by ID.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| format | No |
TDQS
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.
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.
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.
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.
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.
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 statsARead-onlyIdempotent
Inspect security-guard rejection counters (PathGuardError, SsrfBlockedError) since process start. Useful for dashboards and "is anything probing me?" checks.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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 keywordCRead-onlyIdempotent
Get keyword by ID.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| format | No |
TDQS
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.
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.
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.
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.
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.
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 planCRead-onlyIdempotent
Get meal plan by ID
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
TDQS
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.
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.
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.
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.
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.
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 typeCRead-onlyIdempotent
Get a meal type by ID.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| format | No |
TDQS
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.
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.
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.
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.
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.
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 recipeARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Recipe ID | |
| format | No | Response detail level. Default "slim". |
TDQS
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.
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.
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.
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.
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.
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 entryCRead-onlyIdempotent
Get a shopping list entry by ID.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| format | No |
TDQS
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.
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.
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.
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.
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.
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 versionARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Recipe URL to import | |
| name | No | Optional name for the stub recipe (only used if create_stub_on_failure=true and both scrapers fail) | |
| format | No | Response detail level. Default "slim". | |
| create_stub_on_failure | No | Default false. When true AND both scraper attempts fail, create a minimal empty recipe pointing at the URL instead of throwing. |
TDQS
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.
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.
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.
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.
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.
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 jqARead-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".
| Name | Required | Description | Default |
|---|---|---|---|
| filter | Yes | jq filter to apply to the stashed value. Examples: ".results | length", ".results[0]", ".results | map({id, name})", "keys", ".count". | |
| handle | Yes | Stash handle from a prior tool result, e.g. "stash_<uuid>". |
TDQS
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.
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.
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.
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.
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.
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 statsARead-onlyIdempotent
Inspect the in-memory stash (count + total bytes). Diagnostic; not normally needed.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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 foodsCRead-onlyIdempotent
List foods. Optional: query (case-insensitive name match), root (parent id, 0 for top-level), tree (id), random, limit, page, page_size.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| root | No | ||
| tree | No | ||
| limit | No | ||
| query | No | ||
| format | No | ||
| random | No | ||
| page_size | No | ||
| root_tree | No | ||
| updated_at | No |
TDQS
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.
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.
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.
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.
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.
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 entriesARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| format | No | ||
| food_id | No | ||
| page_size | No | ||
| location_id | No | ||
| include_empty | No |
TDQS
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.
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.
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.
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.
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.
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 locationsCRead-onlyIdempotent
List inventory locations (pantry, fridge, freezer and so on). Optional: page, page_size.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| format | No | ||
| page_size | No |
TDQS
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.
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.
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.
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.
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.
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 keywordsCRead-onlyIdempotent
List keywords (recipe tags). Optional: query, root, tree, random, limit, page, page_size.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| root | No | ||
| tree | No | ||
| limit | No | ||
| query | No | ||
| format | No | ||
| random | No | ||
| page_size | No | ||
| root_tree | No | ||
| updated_at | No |
TDQS
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.
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.
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.
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.
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.
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 plansCRead-onlyIdempotent
List meal plans. Optional: from_date, to_date (YYYY-MM-DD), page, page_size
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| to_date | No | ||
| from_date | No | ||
| page_size | No |
TDQS
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.
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.
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.
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.
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.
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 typesARead-onlyIdempotent
List available meal types (breakfast, lunch, dinner, etc.)
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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 recipesARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| new | No | ||
| page | No | ||
| books | No | ||
| foods | No | ||
| query | No | ||
| units | No | ||
| filter | No | ID of a saved CustomFilter | |
| format | No | Response detail level. Default "slim". | |
| random | No | ||
| rating | No | ||
| makenow | No | Only recipes makeable with on-hand foods | |
| books_or | No | ||
| foods_or | No | ||
| internal | No | ||
| keywords | No | ||
| books_and | No | ||
| createdby | No | ||
| createdon | No | ||
| foods_and | No | ||
| page_size | No | ||
| updatedon | No | ||
| num_recent | No | ||
| rating_gte | No | ||
| rating_lte | No | ||
| sort_order | No | ||
| keywords_or | No | ||
| timescooked | No | ||
| books_or_not | No | ||
| cookedon_gte | No | ||
| cookedon_lte | No | ||
| foods_or_not | No | ||
| keywords_and | No | ||
| viewedon_gte | No | ||
| viewedon_lte | No | ||
| books_and_not | No | ||
| createdon_gte | No | ||
| createdon_lte | No | ||
| foods_and_not | No | ||
| updatedon_gte | No | ||
| updatedon_lte | No | ||
| keywords_or_not | No | ||
| timescooked_gte | No | ||
| timescooked_lte | No | ||
| keywords_and_not | No |
TDQS
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.
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.
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.
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.
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.
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)ARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | Response detail level. Default "slim". |
TDQS
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.
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.
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.
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.
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.
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 entriesARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| format | No | ||
| mealplan | No | ||
| page_size | No | ||
| updated_after | No |
TDQS
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.
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.
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.
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.
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.
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 listsBRead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| format | No | ||
| page_size | No |
TDQS
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.
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.
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.
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.
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.
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 groupsARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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 unitsCRead-onlyIdempotent
List units. Optional: query, limit, page, page_size, random.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| limit | No | ||
| query | No | ||
| format | No | ||
| random | No | ||
| page_size | No | ||
| updated_at | No |
TDQS
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.
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.
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.
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.
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.
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 itemBIdempotent
Move a whole inventory entry to another location. Required: entry_id, to_location_id. Optional: sub_location (null clears it).
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | ||
| entry_id | Yes | ||
| sub_location | No | ||
| to_location_id | Yes |
TDQS
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.
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.
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.
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.
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.
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 ingredientAIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes |
TDQS
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.
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.
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.
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.
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.
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 recipesARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| books | No | Recipe book names — recipe must be in ANY of these | |
| foods | No | Food names the recipe must contain ALL of | |
| query | No | Fuzzy match against recipe names | |
| format | No | Response detail level. Default "slim". | |
| random | No | ||
| makenow | No | Only recipes makeable with currently on-hand foods | |
| keywords | No | Keyword names — recipe must have ANY of these | |
| page_size | No | ||
| rating_gte | No | ||
| rating_lte | No | ||
| sort_order | No | score | -score | name | -name | lastcooked | -lastcooked | rating | -rating | times_cooked | -times_cooked | |
| exclude_foods | No | Food names the recipe must NOT contain any of | |
| timescooked_gte | No | ||
| timescooked_lte | No | ||
| exclude_keywords | No | Keyword names to exclude |
TDQS
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.
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.
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.
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.
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.
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 foodADestructiveIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| name | No | ||
| fdc_id | No | ||
| format | No | ||
| properties | No | ||
| description | No | ||
| food_onhand | No | ||
| plural_name | No | ||
| shopping_list_ids | No | ||
| properties_food_amount | No | ||
| properties_food_unit_id | No | ||
| supermarket_category_id | No | ||
| remove_property_type_ids | No |
TDQS
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.
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.
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.
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.
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.
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 planCIdempotent
Update meal plan. Required: id. All other fields optional
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| note | No | ||
| title | No | ||
| to_date | No | ||
| servings | No | ||
| from_date | No | ||
| recipe_id | No | ||
| meal_type_id | No |
TDQS
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.
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.
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.
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.
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.
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 recipeBDestructiveIdempotent
Update recipe metadata and content. Only provide fields you want to update. All fields optional except id.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Recipe ID | |
| name | No | ||
| steps | No | ||
| format | No | Response detail level. Default "slim". | |
| private | No | ||
| internal | No | ||
| keywords | No | ||
| servings | No | ||
| nutrition | No | ||
| properties | No | ||
| source_url | No | ||
| description | No | ||
| waiting_time | No | ||
| working_time | No | ||
| servings_text | No | ||
| show_ingredient_overview | No |
TDQS
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.
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.
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.
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.
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.
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 entryAIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| order | No | ||
| amount | No | ||
| format | No | ||
| checked | No | ||
| food_id | No | ||
| unit_id | No | ||
| delay_until | No | ||
| shopping_list_ids | No |
TDQS
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.
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.
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.
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.
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.
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.
46 tool updates
v3.4.0- First observed
add_inventory_item - First observed
add_recipe_to_shopping_list - First observed
bulk_check_shopping_entries - First observed
bulk_update_shopping_entries - First observed
consume_inventory_item - First observed
create_food - First observed
create_meal_plan - First observed
create_recipe - First observed
create_shopping_entry - First observed
delete_meal_plan - First observed
delete_shopping_entry - First observed
disable_tool_group - First observed
enable_tool_group - First observed
food_shopping_update - First observed
get_current_space - First observed
get_food - First observed
get_guard_stats - First observed
get_keyword - First observed
get_meal_plan - First observed
get_meal_type - First observed
get_recipe - First observed
get_shopping_entry - First observed
get_version - First observed
import_recipe_from_url - First observed
jq_query - First observed
jq_stash_stats - First observed
list_foods - First observed
list_inventory_entries - First observed
list_inventory_locations - First observed
list_keywords - First observed
list_meal_plans - First observed
list_meal_types - First observed
list_recipes - First observed
list_recipes_flat - First observed
list_shopping_entries - First observed
list_shopping_lists - First observed
list_tool_groups - First observed
list_units - First observed
move_inventory_item - First observed
parse_ingredient - First observed
related_recipes - First observed
search_recipes - First observed
update_food - First observed
update_meal_plan - First observed
update_recipe - First observed
update_shopping_entry
TDQS
Scored across 46 tools
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.
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.
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.
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
Related MCP Connectors
Recipe search, ingredient matching, nutrition filters and a private cookbook for any AI agent.
Scraps Kitchen gives any AI agent a persistent, household-aware kitchen memory. Unlike generic chatbot recall, Scraps maintains structured cooking data: what's in your fridge (with freshness tracking), who you cook for (with allergens, dietary restrictions, and preferences), your recipe collection (with cook notes and per-diner ratings), your shopping list, and your kitchen equipment. 27 tools across 6 domains let agents read kitchen context, suggest meals that respect dietary safety, update the pantry after cooking, and build a history of what works for your household. Every interaction makes the data richer. Cooking history, preference signals, kitchen awareness = better suggestions next time. All tools work via oAuth and a free scraps.kitchen account.
Connect AI agents to 1000+ apps with managed authentication and tool-calling.
Search, save, organize, cook, and share recipes with any AI assistant.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Mealie recipe databases, allowing users to manage and query their recipes through natural language conversations.17 npmMIT
- AlicenseBqualityDmaintenanceEnables 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.11332 npm3MIT
- FlicenseNot gradedqualityDmaintenanceEnables interaction with the Tandoor Recipe Manager via the Model Context Protocol. It allows users to search and create recipes, manage meal plan entries, and update shopping list items through natural language.1-
- AlicenseNot gradedqualityCmaintenanceHousehold-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