关于 mcp-recipes
mcp-recipes 是一款 MCP 服务,可搜索和读取 6 个法语、英语及西班牙语食谱网站的内容。它还支持比较不同版本并按份数调整食材用量,适合查找和改编食谱。
主要功能
- 01同时搜索 6 个食谱网站
- 02以统一格式读取食谱
- 03比较不同来源的菜谱
- 04调整食材用量和份数
适用场景
- 01跨多个网站查找食谱
- 02比较法语和英语版本
- 03按就餐人数调整用量
MCP 相关
向 MCP 客户端提供 search_recipes、get_recipe、compare_recipes 和 scale_ingredients 工具。搜索和读取食谱时会访问 6 个食谱网站。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
4收录的工具列表 · 更新于 今天
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| query | string | 是 | 用来源发布内容所使用的任意语言输入菜品或食材。 |
| fan_out | boolean | 否 | 是否可以将问题改写为较短的表达并一并发送。开启此项,因为这些索引会按收到的词语进行匹配:若语料库中包含多条菜品相关内容的句子形式问题,可能会返回空结果。关闭此项则只发送输入的原始词语;此时 `per_source` 会列出未发送的表达。 |
| sources | array | 否 | 要查询的来源,按 id 指定。省略时会查询所有来源,这正是此工具的用途。id 即 `per_source` 报告的那些 id。 |
| limit_per_source | integer | 否 | 从每个来源获取的行数,避免某个来源占满整个列表。 |
详细介绍
mcp-recipes
食谱散落在许多网站上,而且每个网站的写法都不一样:法国烹饪网站用法语发布食谱,有自己的计量方式,也有自己对一份食谱分量的定义;英文维基食谱则会列出器具,并使用前者没有字段可记录的文字说明。向其中一个网站提问,得到的答案也只来自其中一个网站。
此服务可读取六个网站。其中三个以法语发布内容:Marmiton、Ptitchef 和 Supertoinette;两个以英语发布内容:Wikibooks Cookbook 和 BBC Good Food;还有一个以西班牙语发布内容:Pequerecetas。你可以用一个问题搜索所有网站,以统一格式读取任一网站上的食谱,把同一道菜的多个版本并排比较,还可以按比例调整任意食材清单。无需 API 密钥或账号。
安装
一键安装
Claude Code
claude mcp add recipes -- npx -y mcp-recipes
Claude Desktop、Cursor 以及任何使用标准配置格式的客户端
{
"mcpServers": {
"recipes": {
"command": "npx",
"args": ["-y", "mcp-recipes"]
}
}
}
需要 Node 24 或更高版本,无需设置环境变量。
使用 Docker
{
"mcpServers": {
"recipes": {
"command": "docker",
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-recipes:4.0.0"]
}
}
}
-i 会保持 stdin 打开,协议通过它传输;省略 -t 是因为 TTY 会改写数据流。容器需要通过 HTTPS 访问 www.marmiton.org、api.wikimedia.org、www.ptitchef.com、www.bbcgoodfood.com、www.supertoinette.com 和 www.pequerecetas.com,除此之外不需要任何东西:无需卷、端口或凭据。
使用 Bundle,无需 npm
从最新版本下载 mcp-recipes-4.0.0.mcpb 并打开。支持 MCP bundles 的客户端会自动安装,无需 npm,也无需编辑配置文件。该 bundle 已包含所有依赖,因此安装时不会获取任何内容。
你可以提出的请求
- “帮我找各种来源的培根蛋面食谱。”
- “比较这道菜的法语版和英语版。”
- “为 8 个人读一下第二个食谱。”
- “它们当中哪一个用了奶油?”
- “把我笔记本里的这份清单按 1.5 倍调整。”
常规流程是先搜索,再读取:每一行都带有一个标明来源的 id,而 get_recipe 会使用它。
来源
| 来源 | 网站 | 语言 |
|---|---|---|
marmiton | www.marmiton.org | 法语 |
cookbook | Wikibooks Cookbook | 英语 |
ptitchef | www.ptitchef.com | 法语 |
goodfood | www.bbcgoodfood.com | 英语 |
supertoinette | www.supertoinette.com | 法语 |
pequerecetas | www.pequerecetas.com | 西班牙语 |
每一行的 id 都标明其来源,因此从某个回答中读到的标识符会指回正确的网站。不同来源的数量不会相加;来源若读取失败,会报告为失败,而不会报告为没有找到结果。
每个网站都有自己的访问节奏:其中两个网站要求请求间隔 3 秒,而为所有网站设置的间隔只会让本服务比要求最慢的网站更加耐心。
其中两个网站在食谱所在的地址发布的并不是食谱。Wikibooks Cookbook 会将有关食材的页面与使用这些食材的食谱放在一起,而 Pequerecetas 会发布汇集多种食谱的文章。搜索结果会说明这一点,get_recipe 也会说明它从页面中读取到了什么。
工具
| 工具 | 功能 |
|---|---|
search_recipes | 用一个问题搜索所有来源。 |
get_recipe | 以统一格式读取任意来源中的一道食谱。 |
compare_recipes | 并排展示同一道菜的多个版本。 |
scale_ingredients | 按比例调整任意食材清单,不会向任何网站发送请求。 |
search_recipes
用一个问题搜索所有来源。
| 参数 | 类型 | 必填 | 功能 |
|---|---|---|---|
query | string,1 到 200 个字符 | 是 | 要查找的菜肴或食材。 |
limit_per_source | integer,1 到 25,默认值为 5 | 否 | 每个来源保留的行数。 |
sources | 来源 ID 数组 | 否 | 仅查询这些来源。 |
fan_out | boolean,默认值为 true | 否 | 还会向每个来源发送根据问题生成的更简短表述。 |
返回内容:results,包含 id 的行,get_recipe 会使用这些 id;source 和 source_name 用于说明发布该行的网站;title;url;image_url;以及来源提供的 excerpt。per_source 会为每个网站提供一份报告,其中包含 status(值为 answered 或 failed)、该来源提供的 count,以及 reported_total 和 reported_total_means,后者说明该网站所报告的数量代表什么。names_the_dish 表示该网站的结果行中有多少行的标题包含菜名,占 count 的多少:搜索索引会根据收到的词语作答,因此网站可能会提供结果行,但其中没有一道是目标菜肴。order 会用文字说明列表的生成方式。
get_recipe
从任意来源读取一份食谱,并将其转换为统一格式。
| 参数 | 类型 | 必填 | 作用 |
|---|---|---|---|
id | 字符串,1 到 500 个字符 | 是 | 条目携带的标识符,例如 marmiton:44078。两个来源使用纯数字作为食谱地址,因此请在 id 中注明来源。 |
servings | 整数,1 到 500 | 否 | 将食材用量调整为此份数。 |
sections | ingredients、steps、times、nutrition、tips、equipment 数组,默认值为 ["ingredients", "steps"] | 否 | 要返回的部分。 |
max_steps | 整数,1 到 100,默认值为 20 | 否 | 返回的步骤数。 |
max_gathered | 整数,1 到 500,默认值为 30 | 否 | 对于汇集食谱的地址,返回的食谱和标题数。 |
max_step_chars | 整数,80 到 4000,默认值为 600 | 否 | 每个步骤保留的字符数。 |
返回内容: kind 表示该地址包含的内容。recipe 类型的回答包含
recipe,不包含 collection;collection 类型的回答包含 collection,
不包含 recipe,表示一篇汇集其他食谱的文章,其中包含构成文章的 headings
以及指向的 recipes,每份食谱都可通过 get_recipe 读取。
无论由哪个来源发布,食谱都会转换为统一格式:标题、地址、食材(每行都带有
scaling 和 is_equipment)、步骤,以及请求的部分。如果某个来源发布了某个字段,而另一个来源没有相应概念,则该字段会留空,而不是凭空编造。rest_minutes 表示来源单独列出的静置时间,且不会出现在此处的其他时间字段中。steps_as_one_block 表示来源将做法发布为一整段文字,而非分步内容。withheld 标明来源为订阅者保留的部分;这意味着页面上确实存在该部分,而非无法读取。scaling_summary 以四种方式统计各行,这四项相加后等于列表总行数。如果步骤在句子中途被截断,请调高 max_step_chars。
compare_recipes
并排展示同一道菜的多个版本。
| 参数 | 类型 | 必填 | 作用 |
|---|---|---|---|
dish | string,1 到 200 个字符 | 是 | 要比较的菜品。 |
servings | integer,1 到 500 | 否 | 将每个版本的份量换算为指定份数。 |
sections | ingredients、steps、times、nutrition、tips、equipment 数组,默认值为 ["ingredients"] | 否 | 每个版本要返回的部分。 |
max_steps | integer,1 到 100,默认值为 10 | 否 | 每个版本返回的步骤数。 |
max_step_chars | integer,80 到 4000,默认值为 600 | 否 | 每个步骤保留的字符数。 |
sources | 来源 ID 数组 | 否 | 仅比较这些来源。 |
返回内容: versions,每个有响应的来源对应一道食谱,所有食谱都换算为相同份数,方便对照用量;以及 differences,说明它们的差异。per_source 会像搜索结果一样报告每个网站。
scale_ingredients
换算任意配料清单,无需请求任何网站。
| 参数 | 类型 | 必填 | 作用 |
|---|---|---|---|
ingredients | 1 到 200 行的数组 | 是 | 要换算的行。 |
factor | number,最多 1000 | 二选一 | 要应用的倍数。 |
from_servings | integer,1 到 500 | 二选一 | 清单对应的份数。 |
to_servings | integer,1 到 500 | 二选一 | 目标份数。 |
language | auto、fr、en 或 es,默认值为 auto | 否 | 如何解析每一行。 |
传入 factor,或同时传入 from_servings 和 to_servings。auto 会逐行解析,因此适用于包含多种语言的清单;指定语言则会按该语言解析每一行。
返回内容: 按 get_recipe 返回格式换算后的行,每行都带有 scaling。
用量换算
用量会以合适的单位表示,因此返回的行可能使用与食谱原文不同的单位:例如,将 200 g 乘以二十后会显示为 4 kg。
配料能细分到什么程度取决于配料本身。法棍可以切成两份、三份或四份;鸡蛋则无法均分。结果介于两种可分数量之间时会进行四舍五入,换算后的食谱与原始食谱的比例可能因此略有偏差。该行会带有 rounded,并在备注中说明处理方式。
来源会用各自的语言书写用量,每一行都会按其书写语言解析。数值由本服务计算,因此展示时请说明这些数值是重新计算得出的。
答案如何说明来源情况
每个答案都会分别说明每个来源的情况。一个网站请求失败、一个网站无人查询、一个网站返回空结果,这三种情况各不相同,报告中也会分别说明。总数会与发布该总数的来源对应,并注明该来源所统计的内容:一个网站统计整个类别,另一个统计它返回的行数,还有一个根本不发布总数。
配置
所有变量都是可选的。在客户端配置的 env 块中设置它们。
| 变量 | 默认值 | 作用 |
|---|---|---|
RECIPES_USER_AGENT | 项目标识 | 向网站说明你的应用名称,并提供他人可以联系到的地址。 |
RECIPES_MIN_INTERVAL_MS | 1000 | 向同一网站发送两次请求之间的间隔,范围为 500 到 60000。 |
RECIPES_TIMEOUT_MS | 20000 | 单次请求的截止时间,范围为 1000 到 120000。 |
RECIPES_MAX_RETRIES | 3 | 发生暂时性故障后的重试次数,范围为 0 到 8。 |
RECIPES_CACHE_TTL_MS | 900000 | 答案在内存中的保留时间,范围为 0 到 86400000。 |
RECIPES_CACHE_MAX_ENTRIES | 200 | 内存中同时保留的答案数量,范围为 1 到 5000。 |
RECIPES_LOG_LEVEL | error | 日志级别:silent、error、info 或 debug,写入 stderr。 |
超出范围的值会回退为默认值,原因会写入 stderr。
错误
每种失败都带有六种代码之一和一条消息;在有帮助时,还会提供指出下一步操作的提示。
| 代码 | 发生了什么 | 该怎么做 |
|---|---|---|
not_found | 来源已响应,但没有这道菜谱。 | 使用 search_recipes 检查标识符。 |
invalid_input | 请求发出前,参数就已被拒绝。 | 阅读消息,其中会指出具体参数。 |
rate_limited | 来源要求此客户端放慢速度。 | 等待后使用相同参数再次调用。菜谱仍然存在。 |
parse_failure | 页面已加载,但缺少预期内容。 | 在问题跟踪器中报告。 |
network_error | 请求未能完成。 | 稍后重试。 |
timeout | 请求超过了截止时间。 | 调高 RECIPES_TIMEOUT_MS,或请求更少的行。 |
来源发生故障时,会按来源分别报告,而不会导致整个答案失败,因此一个无响应的网站不会掩盖其他网站的结果。
作为库使用
读取各网站内容的这一层单独发布,拥有自己的请求间隔、缓存和错误处理,且不绑定任何协议。
import { RecipesClient } from "mcp-recipes/client";
const client = new RecipesClient();
const { rows, reports } = await client.searchRecipes("carbonara", 3);
console.log(
rows.length,
reports.map((report) => report.status),
);
const { recipe } = await client.getRecipe(rows[0].id);
searchRecipes(query, limitPerSource, sources?, options?) 返回
{ rows, reports }:每个来源对应一份报告,说明它是否成功响应,以及统计的数量。因此,来源发生故障时,绝不会被误认为该来源没有内容。getRecipe(id) 返回 { recipe, cached, read },并抛出携带 6 种错误代码之一的错误。client.profiles 列出构建时注册的来源。
缩放器单独发布在 mcp-recipes/scale,可离线处理任意列表:
import { scaleIngredients } from "mcp-recipes/scale";
scaleIngredients(["200 g de harina", "4 oeufs", "1 cup milk"], { factor: 2 });
每个网站都有自己的请求间隔,这里的间隔下限同样有效。
请求间隔与署名
每个网站分别控制请求间隔,每次只发送一个请求。每个网站都有自己的最低间隔,任何配置都不能低于此值:Marmiton 和 Cookbook 为半秒,Ptitchef 和 BBC Good Food 为 1 秒,Supertoinette 和 Pequerecetas 为 3 秒。针对所有来源设置的间隔可以调长,但不能缩短。因此,同时请求所有网站时,每个网站只会收到一个请求,而不是两个。User-Agent 始终以项目标识和可供联系的地址结尾。
每条记录都包含食谱所在页面的地址,以及发布该食谱的网站名称。Cookbook 页面采用 CC BY-SA 4.0 许可发布,该许可要求基于这些页面创作的内容也以相同许可共享。Marmiton、Ptitchef、BBC Good Food、Supertoinette 和 Pequerecetas 均未在食谱页面上声明使用条款;它们的食谱属于这些网站以及撰写食谱的厨师。没有声明不代表授权,因此请注明网站,并链接到你获取食谱的页面。
BBC Good Food 为订阅用户保留的食谱会以“保留食谱”的形式返回,不包含食材和做法,但会附上页面地址。本服务不会还原该网站选择付费提供的内容。
这里不会重复展示网站发布的两项数据。难度是各网站自行定义的文字标签,没有任何网站公布统一的量表,因此无法用同一坐标轴对不同版本进行比较。费用在一个网站上是欧元价格,在另一个网站上则是其列表中的排名;如果用同一个字段同时表示两者,会让人误以为它们可以比较。
此 MCP 服务是一个非官方项目,与它读取内容的任何网站均无关联。
隐私
此服务不会收集你的任何信息,也不会向作者发送任何信息。它在你的计算机上运行,会联系 www.marmiton.org、
api.wikimedia.org、
www.ptitchef.com、www.bbcgoodfood.com、www.supertoinette.com 和
www.pequerecetas.com,除此之外不会联系其他地址;运行期间会将响应保留在内存中,
不会写入磁盘。PRIVACY.md 说明了请求包含哪些内容,以及哪些设置会改变这些内容。
开发
npm install
npm run build:fixtures
npm test
npm run check
测试使用生成的测试固件,不会发出网络请求。实时测试套件
npm run test:live 会针对每条路由发送一个请求,并于每晚直接对这些网站运行。
贡献
请通过问题跟踪器提交错误报告、问题和想法。欢迎提交拉取请求;先提出问题有助于就变更方案达成一致。请参阅 CONTRIBUTING.md。
许可证
MIT,详见 LICENSE。食谱属于发布它们的网站以及食谱作者。
mcp-recipes(法语)
食谱分布在许多网站上,每个网站的写法都不一样:法国美食网站用法语发布食谱,采用自己的计量单位,也有自己对一份的定义;而英文烹饪维基会列出器具,并使用前者没有对应字段的文字说明。向其中任何一个网站提问,得到的回答都只涉及它自己。
这个服务会读取六个网站。其中三个用法语发布食谱:Marmiton、Ptitchef 和 Supertoinette;两个用英语:Wikibooks 的 Cookbook 和 BBC Good Food;一个用西班牙语:Pequerecetas。你可以用一个问题搜索这六个网站,以统一格式读取任意网站上的食谱,将同一道菜的多个版本并排比较,还可以调整任意配料清单。无需 API 密钥,也无需账户。
安装
一键安装
Claude Code
claude mcp add recipes -- npx -y mcp-recipes
Claude Desktop、Cursor,以及所有采用标准配置格式的客户端
{
"mcpServers": {
"recipes": {
"command": "npx",
"args": ["-y", "mcp-recipes"]
}
}
}
需要 Node 24 或更高版本,无需设置环境变量。
使用 Docker
{
"mcpServers": {
"recipes": {
"command": "docker",
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-recipes:4.0.0"]
}
}
}
-i 会保持标准输入打开,它是协议的通信通道;省略 -t 是因为 TTY 会重写数据流。容器需要能够通过 HTTPS 访问以下网站:www.marmiton.org、api.wikimedia.org、www.ptitchef.com、www.bbcgoodfood.com、www.supertoinette.com 和 www.pequerecetas.com,除此之外不需要任何东西:无需卷、无需端口,也无需凭据。
Bundle,无需 npm
从最新发布版本下载 mcp-recipes-4.0.0.mcpb 并打开。支持 MCP bundle 的客户端会自动安装,无需 npm,也无需修改配置文件。bundle 包含其依赖项,因此安装时不会下载任何内容。
可以提出哪些请求
- “帮我找 carbonara 食谱,任何网站上的都可以。”
- “比较这道菜的法语版和英语版。”
- “读一下第二个版本,按八人份调整。”
- “哪个版本用了奶油?”
- “把我笔记本里这份配料清单的用量乘以 1.5。”
通常的流程是先搜索,再读取:每条结果都带有一个标识来源的 id,然后将它传给 get_recipe。
来源
| 来源 | 网站 | 语言 |
|---|---|---|
marmiton | www.marmiton.org | 法语 |
cookbook | Cookbook Wikibooks | 英语 |
ptitchef | www.ptitchef.com | 法语 |
goodfood | www.bbcgoodfood.com | 英语 |
supertoinette | www.supertoinette.com | 法语 |
pequerecetas | www.pequerecetas.com | 西班牙语 |
每一行的 id 都标明其来源,因此从响应中读取到的标识符会指向正确的网站。不同来源的数量绝不会相加,而失败的来源会报告为失败,而不是报告为没有找到任何内容。
每个网站都有自己的访问节奏:其中两个网站要求两次请求之间间隔三秒,而统一设置的延迟只能让此服务比要求最慢的网站更加耐心。
其中两个网站会在食谱所在的网址存放非食谱内容。Wikibooks Cookbook 会在食谱旁边保留有关食材的页面,而 Pequerecetas 会发布汇集多道食谱的文章。搜索结果会说明这一点,get_recipe 则会说明它从页面读取了什么。
工具
| 工具 | 功能 |
|---|---|
search_recipes | 用一个问题搜索所有来源。 |
get_recipe | 以统一格式读取任意来源的食谱。 |
compare_recipes | 并列比较同一道菜的多个版本。 |
scale_ingredients | 调整任意食材清单的用量,无需请求。 |
search_recipes
用一个问题搜索所有来源。
| 参数 | 类型 | 必填 | 功能 |
|---|---|---|---|
query | 字符串,1 到 200 个字符 | 是 | 要搜索的菜品或食材。 |
limit_per_source | 整数,1 到 25,默认值为 5 | 否 | 每个来源保留的行数。 |
sources | 来源标识符数组 | 否 | 只查询这些来源。 |
fan_out | 布尔值,默认值为 true | 否 | 也将从问题中提取的较短表述发送给每个来源。 |
返回内容: results 是包含 id 的行,get_recipe 会使用这些行;source 和 source_name 表示该行由哪个网站发布;还有 title、url、image_url,以及来源提供的 excerpt。
per_source 会按网站提供报告,其中包含 status(值为 answered 或 failed)、该网站提供的 count,以及该网站的 reported_total 和 reported_total_means,后者说明这个数字在该网站上统计的是什么。
names_the_dish 表示该网站的行中有多少行在标题里包含菜品名称,占 count 的多少:搜索索引会根据提供的词语返回结果,因此网站可能会返回一些与该菜品无关的行。order 用文字说明列表是如何生成的。
get_recipe
读取任意来源的食谱,并以统一形式返回。
| Argument | Type | Requis | Ce qu'il fait |
|---|---|---|---|
id | chaîne, 1 à 500 caractères | oui | 一行食谱的标识符,例如 marmiton:44078。两个来源使用纯数字来标识食谱:请在 id 中注明其来源。 |
servings | entier, 1 à 500 | non | 将食材用量调整为此份数。 |
sections | tableau de ingredients, steps, times, nutrition, tips, equipment, défaut ["ingredients", "steps"] | non | 要返回的部分。 |
max_gathered | entier, 1 à 500, défaut 30 | non | 对于汇集多个食谱的页面,返回的食谱和小标题数量。 |
max_steps | entier, 1 à 100, défaut 20 | non | 返回的步骤数量。 |
max_step_chars | entier, 80 à 4000, défaut 600 | non | 每个步骤保留的字符数。 |
返回内容: kind 表示该地址对应的内容。recipe 响应包含 recipe,不包含 collection;collection 响应包含 collection,不包含 recipe。它是一篇汇集其他食谱的文章,包含构成文章的 headings,以及它指向的 recipes,每个食谱都可通过 get_recipe 读取。
无论食谱由哪个来源发布,都会以所有来源通用的形式返回:标题、地址、食材(每一行均包含 scaling 和 is_equipment)、步骤,以及请求的部分。某个字段若由一个来源发布、但另一个来源没有对应概念,则会缺省,而不会凭空生成。rest_minutes 表示某个来源单独列出的静置时间,不计入此处返回的其他时间。steps_as_one_block 表示某个来源以一整段文字而非分步形式发布做法。scaling_summary 以四种方式统计各行,四项之和等于列表总行数。withheld 指明某个来源仅向订阅者开放的部分;这是页面包含、而非无法读取的部分。如果某个步骤在句子中途被截断,请增大 max_step_chars。
compare_recipes
并排展示同一道菜的多个版本。
| Argument | Type | Requis | Ce qu'il fait |
|---|---|---|---|
dish | chaîne, 1 à 200 caractères | oui | Le plat à comparer. |
servings | entier, 1 à 500 | non | Adapte chaque version à ce nombre de parts. |
sections | tableau de ingredients, steps, times, nutrition, tips, equipment, défaut ["ingredients"] | non | Les parties à rendre par version. |
max_steps | entier, 1 à 100, défaut 10 | non | Étapes à servir par version. |
max_step_chars | entier, 80 à 4000, défaut 600 | non | Caractères gardés par étape. |
sources | tableau d'ids de source | non | Ne compare que ces sources. |
En retour : versions,每个响应源对应一份食谱,并统一调整到相同份数,以便对照各版本的用量;以及 differences,列出它们的差异。per_source 会像搜索结果一样报告每个网站。
scale_ingredients
调整任意食材清单,无需向任何网站查询。
| Argument | Type | Requis | Ce qu'il fait |
|---|---|---|---|
ingredients | tableau de 1 à 200 lignes | oui | Les lignes à adapter. |
factor | nombre, jusqu'à 1000 | l'un des deux | Le multiplicateur à appliquer. |
from_servings | entier, 1 à 500 | l'un des deux | Le nombre de parts de la liste d'origine. |
to_servings | entier, 1 à 500 | l'un des deux | Le nombre de parts voulu. |
language | auto, fr, en ou es, défaut auto | non | Comment chaque ligne est lue. |
传入 factor,或同时传入 from_servings 和 to_servings。auto 会逐行识别语言,适用于包含多种语言的清单;指定一种语言则会按该语言读取所有行。
En retour : 按 get_recipe 返回的格式提供调整后的各行,每行都包含 scaling 和 is_equipment;如果某行写的是工具,则保持原样,并将 is_equipment 设为 true。scaled_count、rounded_count、unscaled_count 和 equipment_count 汇总已发送的各行。
数量的调整
数量以适用的单位表示。因此,调整后的一行可能使用与食谱不同的单位:200 g 乘以二十就是 4 kg。
食材的切分精细程度取决于其性质。法棍可以切成两份、三份或四份;鸡蛋则无法分割。因此,落在两者之间的数量会被四舍五入,调整后的食谱也就会与原始配比略有偏差。该行会标记为 rounded,并在备注中说明处理方式。
来源会用各自的语言写出数量,而每一行也会以其原本使用的语言显示。数字由此服务进行计算,因此展示这些数字时,请说明它们经过了重新计算。
关于来源的响应说明
每个响应都会分别报告每个来源的情况。某个网站请求失败、从未被查询,以及返回空结果,是三种不同的情况,报告时也会分别说明。总数会与发布该总数的来源放在一起,并说明该来源的统计口径:有的统计整个类别,有的统计其提供的行数,还有的则不发布总数。
配置
每个变量都是可选的。请将它们放在客户端配置的 env 块中。
| 变量 | 默认值 | 作用 |
|---|---|---|
RECIPES_USER_AGENT | 项目标识 | 向网站标识您的应用,并提供可联系到负责人的地址。 |
RECIPES_MIN_INTERVAL_MS | 1000 | 向同一网站发送两次请求之间的间隔,范围为 500 至 60000。 |
RECIPES_TIMEOUT_MS | 20000 | 请求超时时间,范围为 1000 至 120000。 |
RECIPES_MAX_RETRIES | 3 | 临时失败后的重试次数,范围为 0 至 8。 |
RECIPES_CACHE_TTL_MS | 900000 | 响应在内存中的保留时长,范围为 0 至 86400000。 |
RECIPES_CACHE_MAX_ENTRIES | 200 | 同时保存在内存中的响应数量,范围为 1 至 5000。 |
RECIPES_LOG_LEVEL | error | silent、error、info 或 debug,写入错误输出。 |
超出范围的值会恢复为默认值,原因会写入错误输出。
错误
每次失败都会带有六种代码之一、一条消息,以及在有帮助时提供的下一步操作建议。
| 代码 | 发生了什么 | 怎么做 |
|---|---|---|
not_found | 某个来源已响应,但没有这道菜谱。 | 使用 search_recipes 检查标识符。 |
invalid_input | 参数在发出任何请求之前就被拒绝了。 | 阅读消息,其中会指出具体参数。 |
rate_limited | 某个来源要求客户端降低请求频率。 | 等待后,使用相同参数再次调用。菜谱仍然存在。 |
parse_failure | 页面已加载,但缺少预期内容。 | 在问题跟踪页报告此问题。 |
network_error | 请求未能完成。 | 稍后重试。 |
timeout | 请求超时。 | 增大 RECIPES_TIMEOUT_MS,或减少请求的行数。 |
失败会按来源分别报告,而不会导致整个响应失败,因此,一个没有响应的网站绝不会掩盖另一个网站。
作为库使用
读取网站的层单独发布,带有自己的节奏、缓存和错误处理,不依赖任何协议。
import { RecipesClient } from "mcp-recipes/client";
const client = new RecipesClient();
const { rows, reports } = await client.searchRecipes("carbonara", 3);
console.log(
rows.length,
reports.map((report) => report.status),
);
const { recipe } = await client.getRecipe(rows[0].id);
searchRecipes(query, limitPerSource, sources?, options?) 返回 { rows, reports }:每个来源对应一份报告,说明它是否已响应以及其自身统计的数量,确保失败的来源绝不会被误认为是不包含任何内容的来源。getRecipe(id) 返回 { recipe, cached, read },并会抛出带有六种代码之一的错误。client.profiles 列出此构建所注册的来源。
扩展机制单独发布在 mcp-recipes/scale 下,可离线处理任意列表:
import { scaleIngredients } from "mcp-recipes/scale";
scaleIngredients(["200 g de harina", "4 oeufs", "1 cup milk"], { factor: 2 });
每个网站都保留自己的节奏,并且这里也同样遵守最低间隔。
频率限制与署名
每个网站单独限速,每次只发送一个请求。每个网站都有自己的最低间隔,任何配置都不能低于该间隔:Marmiton 和 Cookbook 为半秒,Ptitchef 和 BBC Good Food 为一秒,Supertoinette 和 Pequerecetas 为三秒。为所有来源设置的间隔可以延长某个网站的间隔,但不能缩短。一次查询所有网站,因此每个网站都只会收到一个请求,而不是两个。User-Agent 始终以项目身份和可联系到负责人的地址结尾。
每一行都包含食谱页面的地址和发布该食谱的网站名称。Cookbook 的页面采用 CC BY-SA 4.0 发布,该许可要求基于其内容创作的作品也以相同许可共享。Marmiton、Ptitchef、BBC Good Food、Supertoinette 和 Pequerecetas 没有在食谱页面上声明任何条件,其食谱属于这些网站及撰写食谱的厨师。没有声明条件不代表获得授权:请注明网站,并链接到食谱来源页面。
BBC Good Food 为订阅用户保留的食谱不会提供食材和做法,只会标记为保留食谱,并附上其页面地址。本服务不会还原该网站选择付费提供的内容。
此处不会保留网站发布的两个数值。难度是每个网站各自表述的一个词,没有公开的统一量表,因此不存在可用于比较两个版本的共同维度。费用在一个网站上以欧元计价,在另一个网站上则是其自有列表中的排名;用同一个字段呈现两者会让人误以为它们可以比较。
此 MCP 是一个非官方项目,与其读取的任何网站均无关联。
隐私
此服务不会收集您的任何信息,也不会向作者发送任何信息。它在您的计算机上运行,只会连接 www.marmiton.org、api.wikimedia.org、www.ptitchef.com、www.bbcgoodfood.com、www.supertoinette.com 和 www.pequerecetas.com,在运行期间将响应保存在内存中,并且不会向磁盘写入任何内容。PRIVACY.md 说明了请求会携带哪些信息,以及哪些设置会改变这些行为。
开发
npm install
npm run build:fixtures
npm test
npm run check
测试使用生成的 fixture 运行,不会发送任何请求。实时测试套件 npm run test:live 会对每个路由发送一个请求,并且每晚针对网站本身运行。
贡献
问题、疑问和想法都可以提交到问题跟踪页。欢迎提交修改建议;先创建 issue 有助于就修改方案达成一致。请参阅 CONTRIBUTING.md。
许可证
MIT,详见 LICENSE。食谱属于发布它们的网站及其作者。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。