mcpField
M
mcp-recipes

mcp-recipes

本地服务
github.com游戏娱乐0今天更新

关于 mcp-recipes

mcp-recipes 是一款 MCP 服务,可搜索和读取 6 个法语、英语及西班牙语食谱网站的内容。它还支持比较不同版本并按份数调整食材用量,适合查找和改编食谱。

主要功能

  1. 01同时搜索 6 个食谱网站
  2. 02以统一格式读取食谱
  3. 03比较不同来源的菜谱
  4. 04调整食材用量和份数

适用场景

  1. 01跨多个网站查找食谱
  2. 02比较法语和英语版本
  3. 03按就餐人数调整用量

MCP 相关

向 MCP 客户端提供 search_recipes、get_recipe、compare_recipes 和 scale_ingredients 工具。搜索和读取食谱时会访问 6 个食谱网站。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库
安装包
npmmcp-recipes4.1.0
mcpbmcp-recipes-4.1.0.mcpb4.1.0

工具

4

收录的工具列表 · 更新于 今天

参数类型必填说明
querystring是用来源发布内容所使用的任意语言输入菜品或食材。
fan_outboolean否是否可以将问题改写为较短的表达并一并发送。开启此项,因为这些索引会按收到的词语进行匹配:若语料库中包含多条菜品相关内容的句子形式问题,可能会返回空结果。关闭此项则只发送输入的原始词语;此时 `per_source` 会列出未发送的表达。
sourcesarray否要查询的来源,按 id 指定。省略时会查询所有来源,这正是此工具的用途。id 即 `per_source` 报告的那些 id。
limit_per_sourceinteger否从每个来源获取的行数,避免某个来源占满整个列表。

详细介绍

mcp-recipes

npm CI license MCP Registry Glama M8ven LobeHub 在 Cursor 中安装 在 VS Code 中安装

食谱散落在许多网站上,而且每个网站的写法都不一样:法国烹饪网站用法语发布食谱,有自己的计量方式,也有自己对一份食谱分量的定义;英文维基食谱则会列出器具,并使用前者没有字段可记录的文字说明。向其中一个网站提问,得到的答案也只来自其中一个网站。

此服务可读取六个网站。其中三个以法语发布内容:Marmiton、Ptitchef 和 Supertoinette;两个以英语发布内容:Wikibooks Cookbook 和 BBC Good Food;还有一个以西班牙语发布内容:Pequerecetas。你可以用一个问题搜索所有网站,以统一格式读取任一网站上的食谱,把同一道菜的多个版本并排比较,还可以按比例调整任意食材清单。无需 API 密钥或账号。

Version française


安装

一键安装

在 Cursor 中安装 在 VS Code 中安装

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 会使用它。

来源

来源网站语言
marmitonwww.marmiton.org法语
cookbookWikibooks Cookbook英语
ptitchefwww.ptitchef.com法语
goodfoodwww.bbcgoodfood.com英语
supertoinettewww.supertoinette.com法语
pequerecetaswww.pequerecetas.com西班牙语

每一行的 id 都标明其来源,因此从某个回答中读到的标识符会指回正确的网站。不同来源的数量不会相加;来源若读取失败,会报告为失败,而不会报告为没有找到结果。

每个网站都有自己的访问节奏:其中两个网站要求请求间隔 3 秒,而为所有网站设置的间隔只会让本服务比要求最慢的网站更加耐心。

其中两个网站在食谱所在的地址发布的并不是食谱。Wikibooks Cookbook 会将有关食材的页面与使用这些食材的食谱放在一起,而 Pequerecetas 会发布汇集多种食谱的文章。搜索结果会说明这一点,get_recipe 也会说明它从页面中读取到了什么。

工具

工具功能
search_recipes用一个问题搜索所有来源。
get_recipe以统一格式读取任意来源中的一道食谱。
compare_recipes并排展示同一道菜的多个版本。
scale_ingredients按比例调整任意食材清单,不会向任何网站发送请求。
search_recipes

用一个问题搜索所有来源。

参数类型必填功能
querystring,1 到 200 个字符是要查找的菜肴或食材。
limit_per_sourceinteger,1 到 25,默认值为 5否每个来源保留的行数。
sources来源 ID 数组否仅查询这些来源。
fan_outboolean,默认值为 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否将食材用量调整为此份数。
sectionsingredients、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

并排展示同一道菜的多个版本。

