mcp-ptitchef
mcp-ptitchef
一个在 Ptitchef 上读取食谱的 MCP 服务器。只读,无需 API 密钥,无需账户。
存在的原因
Ptitchef 通过食材家族的树状结构浏览其食谱,并且它随意地书写每个类别的地址。同类事物在一行中显示为 chou-kale,在下一行显示为 recette-de-petits-pois,在第三行显示为 recettes-aux-feves。没有规则可以从食材名称推导出其中一个。
因此,手工构建的地址会落空,而网站对落空的回应是将读者发送到树的根节点,并返回 HTTP 200 和根节点自身的类别。一个猜测了 slug 的模型会得到一个关于它从未请求过的层级的完整而自信的答案。
这个服务器发布这棵树,因此类别通过网站赋予的名称来打开。
Related MCP server: France BOAMP MCP
工具
list_categories
列出食谱浏览所依据的类别。不带参数调用时,它返回食材家族;将某个家族的 slug 传回,以列出其所包含的内容。
Argument | Type | Meaning |
| string, 可选 | 要打开的家族的 slug,来自之前的调用。省略它以读取根节点。 |
| integer, 可选 | 要渲染的条目数,默认 50,最多 200。 |
{
"family": null,
"family_title": "Recettes de cuisine sur Ptitchef",
"categories": [
{
"slug": "legume",
"title": "Légume",
"url": "https://www.ptitchef.com/recettes/cat/legume",
"description": null,
"sample_children": [
{
"slug": "pois-mange-tout",
"title": "Pois mange-tout",
"url": "https://www.ptitchef.com/recettes/pois-mange-tout"
}
],
"is_family": true
}
],
"category_count": 15,
"categories_published": 15,
"url": "https://www.ptitchef.com/recettes",
"source": "Ptitchef",
"notes": ["…"]
}search_recipes
按菜肴或食材搜索。网站以两种方式之一作答,kind 说明是哪一种。
Argument | Type | Meaning |
| string | 一道菜肴或一种食材,用法语。 |
| integer, 可选 | 要渲染的行数,默认 20,最多 100。 |
搜索 puree de patate douce 会返回 kind: "topic",并带有 topic_slug: "puree-de-patates-douces":网站为它保存了一个页面,将搜索发送到那里,总数统计该页面所包含的内容。搜索 soupe froide concombre menthe 会返回 kind: "free_text":网站没有这样的页面,按自己的方式作答,总数是它提供的行数。
browse_recipes
逐页读取一个类别,或网站长期保留的三个列表之一。
Argument | Type | Meaning |
| string, 可选 | 来自 |
|
| 网站长期保留的列表之一。 |
| integer, 可选 | 要读取的类别的页码。 |
| integer, 可选 | 要渲染的行数,默认 20。 |
search_by_ingredients
读取网站自带的冰箱搜索:输入一到五种食材,输出包含它们的食谱。
Argument | Type | Meaning |
| string[] | 一到五种食材,用法语。 |
| integer, 可选 | 要渲染的行数,默认 20。 |
get_recipe
读取一份食谱,并按请求重新缩放其食材用量。
Argument | Type | Meaning |
| string | 来自搜索或列表的某一行的 |
| integer, 可选 | 将食材用量重新缩放为这么多份。 |
每一行都带有 scaling,说明运算做了什么:scaled 是精确的,rounded 被调整以保持可用,unscaled 不携带任何可被乘的内容。将 1 oeuf 加倍得到 2 oeufs;将其减半得到标记为 rounded 的 1 oeuf,因为半个鸡蛋不是厨房量取的数量。
scale_ingredients
同样的运算,离线进行,适用于任何来源的任何法语食材列表。
Argument | Type | Meaning |
| string[] | 要重新缩放的行。 |
| number | 要应用的乘数。 |
| numbers | 或者从中读取因子的那一对数值。 |
get_recipe_translations
列出食谱发布所用的其他语言。Ptitchef 是一个发布相同食谱的网站网络的法语版,每个页面都会指明其对应版本。有多少种是食谱自己的事:较新的食谱会列出二十多种,较旧的则一种也没有,答案说明页面所携带的内容,而不是这里固定的数字。
答案拒绝夸大之处
网站替换的层级不是所请求的层级。 未知家族会以 HTTP 200 和树的根节点作答,因此答案返回的地址决定了它是哪个层级。未持有的家族被报告为 not_found,而不是渲染为网站改而提供的类别。
家族旁边的条目是摘录。 根节点显示三个条目,后面跟着网站自己打印的省略号。它们在 sample_children 下返回,并附注说明它们是什么,因为将它们渲染为家族内容会把一个有九十个条目的家族呈现成只有三个。
两个计数,因为它们回答两个问题。 categories_published 是页面列出的内容,category_count 是答案渲染的内容。每当 limit 截断列表时它们就会不同,附注说明相差多少,而不是让一个被截断的列表读起来像完整的。
没有地址的条目被搁置而不是渲染。 网站发布的无链接标题不携带可传回的 slug,因此它被丢弃、计数,并在附注中说明。
页面未携带的简介是 null,绝不是空字符串。 空的描述会提供从未发布过的措辞。
一个列表有两个总计,统计不同的东西,答案说明到达的是哪一个。 网站发送到类别页面的搜索报告该类别的总计;网站自己作答的搜索报告它提供的行数。将两者相加会把目录加到页面上。
评分是网站计算出的数字。 一行在其数据中写明 3.8,并绘制四颗星。绘制的数字保持不变。
超过最后一页的页面会以网站提供的页面返回。 网站以第一页作答,因此报告所请求的页码会让调用者永远在同样的行中打转。
冰箱搜索的计数远超其提供的内容。 它为三种食材找到八十九份食谱,在一页上提供其中二十四份,并且没有链接其他页。答案说明这两个数字,并说其余部分无法读取。
指南不是列表,答案说明到达的是哪一个。 有些主题以网站编写的指南形式提供:食谱分组在网站自己的标题下,没有总计,行只携带名称和地址。kind 在那里显示 guide,对同一 slug 调用 browse_recipes 会读取该主题的完整列表及其总计:épinards 以 32 条的指南返回,而其列表包含 736 条。
用另一份食谱代替所请求的食谱时,渲染为缺失。 食谱地址中的词语是装饰性的,而其中的数字不是:请求网站不持有的数字会带回一份无关的食谱,以 HTTP 200 和完整细节返回。返回的数字与请求的数字进行比较。
没有什么是盲目相乘的。 可计数的事物落在厨师从其中取出的最小份额上:当半个无法量取时取整个,比如鸡蛋;当半个可以倒出或分开时取半个,比如小袋。质量在取整前先转换到更小的单位,因此小于一的数量永远不会取整为零。一小撮保留自己的词汇,其数量被相乘,因为一个的大小由厨师决定。
未重新缩放就交回的列表只说明一次,而不是逐行说明。 没有请求份数就没有运算,将每一行标记为 unscaled 会声称它们中没有任何可乘的内容。
网站估算的成本被重复,而不是重新计算。 这是网站自己的数字,网站的读者质疑它过低;答案说明这一点,而不是悄悄传递或默默丢弃。
安装
npx mcp-ptitchefClaude Code
claude mcp add ptitchef -- npx -y mcp-ptitchef任何 MCP 客户端
{
"mcpServers": {
"ptitchef": {
"command": "npx",
"args": ["-y", "mcp-ptitchef"]
}
}
}容器
docker build -t mcp-ptitchef .
docker run -i --rm mcp-ptitchef容器需要能够访问 www.ptitchef.com,仅此而已。它不需要任何凭据,因为本来就没有可取的凭据。
设置
每个设置都是一个环境变量,并且都不是必需的。超出范围的值会被拒绝,并在 stderr 上输出一行,默认值保持不变:无法生效的设置会说明这一点,而不是被悄悄截断。
Variable | Default | Range |
| — | 你自己的标识符。本项目的标识符会保持附加,以便网站可以联系到真人。 |
| 1500 | 1000 到 60000 |
| 20000 | 1000 到 120000 |
| 3 | 0 到 8 |
| 900000 | 0 到 86400000,0 关闭存储 |
| 200 | 1 到 5000 |
| 8000000 | 100000 到 64000000。超过此值,页面会被放弃而不是整体保留 |
| 60000 | 5000 到 600000。包括一次读取的全部、其重试及等待 |
|
|
|
节奏下限无法从外部降低。该网站可免费阅读,且未发布爬取延迟,这更应谨慎行事,而不是快速访问的许可。
作为库使用
读取层单独发布,带有其节奏、存储和错误词汇,不附带任何协议:
import { PtitchefClient } from "mcp-ptitchef/client";错误
六个代码,仅此而已。调用者根据打开消息的代码进行分支。
代码 | 含义 |
| 网站在该地址下没有任何内容 |
| 参数无法生成请求 |
| 网站要求此客户端放慢速度。它没有说明是否有匹配项 |
| 答案以本服务器无法读取的形式到达 |
| 请求无法完成 |
| 截止时间内没有收到答案 |
署名
食谱、标题和类别属于 Ptitchef。每个回答都带有来源,展示给读者的列表应注明网站并链接到页面。
贡献
参见 CONTRIBUTING.md。测试优先,覆盖率下限为 100%,所有内容遵循的规则是:服务器绝不说数据未携带的任何内容。
根据 MIT 许可。
mcp-ptitchef(法语)
一个读取 Ptitchef 食谱的 MCP 服务器。只读,无需 API 密钥,无需账户。
为什么存在
Ptitchef 通过一棵食材家族树来浏览其食谱,并自由书写每个类别的地址。同一种东西在一行叫 chou-kale,下一行叫 recette-de-petits-pois,第三行叫 recettes-aux-feves。没有任何规则可以从食材名称推导出其中一个。
因此,手工构造的地址会落空,网站也会答非所问:将读者重定向到树的根部,返回 HTTP 200,并带有根部的类别。一个猜了 slug 的模型会收到一个完整而确定的、关于它从未请求过的层级的响应。
这个服务器发布这棵树,以便一个类别可以通过网站赋予它的名称打开。
工具
list_categories
列出食谱可以按之浏览的类别。不带参数调用时,它返回食材家族;将某个家族的 slug 传回给它时,它返回该家族包含的内容。
参数 | 类型 | 含义 |
| 字符串,可选 | 要打开的家族的 slug,来自之前的调用。若缺省,则从树的根部读取。 |
| 整数,可选 | 返回的条目数,默认 20,最多 200。 |
search_recipes
按菜肴或食材搜索。网站以五种方式回应,kind 说明是哪一种:当它把搜索发送到自己的某个类别页面时是 topic,当它按自己的条件回应时是 free_text,当它为这个主题撰写了一篇指南时是 guide,当它认为词语足够精确以打开一张卡片时是 recipe,当它因未能理解而提供其首页时是 unmatched。
参数 | 类型 | 含义 |
| 字符串 | 一个菜肴或食材,用法语。 |
| 整数,可选 | 返回的行数,默认 20,最多 100。 |
browse_recipes
逐页浏览一个类别,或浏览网站维护的三个列表之一。
参数 | 类型 | 含义 |
| 字符串,可选 | 来自 |
|
| 网站常设列表之一。 |
| 整数,可选 | 要读取的某个类别的页面。 |
| 整数,可选 | 返回的行数,默认 20。 |
search_by_ingredients
读取网站的“冰箱搜索”:输入一到五种食材,输出包含这些食材的食谱。
参数 | 类型 | 含义 |
| 字符串[] | 一到五种食材,用法语。 |
| 整数,可选 | 返回的行数,默认 20。 |
get_recipe
读取一份食谱,并可按要求重新调整其食材的用量。
参数 | 类型 | 含义 |
| 字符串 | 由搜索或列表返回的某一行的 |
| 整数,可选 | 将食材重新调整为这个份数。 |
每一行都带有一个 scaling,说明算术做了什么:scaled 是精确的,rounded 被移动过以保持可用,unscaled 没有任何可乘的内容。将 1 oeuf 加倍得到 2 oeufs;将其除以二得到标记为 rounded 的 1 oeuf,因为半个鸡蛋不是厨房可以计量的数量。
scale_ingredients
同样的算术,离线进行,适用于任何法语列表,无论其来源如何。
参数 | 类型 | 含义 |
| 字符串[] | 要重新调整的行。 |
| 数字 | 要应用的乘数。 |
| 数字 | 或者可以推导出乘数的那一对。 |
get_recipe_translations
列出一份食谱已发布的其他语言。Ptitchef 是一个发布相同食谱的网站网络的法语版,每个页面都会点名其对应版本。有多少个取决于食谱本身:新近的食谱会列出二十多个,旧的则一个也没有。
回答拒绝断言的内容
指南不是列表,回答会说明返回的是哪一种。 某些主题由网站撰写的指南提供,没有总数,其行带有名称、地址、图片和投票数。此时 kind 为 guide,而对同一 slug 调用 browse_recipes 会返回该主题的完整列表及其总数:épinards 返回一份包含 32 个食谱的指南,而其列表包含 736 个。
一份代替另一份被提供的食谱会被呈现为缺失。 食谱地址中的词语是装饰性的,而其中的编号则不是:请求一个网站不持有的编号会返回一份毫不相关的食谱,HTTP 200,且带有完整详情。返回的编号会与请求的编号进行比较。
列表无法读取的页面不是缺失。 一个带有计数但没有可读列表的标题,是这个服务器无法读取的页面,而它返回的正是这一点,而不是“没有食谱,网站说它有 3200 个”。
评分是网站计算出的数字。 一行在其数据中声明 3.8,却画出四颗星;发布的是计算出的数字,而一个不计算任何评分的指南也不会发布任何评分。
总数统计的是什么,要从回答中读取。 网站发送到某个类别页面的搜索返回该类别的总数;网站自行处理的搜索返回它统计的数量,有时会超过所返回的行数。只有在两个数字都能证明时,说明才会这样说。
没有任何东西会被盲目地乘以。 可数物会落到厨师从单个物品中取用的最小份量:在半个无法计量的地方取整数,如一个鸡蛋;在可以倒出或切开的地方取一半,如一小袋。质量在取整前会先降一个单位,因此低于单位的量永远不会降到零。一小撮保留自己的词汇,其数量会被乘以,因为一撮的大小由厨师决定。
未进行缩放而返回的列表会一次性说明这一点,而不是逐行说明。没有 servings 就没有算术,而将每一行标记为 unscaled 会断言其中没有任何一行带有可乘的内容。
估算成本会被重复,而绝不会重新计算。 这是网站的数字,按页面所声明的份数发布,回答会说明是哪一个。
从页面中读取的地址不会离开该网站。 指向别处的行会被剔除,而不是以“食谱的公开页面”这一标签发布。
安装
npx mcp-ptitchefClaude Code
claude mcp add ptitchef -- npx -y mcp-ptitchef任何 MCP 客户端
{
"mcpServers": {
"ptitchef": {
"command": "npx",
"args": ["-y", "mcp-ptitchef"]
}
}
}容器
docker build -t mcp-ptitchef .
docker run -i --rm mcp-ptitchef容器必须能够访问 www.ptitchef.com,仅此而已。它不接受任何标识符,因为本来就没有任何标识符可接受。
设置
每个设置都是一个环境变量,且都不是必需的。超出范围的值会被拒绝,并在 stderr 上输出一行,默认值继续生效:一个无法应用的设置会说明这一点,而不是被悄悄拉回范围内。
变量 | 默认值 | 范围 |
| — | 您的标识符。项目的标识符仍会附加在后面,以便网站能够联系到一个人。 |
| 1500 | 1000 到 60000 |
| 20000 | 1000 到 120000 |
| 3 | 0 到 8 |
| 900000 | 0 到 86400000,0 关闭存储 |
| 200 | 1 到 5000 |
|
|
|
节奏下限不能从外部降低。该网站可自由阅读,且未公布任何抓取延迟,这正是一个保持谨慎的理由。
作为库使用
读取层单独发布,带有自己的节奏、存储和错误词汇,不附带任何协议:
import { PtitchefClient } from "mcp-ptitchef/client";错误
六个代码,一个也不多。调用方根据打开消息的代码进行分支。
代码 | 含义 |
| 该网站在此地址没有任何内容 |
| 这些参数无法构成有效的请求 |
| 该网站要求此客户端放慢速度。这并不说明它提供什么内容 |
| 响应以该服务器无法读取的形式到达 |
| 请求未能完成 |
| 在时限内没有收到任何响应 |
署名
食谱、标题和分类均归 Ptitchef 所有。每条响应都带有来源,展示给读者的列表必须注明网站出处并链接到相应页面。
贡献
参见 CONTRIBUTING.md。测试优先,覆盖率下限为 100%,并且所有内容遵循的规则是:服务器绝不说出数据本身不承载的内容。
以 MIT 许可证发布。
Available Tools
7 toolsbrowse_recipesBrowse a category or a standing listARead-onlyIdempotent
Read the recipes under one category of Ptitchef, page by page, or one of the lists the site keeps standing. Pass 'category' with a slug from list_categories or from a search's 'topic_slug', or pass 'listing' for one of: latest, top_rated, most_viewed. Never build a category slug by hand: the site writes them freely and answers an address it does not hold by serving another page. The page in the answer is the one the site served, which is the first page again when the page asked for is past the last one.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | The page of a category to read. A standing list has one page only. | |
| limit | No | Rows to render, 20 by default. | |
| listing | No | One of the site's standing lists, read instead of a category. | |
| category | No | A category slug: one from list_categories whose 'is_family' is false, or the 'topic_slug' a search answered with. A family's slug belongs to list_categories instead. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | The address the listing was read from. |
| kind | Yes | How the listing came to be, which decides what its total counts. 'topic' means the site answered a search from a page of its own; 'free_text' means it answered on its own terms. |
| page | Yes | The page that was read, which is the one the site served. |
| asked | Yes | What was asked for: a search, a category, or a list of ingredients. 'query' carries the same value under the name every source of recipes publishes it in. |
| notes | Yes | What qualifies this answer: what its total counts, what it left out, and where the site answered from an address other than the one asked for. Read these before quoting a figure. |
| query | Yes | What was asked for, under the name a search publishes it in. |
| title | Yes | The site's own heading for the listing. |
| folded | Yes | Rows naming a recipe already held. A guide lists one recipe under two headings where it belongs to both; such a row is counted in 'rows_seen' and rendered once. |
| source | Yes | The site this answer was read from. Credit it when showing a row. |
| results | Yes | |
| rows_seen | Yes | Rows the site served on this page, before any were set aside. |
| topic_slug | Yes | The category page this listing was served from. Pass it to browse_recipes as 'category' to read the topic's further pages, and its total where this answer carries none. |
| single_page | Yes | True when the site serves this listing on one page and offers no further one. |
| result_count | Yes | Rows rendered here. |
| total_available | Yes | Recipes the site says this listing holds. Null when it published no figure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/non-destructive annotations, the description discloses a non-obvious behavioral quirk: the site serves another page when it does not hold the address, and pages past the last one silently return the first page. This is exactly the kind of edge-case behavior an agent needs before invoking the 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 sentences, and each earns its place: the core operation, the two input modes, the slug-authoring warning, and the pagination fallback behavior. The main purpose is front-loaded and the caveats are placed after the primary semantics.
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 read-only paginated browsing tool with rich schema descriptions and an output schema, the definition covers the dangerous non-obvious behaviors that could otherwise cause an agent to misread results: slug tolerance and page wrapping. Nothing essential 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?
The schema already documents all parameters at 100% coverage, but the description adds usable guidance about where category slugs come from, that listing values are mutually exclusive with category, and the warning against hand-built slugs. It reinforces but does not deeply extend the schema's parameter descriptions, so a 4 is appropriate.
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: 'Read the recipes under one category of Ptitchef, page by page, or one of the lists the site keeps standing.' It clearly states both operating modes and distinguishes this from siblings like list_categories (which returns categories) and search_recipes (which returns search results).
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 gives explicit input-selection rules: pass 'category' with a slug from list_categories or a search's 'topic_slug', or pass 'listing' with one of the named standing lists. It also gives a strong exclusion: never hand-build a category slug. It does not explicitly name the sibling tools to use instead, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recipeRead one recipeARead-onlyIdempotent
Read one Ptitchef recipe: its ingredients, method, times, rating, nutrition and the cost the site estimates for it. Pass the 'id' of a row from search_recipes, browse_recipes or search_by_ingredients. Give 'servings' to rescale the ingredients, and read each line's 'scaling' before quoting a quantity: 'scaled' is exact arithmetic, 'rounded' was moved to stay usable, and 'unscaled' carries nothing that could be multiplied. A time or a figure the site publishes none of comes back null, never zero.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The 'id' of a row from a search or a listing, which is the recipe's own page path. | |
| servings | No | Rescale the ingredients to this many servings. Left out, the ingredients come back as published. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| faq | Yes | |
| url | Yes | The public page. Show this when citing the recipe. |
| notes | Yes | What qualifies this answer: what the arithmetic did, what it could not do, and what the site states rather than this server. Read these before quoting a quantity or a cost. |
| steps | Yes | The method, one line per step, in the shape every source of recipes publishes it in. 'illustrated_steps' carries the same lines beside the photograph the site took of each. |
| title | Yes | |
| yield | Yes | |
| author | Yes | |
| rating | Yes | 1 to 5, as the site states it. |
| source | Yes | The site this recipe was read from. Credit it when showing it. |
| cuisine | Yes | |
| category | Yes | |
| keywords | Yes | |
| modified | Yes | |
| image_url | Yes | |
| nutrition | Yes | As published, per the serving size it names. |
| published | Yes | |
| author_url | Yes | |
| difficulty | Yes | The site's own wording, such as 'facile'. |
| attribution | Yes | |
| description | Yes | |
| ingredients | Yes | The lines as published where no servings were asked for, in which case 'yield.factor' is null and each line's 'scaling' describes no arithmetic. Pass 'servings' to rescale them. |
| cook_minutes | Yes | |
| prep_minutes | Yes | |
| rating_count | Yes | |
| review_count | Yes | |
| translations | Yes | The other languages this recipe was published in, which get_recipe_translations answers on its own for a caller who wants nothing else. |
| total_minutes | Yes | |
| estimated_cost | Yes | What the site estimates the ingredients cost, with the currency it names. Repeated as published: it is the site's figure and readers of the site dispute it. |
| illustrated_steps | Yes | |
| steps_are_one_block | Yes | True when the site published its method as one block of prose, so the single step above is that block rather than the first of several. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, open-world, idempotent, and non-destructive behavior. The description adds valuable behavioral detail beyond that: it explains the 'scaling' field's values ('scaled', 'rounded', 'unscaled') and their meaning for quoting quantities, and states that absent site figures come back null, never zero. No contradiction with annotations.
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 sentences, each earning its place: scope, id sourcing, servings, and output semantics. It is dense but front-loaded with the core purpose, and no sentence 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?
With an output schema present and annotations covering the safety profile, the description provides enough context for correct invocation. It handles id provenance, optional servings, scaling nuances, and null semantics; minor omissions like invalid-id behavior are not critical.
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 schema already documents both parameters. The description adds value by specifying that valid 'id' values come from rows of three sibling tools and clarifies that 'servings' rescales ingredients, echoing the schema in more actionable terms.
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 ('Read'), a unique resource ('one Ptitchef recipe'), and enumerates what is returned (ingredients, method, times, rating, nutrition, cost). It also differentiates from search siblings by instructing the agent to pass an id from search_recipes, browse_recipes, or search_by_ingredients.
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 clear context: use with an id coming from the three listed search tools, and optionally pass servings to rescale. It names the upstream tools that produce valid ids, but doesn't explicitly state when not to use it (e.g., when scale_ingredients might be more appropriate), so it stops short of full exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recipe_translationsFind a recipe in the other languages it was published inARead-onlyIdempotent
List the other languages a Ptitchef recipe was published in, with the page of each. get_recipe already carries this list under 'translations', so call this one only where the rest of the recipe is not wanted. Pass the 'id' of a row from a search or a listing. The pairing is the site's own: each page names its counterparts, and this repeats those names rather than matching titles. How many there are belongs to the recipe: a recent one names more than twenty, from German to Hindi, and an older one names none. An empty list is what the site published, and the read succeeded.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The 'id' of a row from a search or a listing, which is the recipe's own page path. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| url | Yes | The French page these counterparts were read from. |
| notes | Yes | |
| title | Yes | |
| source | Yes | |
| translations | Yes | |
| translation_count | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent, open-world, and non-destructive behavior. The description adds meaningful nuanced behavior: the translation pairing is site-defined and repeated rather than title-matched, the count varies by recipe, and an empty list still means the read succeeded. This goes well beyond the annotation hints.
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 front-loaded with the core purpose and is not padded. A few repeated details from the schema and the illustrative language examples add length, but each sentence contributes useful operational or interpretive context for an agent.
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 single-parameter read tool with an output schema and strong annotations, the description is complete: it explains when to use this tool instead of get_recipe, how to source the id, what the result represents, how size varies, and how to interpret an empty 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 coverage is 100%, and the schema already explains that 'id' is 'The id of a row from a search or a listing, which is the recipe's own page path.' The description repeats this same guidance without adding substantial new parameter semantics, so the baseline of 3 is appropriate.
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?
Description names a specific verb and resource: 'List the other languages a Ptitchef recipe was published in, with the page of each.' It explicitly contrasts with the sibling get_recipe, which already contains this list, so an agent can immediately distinguish this tool from the main recipe-fetching tool.
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 gives a clear when-to-use rule: call this only when the rest of the recipe is not wanted, because get_recipe already carries the translations list. It also tells the agent exactly what input to pass: the 'id' of a row from a search or listing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_categoriesList the categories recipes are browsed byARead-onlyIdempotent
List the categories Ptitchef browses its recipes by. Called without arguments it returns the families of ingredients; pass a family's slug as 'family' to list the categories it holds. Read this before building an address by hand: the site writes its slugs freely, so the same vegetable appears as 'chou-kale' on one line and as 'recette-de-petits-pois' on the next, and a slug that was guessed lands on a page the site does not hold. Each entry carries the slug to pass back and the page to open.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Entries to render, 20 by default and 200 at most. A level holding more than this says so, and 'categories_published' always states what the page listed. | |
| family | No | The slug of a family to open, taken from a previous call. Leave it out to read the families themselves, which is where the tree starts. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | The page these categories were read from. |
| notes | Yes | |
| family | Yes | The family that was opened, or null for the root. |
| source | Yes | |
| categories | Yes | |
| family_title | Yes | The site's own heading for this level. Null when the page carries none. |
| category_count | Yes | Entries rendered here. |
| categories_published | Yes | Entries the page listed, before any were rendered. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is read-only, idempotent, non-destructive, and open-world. The description adds valuable behavioral context beyond those annotations by warning that slugs are written freely by the site, that guessed slugs land on non-existent pages, and that entries carry the slug to pass back. This directly addresses the open-world nature of the catalog and prevents a common failure 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?
The description is compact and front-loaded: the core action and the two-mode behavior appear first, followed by a necessary warning about slug instability. Every sentence contributes either to correct invocation or to avoiding an error, with no filler or repetition of schema content.
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?
Given the tool's two-level hierarchy, optional parameters, rich annotations, and existing output schema, the description covers everything an agent needs: how to start, how to descend, and why slug guessing is unsafe. Pagination and return details are already handled by the schema and output schema, so nothing essential 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?
Schema description coverage is 100%, so the schema fully documents 'limit' and 'family.' The description reinforces that 'family' should come from a previous call and that omitting it reads the families, but it does not add meaning significantly beyond the schema. Baseline 3 is appropriate because the schema carries the parameter documentation burden.
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: 'List the categories Ptitchef browses its recipes by.' It also clarifies the hierarchical relationship between families of ingredients and categories, which separates it from sibling tools like search_recipes, browse_recipes, and get_recipe. The two-call pattern (no argument for families, family slug for categories) makes the tool's purpose 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?
The description gives explicit instructions for both usage modes: called without arguments it returns families, and passing a family's slug as 'family' returns its categories. It also warns against hand-building slugs. It does not explicitly name sibling alternatives or state when to prefer this tool over search/browse tools, but the context is clear enough for an agent to select it for category-tree navigation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scale_ingredientsRescale an ingredient listARead-onlyIdempotent
Rescale a list of ingredient lines to a different number of servings, without contacting any website. Give either 'factor' directly, or 'from_servings' and 'to_servings' and the factor is computed. Works on any French ingredient list, whatever its source, so it also serves a recipe pasted in by hand. Quantities in grams or millilitres are multiplied and rounded to readable values; a countable thing lands on a half when half of one can be poured, weighed or cut, as a boîte, a sachet, a feuille de gélatine or a cuillère can, and on a whole one when it cannot, as an oeuf, a jaune or a blanc; approximate measures such as a pinch or a handful have their count multiplied in whole units and stay in their own vocabulary. A line writing an article where a digit would go, as in 'un bouchon de rhum' or 'une pincée de sel', is read as one of that measure. Lines carrying no quantity are returned untouched and flagged. Prefer this over doing the arithmetic yourself.
| Name | Required | Description | Default |
|---|---|---|---|
| factor | No | Multiplier to apply. Use this or the from/to pair. | |
| ingredients | Yes | Ingredient lines, for example ['200 g de farine', '3 oeufs', 'sel']. | |
| to_servings | No | How many servings are wanted. | |
| from_servings | No | How many servings the list is written for. |
Output Schema
| Name | Required | Description |
|---|---|---|
| notes | Yes | |
| factor | Yes | |
| ingredients | Yes | |
| scaled_count | Yes | |
| rounded_count | Yes | Lines whose value rounding moved away from the exact product, not lines that could have been rounded. |
| unscaled_count | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnly, idempotent, and non-destructive behavior, but the description goes far beyond them: it explains rounding to readable values, the half/whole rounding rule based on countable items, treatment of approximate measures, parsing of articles as one unit, and that unquantified lines are returned untouched and flagged. This is rich behavioral disclosure with no contradiction to the annotations.
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 sentence front-loads the core purpose and the no-network constraint. The following sentences pack dense but relevant detail: parameter alternatives, French-list applicability, rounding rules with concrete examples, edge-case handling, and a closing usage preference. Every clause earns its place; there is no 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?
Given the tool's complexity, the description covers domain scope, parameter alternatives, rounding rules, approximate measures, and unquantified lines. An output schema exists, so return-value details are not required. The only notable omission is the fallback or error behavior when no scale parameter is provided, since the schema does not enforce one of factor/from_servings/to_servings.
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 schema already describes every parameter, so the baseline is 3. The description adds meaning by explaining the relationship between factor and from_servings/to_servings, stating that the factor is computed from the serving pair. It also gives concrete ingredient-line examples. A minor gap is that it does not explicitly state what happens if neither factor nor the from/to pair is supplied, though the schema only requires ingredients.
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: 'Rescale a list of ingredient lines to a different number of servings,' and adds the key constraint 'without contacting any website.' This clearly distinguishes it from sibling recipe browsing and search tools, which focus on finding or retrieving recipes rather than transforming ingredient lines.
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 clear context: it works on any French ingredient list, including pasted recipes, and explicitly says 'Prefer this over doing the arithmetic yourself.' It does not name a competing sibling tool or state explicit exclusions, but no sibling targets the same operation, so the guidance is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_by_ingredientsFind recipes from the ingredients a cook hasARead-onlyIdempotent
Find Ptitchef recipes from the ingredients a cook already has. Give one to 5 ingredients in French, as a cook would name them ("poulet", "citron"). The site counts every recipe it finds and serves one page of them, so 'total_available' can be far larger than the rows returned, and the rest cannot be reached. A longer list than the site's own form reads is refused rather than sent and silently cut.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Rows to render, 20 by default. | |
| ingredients | Yes | One to 5 ingredients, in French. The site reads no more than that. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | The address the listing was read from. |
| kind | Yes | How the listing came to be, which decides what its total counts. 'topic' means the site answered a search from a page of its own; 'free_text' means it answered on its own terms. |
| page | Yes | The page that was read, which is the one the site served. |
| asked | Yes | What was asked for: a search, a category, or a list of ingredients. 'query' carries the same value under the name every source of recipes publishes it in. |
| notes | Yes | What qualifies this answer: what its total counts, what it left out, and where the site answered from an address other than the one asked for. Read these before quoting a figure. |
| query | Yes | What was asked for, under the name a search publishes it in. |
| title | Yes | The site's own heading for the listing. |
| folded | Yes | Rows naming a recipe already held. A guide lists one recipe under two headings where it belongs to both; such a row is counted in 'rows_seen' and rendered once. |
| source | Yes | The site this answer was read from. Credit it when showing a row. |
| results | Yes | |
| rows_seen | Yes | Rows the site served on this page, before any were set aside. |
| topic_slug | Yes | The category page this listing was served from. Pass it to browse_recipes as 'category' to read the topic's further pages, and its total where this answer carries none. |
| single_page | Yes | True when the site serves this listing on one page and offers no further one. |
| result_count | Yes | Rows rendered here. |
| total_available | Yes | Recipes the site says this listing holds. Null when it published no figure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint, openWorldHint, and idempotentHint annotations, it discloses non-obvious behaviors: the site counts all matches but serves only one page, the rest cannot be reached, and an over-long ingredient list is refused rather than silently truncated. This is exactly the kind of behavioral context annotations do not capture.
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 with the purpose first, then instructions, then boundary behaviors. Every sentence earns its place and there is no filler or repetition of annotation data.
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?
Given the rich annotations and output schema, the description covers everything an agent needs to invoke it correctly: ingredient count, language, refusal behavior, and pagination limitations. The only minor gap is not explicitly routing to sibling search_recipes, but the ingredient-based purpose makes that choice obvious.
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 input schema already has 100% coverage, including the French requirement, one-to-five item bounds, and per-string length limits. The description adds helpful cook-friendly examples, but it largely restates the schema rather than adding deeper semantic meaning, so the baseline 3 is appropriate.
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 pair ('Find Ptitchef recipes') and narrows the scope to ingredients a cook already has, which distinguishes it from sibling search_recipes, browse_recipes, and list_categories. It also clarifies the input language and gives examples, making the tool's identity 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?
It gives actionable usage instructions: one to five ingredients, in French, using natural cook phrasing with examples. It doesn't explicitly say when not to use this tool or name an alternative, so it stops short of a 5, but the context is clear enough for an agent to select it appropriately.
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
Search recipes on Ptitchef by dish or ingredient. The site answers in one of two ways and the answer says which: it either sends the search to a category page of its own, whose total counts what that category holds, or it answers on its own terms on a single page whose total is the number of rows served. When a category answered, 'topic_slug' names it and browse_recipes reads its further pages. Some topics come back as a guide the site wrote instead, grouped under headings of its own and carrying no total; browse_recipes on the same 'topic_slug' reads their full listing. A search the site matched nothing for comes back with no row and a total of zero, which is an absence the site stated.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Rows to render, 20 by default. 'rows_seen' states what the page served. | |
| query | Yes | A dish or an ingredient, in French, as a reader of the site would type it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | The address the listing was read from. |
| kind | Yes | How the listing came to be, which decides what its total counts. 'topic' means the site answered a search from a page of its own; 'free_text' means it answered on its own terms. |
| page | Yes | The page that was read, which is the one the site served. |
| asked | Yes | What was asked for: a search, a category, or a list of ingredients. 'query' carries the same value under the name every source of recipes publishes it in. |
| notes | Yes | What qualifies this answer: what its total counts, what it left out, and where the site answered from an address other than the one asked for. Read these before quoting a figure. |
| query | Yes | What was asked for, under the name a search publishes it in. |
| title | Yes | The site's own heading for the listing. |
| folded | Yes | Rows naming a recipe already held. A guide lists one recipe under two headings where it belongs to both; such a row is counted in 'rows_seen' and rendered once. |
| source | Yes | The site this answer was read from. Credit it when showing a row. |
| results | Yes | |
| rows_seen | Yes | Rows the site served on this page, before any were set aside. |
| topic_slug | Yes | The category page this listing was served from. Pass it to browse_recipes as 'category' to read the topic's further pages, and its total where this answer carries none. |
| single_page | Yes | True when the site serves this listing on one page and offers no further one. |
| result_count | Yes | Rows rendered here. |
| total_available | Yes | Recipes the site says this listing holds. Null when it published no figure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses a wealth of behavioral detail far beyond what annotations provide. It explains the two distinct response modes (category pages vs. single pages), the meaning of the total (category count vs. row count), the existence of topic_slug, the guide case with no total, and the zero-result case as an explicit absence. This is precisely the kind of non-obvious behavior an agent needs to know before calling the 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?
While the purpose is front-loaded in the opening sentence, the remainder is a long, winding explanation of response behavior packed into a single run-on paragraph. It lacks clear structure and could be shortened or bullet-pointed. The complexity is high, but the description is not concise; several sentences could be consolidated without losing information. This makes it harder for an agent to quickly extract the key points.
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 search tool with rich behavioral nuances, the description covers all essential aspects: response variants, total semantics, topic_slug usage, guides, and the no-result case. It also routes to browse_recipes for pagination. Since an output schema exists, the description need not explain return values, and it already explains the meaning of fields like rows_seen and total as they appear in responses. No critical missing context is apparent.
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 input schema already covers both parameters with clear descriptions (query in French, limit with default and meaning of rows_seen). The description adds no additional parameter-specific meaning, which is acceptable given 100% schema coverage. Baseline 3 is appropriate; the description does not need to repeat schema content.
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 clearly states a specific verb and resource: 'Search recipes on Ptitchef by dish or ingredient.' It also distinguishes itself from the sibling 'browse_recipes' by explaining that browse_recipes reads further pages of a category topic. This gives an agent a precise initial understanding of what the tool does and how it differs from a closely related tool.
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 provides explicit guidance on when to follow up with 'browse_recipes' (when a category answers or a guide is returned), which is a form of usage routing. However, it never mentions the alternative 'search_by_ingredients' or states when to choose this tool over it. It also does not explicitly state when NOT to use search_recipes, so the guidance is partial and relies on inference.
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.
7 tool updates
v1.0.0- First observed
browse_recipes - First observed
get_recipe - First observed
get_recipe_translations - First observed
list_categories - First observed
scale_ingredients - First observed
search_by_ingredients - First observed
search_recipes
TDQS
Scored across 7 tools
Each tool targets a distinct action—listing, searching, browsing, reading, scaling, translating—but search_recipes and search_by_ingredients overlap conceptually, and get_recipe's built-in rescaling partially duplicates scale_ingredients. The descriptions are detailed enough to separate them, though an agent could still pause between those pairs.
All tool names follow a clear snake_case verb_noun pattern: list_, search_, browse_, get_, scale_. The one longer name, search_by_ingredients, still fits predictably and does not break the convention.
Seven tools is a well-scoped set for a recipe site: discovery, browsing, retrieval, scaling, and translations are each represented without unnecessary duplication. Each tool earns its place in the workflow.
The read-side recipe workflow is fully covered: find categories, search, browse, search by ingredients, read a recipe, rescale ingredients, and access translations. There are no dead ends, and CRUD operations are not relevant to this domain.
Maintenance
Related MCP Connectors
Read-only Danish recipes, ingredients and categories from ullasopskrifter.dk: search and browse.
Recipes MCP — wraps TheMealDB API (free tier, no auth)
Canadian grocery flyer deals and recipes by item, store, postal code, cuisine, or diet. No auth.
Unofficial read-only MCP server for VeryChic hotel offers
Related MCP Servers
- FlicenseCqualityDmaintenanceEnables management of culinary recipes through web scraping from sites like Marmiton.org, recipe generation, ingredient management, and querying a MongoDB database of recipes, comments, users, and utensils.18-
- AlicenseNot gradedqualityBmaintenanceEnables querying French government public procurement notices (BOAMP) without an API key.29 npmMIT
- AlicenseAqualityBmaintenanceMCP server that searches French recipes from Marmiton, reads ingredients and steps, and rescales quantities to any number of servings without requiring an API key.3136 npm1MIT
- AlicenseAqualityAmaintenanceEnables read-only recipe search and filtering on BBC Good Food by exposing available filter axes with counts, requiring no API key.4114 npmMIT