参数类型必填作用
dishstring,1 到 200 个字符是要比较的菜品。
servingsinteger,1 到 500否将每个版本的份量换算为指定份数。
sectionsingredients、steps、times、nutrition、tips、equipment 数组,默认值为 ["ingredients"]否每个版本要返回的部分。
max_stepsinteger,1 到 100,默认值为 10否每个版本返回的步骤数。
max_step_charsinteger,80 到 4000,默认值为 600否每个步骤保留的字符数。
sources来源 ID 数组否仅比较这些来源。

返回内容: versions,每个有响应的来源对应一道食谱,所有食谱都换算为相同份数,方便对照用量;以及 differences,说明它们的差异。per_source 会像搜索结果一样报告每个网站。

scale_ingredients

换算任意配料清单,无需请求任何网站。

参数类型必填作用
ingredients1 到 200 行的数组是要换算的行。
factornumber,最多 1000二选一要应用的倍数。
from_servingsinteger,1 到 500二选一清单对应的份数。
to_servingsinteger,1 到 500二选一目标份数。
languageauto、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_MS1000向同一网站发送两次请求之间的间隔,范围为 500 到 60000。
RECIPES_TIMEOUT_MS20000单次请求的截止时间,范围为 1000 到 120000。
RECIPES_MAX_RETRIES3发生暂时性故障后的重试次数,范围为 0 到 8。
RECIPES_CACHE_TTL_MS900000答案在内存中的保留时间,范围为 0 到 86400000。
RECIPES_CACHE_MAX_ENTRIES200内存中同时保留的答案数量,范围为 1 到 5000。
RECIPES_LOG_LEVELerror日志级别: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 密钥,也无需账户。

安装

一键安装

在 Cursor 中安装 在 VS Code 中安装

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。

来源

来源网站语言
marmitonwww.marmiton.org法语
cookbookCookbook Wikibooks英语
ptitchefwww.ptitchef.com法语
goodfoodwww.bbcgoodfood.com英语
supertoinettewww.supertoinette.com法语
pequerecetaswww.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

读取任意来源的食谱,并以统一形式返回。

ArgumentTypeRequisCe qu'il fait
idchaîne, 1 à 500 caractèresoui一行食谱的标识符,例如 marmiton:44078。两个来源使用纯数字来标识食谱:请在 id 中注明其来源。
servingsentier, 1 à 500non将食材用量调整为此份数。
sectionstableau de ingredients, steps, times, nutrition, tips, equipment, défaut ["ingredients", "steps"]non要返回的部分。
max_gatheredentier, 1 à 500, défaut 30non对于汇集多个食谱的页面,返回的食谱和小标题数量。
max_stepsentier, 1 à 100, défaut 20non返回的步骤数量。
max_step_charsentier, 80 à 4000, défaut 600non每个步骤保留的字符数。

返回内容: 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

并排展示同一道菜的多个版本。

ArgumentTypeRequisCe qu'il fait
dishchaîne, 1 à 200 caractèresouiLe plat à comparer.
servingsentier, 1 à 500nonAdapte chaque version à ce nombre de parts.
sectionstableau de ingredients, steps, times, nutrition, tips, equipment, défaut ["ingredients"]nonLes parties à rendre par version.
max_stepsentier, 1 à 100, défaut 10nonÉtapes à servir par version.
max_step_charsentier, 80 à 4000, défaut 600nonCaractères gardés par étape.
sourcestableau d'ids de sourcenonNe compare que ces sources.

En retour : versions,每个响应源对应一份食谱,并统一调整到相同份数,以便对照各版本的用量;以及 differences,列出它们的差异。per_source 会像搜索结果一样报告每个网站。

scale_ingredients

调整任意食材清单,无需向任何网站查询。

ArgumentTypeRequisCe qu'il fait
ingredientstableau de 1 à 200 lignesouiLes lignes à adapter.
factornombre, jusqu'à 1000l'un des deuxLe multiplicateur à appliquer.
from_servingsentier, 1 à 500l'un des deuxLe nombre de parts de la liste d'origine.
to_servingsentier, 1 à 500l'un des deuxLe nombre de parts voulu.
languageauto, fr, en ou es, défaut autononComment 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_MS1000向同一网站发送两次请求之间的间隔,范围为 500 至 60000。
RECIPES_TIMEOUT_MS20000请求超时时间,范围为 1000 至 120000。
RECIPES_MAX_RETRIES3临时失败后的重试次数,范围为 0 至 8。
RECIPES_CACHE_TTL_MS900000响应在内存中的保留时长,范围为 0 至 86400000。
RECIPES_CACHE_MAX_ENTRIES200同时保存在内存中的响应数量,范围为 1 至 5000。
RECIPES_LOG_LEVELerrorsilent、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。食谱属于发布它们的网站及其作者。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。