关于 plan-to-eat
plan-to-eat 是用于管理 Plan to Eat 账户的 MCP 服务、命令行工具和 Node 客户端,适合 meal planning 用户及烹饪类 Agent。它可读写食谱、日程、剩菜、冷冻库存和购物清单。
主要功能
- 01食谱与食材增删改查
- 02管理用餐计划条目
- 03编辑购物清单
- 04追踪剩菜与冷冻份数
- 05命令行工具与 Node 客户端
适用场景
- 01保存并整理导入的食谱
- 02安排餐食并调整份数
- 03根据计划更新购物清单
- 04记录冷冻份数与剩菜
MCP 相关
向 MCP 客户端提供 36 个工具,用于读写食谱、计划条目、购物清单和冷冻记录。通过 stdio 连接,并处理账户登录及会话恢复。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y plan-to-eat-mcpPLAN_TO_EAT_USERNAMEPlan to Eat login emailPLAN_TO_EAT_PASSWORD密钥Plan to Eat passwordPLAN_TO_EAT_SESSION_FILEWhere the cookie session is cached. Set to "" to disable caching.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
36收录的工具列表 · 更新于 2 周前
此工具无需参数。
详细介绍
🍽️ plan-to-eat-mcp
别再手动输入食谱,直接说给它听。 通过 Model Context Protocol,让你最喜欢的大模型访问你的 Plan to Eat 食谱库、规划器 和购物清单。
一款即插即用的 MCP 服务、一个命令行工具,以及一个独立的 Node 客户端,可让 Claude、 ChatGPT、任何支持 MCP 的助手,或你自己的 Shell 完全读写你的 Plan to Eat 账户。
You: "Save the Bon Appétit miso pasta from this URL and tag it weeknight."
LLM: ✓ created recipe #48,872,094 — 7 ingredients, 25 min, tagged weeknight.
You: "Plan dinner around it Tuesday and add the missing pantry items to my
shopping list."
LLM: ✓ event created 2026-05-05 / dinner / 4 servings.
✓ shopping list now reflects miso, mirin, and dashi.
……或者,如果你不想跟任何东西交谈:
$ plan-to-eat get-planner-week 2026-05-04
start_date 2026-05-04
end_date 2026-05-10
ID DATE SECTION KIND RECIPE_ID RECIPE_TITLE DESCRIPTION SERVINGS
──────── ────────── ───────── ────────── ───────── ────────────────── ───────────────────── ────────
67698872 2026-05-05 breakfast recipe 17314561 Breakfast Sandwich 8
67483177 2026-05-05 dinner ingredient Asparagus (in season) 0
67710784 2026-05-06 dinner note Cucumber salad 0
3 rows
就是这样。无需重新输入食谱,无需把 URL 复制粘贴到手机应用。只需 开口说。
❤️ 为什么选择 Plan to Eat?
如果你还没在用,Plan to Eat 确实是我用过的最好的膳食规划应用:
- 随处剪藏食谱的导入器,在真实的美食博客上也确实好用。
- 拖放式每周规划器,会自动将食材汇总到购物清单中,并智能处理单位和储藏室去重。
- 永远属于你——你的食谱库可移植、可导出,不会被算法挟持。
- 适合家庭使用——可在应用内与朋友分享食谱和菜单。
- 14 天免费试用,无需信用卡。
👉 通过我的推荐链接注册 — 你可以获得试用资格,我会收到一份小小的感谢。双赢。
✨ 它能为你做什么
- 🤖 开箱即用的 MCP 服务——将 Claude Desktop、Claude Code、OpenClaw 或任何兼容 MCP 的宿主连接到它,即可开始与食谱库对话。
- ⌨️ 使用同一套工具的命令行工具——每个 MCP 工具也都是
plan-to-eat子命令,可为用户显示表格,也可通过--json供脚本使用。同一个注册表 为两种接口提供支持,因此两者不会出现偏差。 - 🔐 自动身份验证与自动恢复——只需设置一次凭据,服务便会处理登录,将 Cookie 会话缓存到磁盘,并在 Plan to Eat 使会话失效时静默重新验证。
- 🧰 36 个工具,涵盖所有重要操作——完整的食谱 CRUD、完整的膳食规划器 CRUD(添加 / 移动 / 复制 / 删除食谱、备注和 食材条目)、重新排列时段中的事件、将剩菜作为一等工作流处理、跟踪冷冻食品、浏览课程、菜系和标签,以及统计队列中的项目数量。
- 🗓️ 真正掌控规划器——查看一周的计划并预先关联食谱标题、按日期安排食谱、附加准备备注、通过一次工具调用重新安排、更改份数、复制、查找重复项,以及重新排列同一时段中的事件。
- 🛒 真正实用的购物清单——读取清单及每件商品所属的商店和货架,添加商品(Plan to Eat 会猜测货架,并沿用你上次选择的商店)、修改条目名称或数量、在商店之间移动商品、移除商品,以及将商品放回清单。
- ❄️ 冷冻食品跟踪——烹饪后,使用
freeze_recipe_portions标记 N 份冷冻食品;使用list_frozen_recipes查看冷冻库存;食用后消耗相应条目(软删除,保留历史记录)。 - 🍳 真正的 CRUD——包括具有正确计量单位的食材清单、做法、准备 / 烹饪时间、营养信息、评分和标签。
- 📦 精简的运行时——无需 Playwright、无头浏览器或原生模块。
只需
fetch、MCP SDK 和 Zod。不到一秒即可启动。 - 🦺 100% TypeScript——提供完整类型定义的
Recipe、Ingredient、PlannerEvent结构,以及通用的_json<T>,让工具无需猜测返回结果。 - 📚 同时也是一个库——
core/client.ts是简洁、纯 Node 的 API 客户端, 可直接用于任何脚本。 - 🧠 内置 Claude Code 技能——
.claude/skills/plan-to-eat/SKILL.md向任何 Agent 讲解常见工作流和注意事项(如 supper 与 dinner 的别名、description与title不匹配等),无需它重新摸索。
根据线上 Web 应用逆向工程得出。Plan to Eat 没有公开 API, 但桌面网站内部使用的也是这些端点。使用风险自负——这些端点可能随时发生任何变化。
🚀 快速开始
npx -y plan-to-eat-mcp # run the MCP server
npm i -g plan-to-eat-mcp # …or install both bins on PATH
需要 Node 18+(用于内置的 fetch)以及一个
Plan to Eat 账户。
该软件包提供两个可执行文件:plan-to-eat-mcp(MCP 服务)和
plan-to-eat(命令行工具)。如需通过 npx 运行命令行工具而不安装,请注意
必须显式选择该工具,因为默认可执行文件是服务:
npx -y -p plan-to-eat-mcp plan-to-eat --help
改为从克隆的仓库构建(用于开发或 Claude Code 插件)
git clone https://github.com/alex-zwingli/plan-to-eat-mcp.git
cd plan-to-eat-mcp
npm install
npm run build
构建会在 dist/ 中生成 CommonJS 文件。
配置
| 变量 | 必需 | 默认值 | 说明 |
|---|---|---|---|
PLAN_TO_EAT_USERNAME | 是 | — | Plan to Eat 登录邮箱 |
PLAN_TO_EAT_PASSWORD | 是 | — | Plan to Eat 密码 |
PLAN_TO_EAT_SESSION_FILE | 否 | ~/.plan-to-eat-session.json | Cookie 会话的缓存位置。设为 "" 可禁用缓存。 |
命令行工具也会读取工作目录中的 .env(Shell 变量优先)。MCP 服务不会读取——MCP 主机会显式传入环境变量,如下所示。
🤖 与 Agent 搭配使用
任何能够启动本地 stdio MCP 服务的主机都可以使用。该服务只需要一个命令和两个环境变量,无需其他配置——无需端口、OAuth 或守护进程。
Claude Code,简便方式:安装插件
此仓库以 Claude Code 插件的形式提供——一步即可安装 MCP 服务和两个技能:
export [email protected]
export PLAN_TO_EAT_PASSWORD=hunter2
git clone https://github.com/alex-zwingli/plan-to-eat-mcp.git
cd plan-to-eat-mcp && npm install && npm run build
claude plugin marketplace add "$(pwd)"
claude plugin install plan-to-eat@plan-to-eat
安装后将包含:
| 组件 | 说明 |
|---|---|
MCP 服务 plan-to-eat | 全部 36 个工具 |
技能 plan-to-eat | 如何更好地使用 MCP 工具——工作流和注意事项 |
技能 plan-to-eat-cli | 同上,供操作命令行工具的 Agent 使用 |
使用 claude plugin details plan-to-eat@plan-to-eat 和 claude mcp list 确认。服务会从启动 Claude Code 时的环境中读取 PLAN_TO_EAT_USERNAME / PLAN_TO_EAT_PASSWORD,因此请在 Shell 配置文件中导出这些变量,而不要将其提交到任何地方。
Claude Code,手动配置
claude mcp add plan-to-eat \
--env [email protected] \
--env PLAN_TO_EAT_PASSWORD=hunter2 \
-- npx -y plan-to-eat-mcp
添加 --scope user,即可在所有项目中使用,而不仅限于当前项目。使用 claude mcp list 检查连接状态,或在会话中输入 /mcp。
Claude Desktop
编辑 claude_desktop_config.json——Settings → Developer → Edit Config,或者:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"plan-to-eat": {
"command": "npx",
"args": ["-y", "plan-to-eat-mcp"],
"env": {
"PLAN_TO_EAT_USERNAME": "[email protected]",
"PLAN_TO_EAT_PASSWORD": "hunter2"
}
}
}
}
重启 Claude Desktop,就可以开始烹饪了。
其他 MCP 主机
Cursor、Windsurf、Zed、Cline、Continue、OpenClaw、VS Code 的 MCP 支持以及自定义 SDK 客户端,都只需要相同的三项配置。请将它们指向:
| 字段 | 值 |
|---|---|
| 传输方式 | stdio |
| 命令 | npx |
| 参数 | ["-y", "plan-to-eat-mcp"] |
| 环境变量 | PLAN_TO_EAT_USERNAME、PLAN_TO_EAT_PASSWORD |
大多数主机使用与上文 Claude Desktop 相同的 mcpServers JSON 配置块——通常位于 .cursor/mcp.json、.vscode/mcp.json,或主机的设置界面中。
如果你进行了全局安装(npm i -g plan-to-eat-mcp),请将 plan-to-eat-mcp 可执行文件用作命令,并完全省略参数。如果你从克隆的仓库构建,命令为 node,参数为
["/absolute/path/to/plan-to-eat-mcp/dist/mcp/server.js"]。
绝对路径很重要,尤其是从克隆的仓库运行时。MCP 主机不会从你的项目目录启动服务,因此相对路径会解析失败。上述
npx命令则完全避免了这个问题。
验证是否正常运行
[email protected] PLAN_TO_EAT_PASSWORD=hunter2 npx -y plan-to-eat-mcp
你应该会在 stderr 中看到 [plan-to-eat] mcp server ready on stdio (36 tools)。这表示服务正在等待客户端——按 Ctrl-C 退出。如果看到的是凭据错误,请先修复,再配置主机;否则出错时会更难发现。
教会你的 Agent 使用工作流
.claude/skills/ 中附带了两个技能,涵盖常见流程和容易出错的地方(supper 与 dinner 的别名、笔记条目中 description 与 title 不匹配,以及安排日程前检查重复项):
plan-to-eat— 供调用 MCP 工具的 Agent 使用。plan-to-eat-cli— 供有 shell 但没有 MCP 服务的 Agent 使用。具备相同的 30 项功能,通过子命令调用,并提供--json以便解析。
上文的插件安装会注册这两个技能。使用其他宿主的 Agent 可以将它们作为普通上下文读取——将文件提供给它们,或把其中一个粘贴到系统提示词中。
也可以通过 skills.sh CLI 将技能单独安装到 18 种以上的 Agent 中:
npx skills add alex-zwingli/plan-to-eat-mcp
这会将两个 SKILL.md 文件复制到 .agents/skills/,并为 Claude Code、Cursor、Codex、Copilot、Gemini CLI 等创建符号链接。添加 --skill plan-to-eat-cli 可只安装一个。请注意,这安装的是技能,而不是服务——每个技能的设置部分都会引导 Agent 构建 MCP 服务或 CLI(如果尚未构建)。
对于 OpenClaw Agent,这两个技能都已发布到 ClawHub:
clawhub install plan-to-eat # MCP tools
clawhub install plan-to-eat-cli # shell / CLI
它们的 frontmatter 会在 metadata.openclaw 中声明各自所需的凭据和二进制文件,因此 ClawHub 可以在安装时检查你的环境。
⌨️ 在终端中使用
每个 MCP 工具也都是一个子命令。下划线会转换为短横线;两种写法都有效。
npm i -g plan-to-eat-mcp
plan-to-eat --help
也可以不安装直接使用——注意 -p,因为软件包的默认可执行文件是 MCP 服务,而不是 CLI:
npx -y -p plan-to-eat-mcp plan-to-eat --help
$ plan-to-eat list-frozen-recipes
ID RECIPE_ID COUNT SERVINGS FROZEN_ON
────── ───────── ───── ──────── ──────────
227854 44676380 6 1.0 2025-05-04
227908 17314561 3 1.0 2025-05-05
2 rows
$ plan-to-eat add-planner-note "Defrost chicken" 2026-05-05 dinner
id 67710999
date 2026-05-05
section dinner
$ plan-to-eat get-counts --json | jq .frozen
10
- 位置参数或标志参数 —
get-recipe 123和get-recipe --id 123等效。<command> --help会列出哪些参数可以按位置传入。 --json会输出原始数据,而不是表格,便于通过管道传给jq。- 数组可重复使用标志参数(
--event_ids 11 --event_ids 22),也可传入 JSON(--event_ids '[11,22]')。对象参数需使用 JSON:--ingredients '{"title":"bread","amount":"2"}'。 - 验证使用与 MCP 服务相同的 Zod schema,因此无效的枚举值或格式错误的日期在两种调用方式下都会以相同方式报错。
🧰 36 个工具
每个工具既是 MCP 工具,也是一个 CLI 子命令——add_planner_recipe 工具在 shell 中对应
plan-to-eat add-planner-recipe。完整参考文档包含输入架构和返回格式:docs/TOOLS.md。
食谱
| 工具 | 功能 |
|---|---|
list_recipes | 列出你的全部食谱,可按标题关键词(search)、course 或 owned_only 筛选。返回简要条目(id、标题、菜品类别、标签等;使用 full 可查看所有字段)——不含食材。 |
get_recipe | 获取单个食谱,包含做法、食材、标签、准备备注和评论。 |
create_recipe | 创建食谱。仅 title 为必填项。 |
update_recipe | 更新任意字段。 |
delete_recipe | 按 id 删除。 |
计划表 — 读取
| 工具 | 功能 |
|---|---|
list_planner_events | 列出所有计划表条目,不按日期筛选。 |
get_planner_week | 获取指定日期范围内的事件,并预先关联 recipe_title。end_date 默认为 start_date + 6 days。 |
计划表 — 写入
| 工具 | 功能 |
|---|---|
add_planner_recipe | 在指定日期和时段安排食谱。 |
add_planner_ingredient | 为餐次添加自由格式的食材(“2 lbs ground beef”)。 |
add_planner_note | 为餐次添加自由格式的备注(“Defrost chicken”)。 |
add_leftover_meal | 安排此前已计划食谱事件的剩菜(通过 plan_leftover 复制,可选是否移动)。 |
move_planner_event | 将任意计划表事件改到新的日期或时段。 |
reorder_planner_events | 调整一个时段内事件的顺序(按所需顺序传入 id)。 |
update_planner_entry_text | 编辑备注或食材条目的文本。 |
set_planner_servings | 更改食谱事件的份数。 |
duplicate_planner_event | 复制任意事件。可选 plan_leftover。 |
delete_planner_event | 按 id 删除。 |
find_planned_dates | 查找指定日期范围内某个食谱的计划表事件。可用于检查重复项。 |
冷冻柜
| 工具 | 功能 |
|---|---|
list_frozen_recipes | 查看当前冷冻柜中的食谱。使用 {include_consumed: true} 也可查看历史记录。 |
freeze_recipe_portions | 将已烹饪食谱的 N 份标记为已冷冻,并关联到其来源的计划表事件。 |
delete_frozen_recipe | 将冷冻条目标记为已食用(软删除:API 将数量设为零,但保留该行)。 |
购物清单
清单项通过其 item_ids 数组定位,而不是单个 id——Plan to Eat 会将重复食材合并为一行,并保留其所有底层行 id。
| 工具 | 功能 |
|---|---|
get_shopping_list | 获取清单;每行包含所属商店(store_title)、所在货架,以及将其加入清单的食谱。 |
add_shopping_list_items | 添加清单项。仅 title 为必填项;系统会猜测货架,商店则默认为上次为该商品使用的商店。 |
update_shopping_list_items | 修改条目名称或数量,或将任意数量的条目移至其他商店或货架。 |
remove_shopping_list_items | 从清单中移除条目(软删除)。 |
restore_shopping_list_items | 将已移除的条目恢复到清单中。 |
查找表和其他功能
| 工具 | 功能 |
|---|---|
list_courses / list_cuisines / list_main_ingredients / list_tags | 查找表。 |
list_stores / list_grocery_categories | 查看你的商店和食品杂货货架——store_id 和 category_id 需要使用这里的 id。 |
list_menus | 已保存的菜单。 |
list_friends | 好友列表。 |
get_counts | 从食谱库小组件获取 { friends, queued, frozen }。 |
update_planner_options | 设置计划表显示偏好(时区、每周起始日、营养信息列)。很少需要使用。 |
📚 将客户端用作库
import { PlanToEat, type Recipe } from 'plan-to-eat-mcp';
const pte = new PlanToEat();
await pte.login(process.env.PLAN_TO_EAT_USERNAME!, process.env.PLAN_TO_EAT_PASSWORD!);
// Or restore: pte.importSession(JSON.parse(fs.readFileSync('session.json', 'utf8')));
const recipes = await pte.listRecipes(); // every active recipe
const [dumplings] = await pte.listRecipes({ search: 'pork chive' });
const detail: Recipe = await pte.getRecipe(dumplings.id); // ingredients + directions
const created = await pte.createRecipe({
title: 'Grilled cheese',
servings: 1,
directions: 'Butter bread. Cheese. Pan. Flip.',
ingredients: [
{ title: 'bread', amount: '2', unit: 'slice', position: 1 },
{ title: 'cheese', amount: '1', unit: 'slice', position: 2 },
],
tag_titles: 'easy,lunch',
});
await pte.updateRecipe(created.id, { rating: 5 });
await pte.deleteRecipe(created.id);
客户端会在首次登录时在内部保存凭据,以便在缓存的 cookie 于会话期间过期时自动重新进行身份验证。
工具注册表也已导出,你可以基于相同的 36 项功能构建自己的适配器:
import { toolsByName, createSession } from 'plan-to-eat-mcp';
const { pte, ensure } = createSession();
await ensure();
const getRecipe = toolsByName.get('get_recipe')!;
console.log(getRecipe.description); // same text the MCP host sees
const recipe = await getRecipe.run(pte, { id: 123 });
🧪 API 参考(可用部分)
所有路径均位于 https://app.plantoeat.com 下。
JSON 端点(/api/v1/*)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/v1/recipes/lite_plus | 整本食谱集以一个轻量列表数组的形式返回(标题、课程/菜系/主要食材标题、标签、标记;不含食材)。Web 应用的食谱网格使用此接口。包含未激活/已移除/已隐藏的条目——请按 active、remove、hidden 过滤。忽略分页参数,但无需分页。Web 应用使用 ?ids[]=1&ids[]=2 刷新指定卡片。 |
| GET | /api/v1/recipes | 请勿用于列表查询。 仅返回按 ID 排序最早的 500 个食谱,并内嵌食材。已尝试的所有分页/排序参数均会被忽略:page、per_page、offset、limit、start、after_id、page[number]、sort、order、q、search。/api/v1/recipes/search、/api/v1/recipes/count 和 /api/v2/recipes 均返回 404;/recipes.json 返回 406。 |
| GET | /api/v1/recipes/:id | 单个食谱,包含 directions、ingredients、tags、prep_notes、comments。 |
| POST | /api/v1/recipes | 创建。请求体:{ "recipe": {...} }。返回 201 + 完整食谱。 |
| PUT | /api/v1/recipes/:id | 更新。请求体格式相同。 |
| DELETE | /api/v1/recipes/:id | 删除。返回已删除的食谱。 |
| GET | /api/v1/courses、/cuisines、/main_ingredients、/tags | 查找表。 |
| GET | /api/v1/events | 规划条目(日历)。返回整个日历——请在客户端按日期过滤。 |
| GET | /api/v1/menus | 已保存的菜单。 |
| GET | /api/v1/shopping_list | 仅同步元数据(updated_items、last_sync_time)——不包含清单。 |
| GET | /api/v1/shopping_list/items | 购物清单本身,每个合并后的条目占一行。 |
| GET | /api/v1/stores | 杂货店。 |
| GET | /api/v1/grocery_categories | 杂货分类。 |
| GET | /api/v1/friends | 好友。 |
| GET | /api/v1/frozen_recipes | 冷冻食谱:[{id, recipe_id, count, servings, frozen_on}]。 |
| DELETE | /api/v1/frozen_recipes/:id | 软删除(将 count 设为 0;条目仍保留)。返回更新后的条目。 |
| GET | /recipes/counts/ | { friends, queued, frozen }。(注意:不在 /api/v1 下。) |
规划写入端点(/planner/*)
风格不同:请求体采用表单编码,响应为 text/javascript(空内容)。服务器会修改状态,UI 会单独重新获取数据。必需请求头:X-CSRF-Token、X-Requested-With: XMLHttpRequest、Accept: text/javascript。由于响应体为空,客户端通过比较 /api/v1/events 前后的差异来获取新事件 ID。
| 方法 | 路径 | 请求体 |
|---|---|---|
| POST | /planner/create | rid=<recipeId>&date=YYYY-MM-DD§ion=...(食谱),或 date=...§ion=...&eventType=note|ingredient&title=<text> |
| POST | /planner/create/ | rid=<id>&frozen_id=&date=...§ion=...(冷冻食谱变体——注意末尾的斜杠) |
| POST | /planner/update | eventid=<id>&date=...§ion=...&readonly=false(移动/重新安排) |
| POST | /planner/update/<id> | description=<text>(编辑备注/食材文本) |
| POST | /planner/update_serving | event=<id>&serving=<n> |
| POST | /planner/duplicate | id=<id>&plan_leftover=true|false&readonly=false |
| POST | /planner/update_order | ids=e<id1>,e<id2> — 对一个分区内的事件重新排序 |
| POST | /planner/destroy | id=<id>&readonly=false |
| POST | /planner/update_planner_options | Rails 嵌套键:user[time_zone]=...&calendar_settings[show_calories]=1&... |
| POST | /frozen_recipes | id=<recipe_id>&eid=<event_id>&count=<n>&servings=<per-portion> — 冷冻 N 份 |
| GET | /planner/search_dates | 返回渲染后的 HTML,不是 JSON——客户端不会使用。我们会改为过滤 /api/v1/events。 |
section 的取值为 breakfast、lunch、dinner、snacks。请注意,服务器可能会根据用户的账户偏好,将 dinner 规范化为 supper;读取时会返回规范名称。
身份验证
基于 Cookie。客户端支持两种流程:
- 登录。 使用
login[email]和login[password]向POST /login发送请求,并附上从GET /login页面 meta 标签中获取的authenticity_token。服务器返回 302 并设置 Cookie。 - 复用 Cookie。 “记住我”对应的
ptermid2(用户 ID)和ptermxt2(长期有效的令牌)单独就足够使用——保存这两个值,在它们失效前无需重新登录。
写入请求需要 X-CSRF-Token 标头。客户端会按需从 /recipes 页面上的 <meta name="csrf-token"> 标签中获取该值。
不支持对 /api/v1/... 使用 HTTP Basic 身份验证(会返回 401)。
食谱负载结构
单个食谱的响应包含 65 个字段。POST/PUT 请求中可写入的字段包括:
title、description、source、url、servings、yield、scaling、
prep_time、cook_time、total_time(分钟)、
course_id、cuisine_id、main_ingredient_id、tag_titles(逗号分隔的列表)、
directions(自由文本)、private、draft、rating、
营养信息字符串(calories、sodium 等)以及食材。
食材使用 Rails 嵌套属性——实际传输字段为
recipe_ingredients_attributes,而不是 ingredients。客户端以及
create_recipe / update_recipe 工具接受更易用的名称
ingredients,并会进行转换。每个条目如下:
{ "title": "water", "amount": "1", "unit": "cup", "note": "", "position": 1 }
更新时如需删除已有食材,请包含其 id 和
"_destroy": true。服务器会补全 amount_float、metric_amount、
metric_unit 和 similar_titles。
📁 目录结构
一个软件包,三层结构。逻辑位于 core/;MCP 服务和
CLI 是基于同一注册表构建的轻量适配器。
src/
core/
client.ts API client — no MCP, no CLI, no I/O beyond fetch
tools.ts the tool registry: name, description, Zod shape, handler
session.ts credentials + cookie-cache bootstrap, shared by both adapters
version.ts version read from package.json at runtime
mcp/server.ts registry -> MCP tools (stdio transport)
cli/
main.ts registry -> subcommands, help, dispatch
args.ts argv -> Zod-validated arguments
render.ts results -> tables (or raw JSON under --json)
scripts/ smoke tests and the docs coverage check
tests/ offline unit tests (fetch is stubbed)
index.ts public entrypoint for library consumers
server.ts back-compat shim, see below
添加工具只需在 src/core/tools.ts 中添加一条记录。 它会同时出现在
MCP 服务和 CLI 中,并使用相同的名称、架构和描述——二者不会出现偏差。
其他值得了解的文件:
docs/TOOLS.md— 各工具的参考文档,包含输入/输出结构和注意事项。 手动编写;如果文档与注册表中工具列表不一致,npm run check:docs会失败。.claude/skills/plan-to-eat/SKILL.md— 如何有效使用 MCP 工具。.claude/skills/plan-to-eat-cli/SKILL.md— CLI 的使用方法。.claude-plugin/— Claude Code 插件和市场清单。.mcp.json— 插件的 MCP 服务声明。dist/— 由npm run build生成。
从 ≤0.4 版本升级? 服务入口从
dist/server.js移至dist/mcp/server.js。旧路径仍可使用——它是一个会加载新入口的垫片——因此现有主机配置和部署仍可运行。新配置应使用新路径或plan-to-eat-mcp可执行文件。
逆向工程期间使用了 Playwright;为未来可能开展的 API 探索工作,仍将其作为开发依赖保留。运行时仅依赖 fetch、MCP SDK 和 Zod。
脚本
| 命令 | 功能 |
|---|---|
npm run build | 将 src/**/*.ts 编译到 dist/。 |
npm run watch | 同上,以监听模式运行。 |
npm start | 运行编译后的 MCP 服务(dist/mcp/server.js)。 |
npm run cli -- <command> | 运行 CLI,无需全局链接。 |
npm run verify | 针对你的账户对客户端进行端到端冒烟测试(食谱)。 |
npm run verify:planner | 对规划器写入端点进行冒烟测试(在 6 个月后的某个日期创建并清理测试事件)。 |
npm test | 对 MCP 服务进行端到端冒烟测试(启动服务并调用工具)。 |
npm run check:docs | 检查 docs/TOOLS.md 是否恰好涵盖所有已注册工具。 |
npm run test:unit | 离线单元测试,使用存根替代 fetch。不会触及任何内容;CI 会运行这些测试。 |
npm run clean | 删除 dist/。 |
verify* 和 test 脚本会访问你的真实账户(test:unit 不会)。它们会创建并删除各自的测试数据,但并非试运行——详情请参阅
CONTRIBUTING.md。
🤝 贡献
欢迎提交错误报告、新端点和上游破坏性变更的修复——请参阅 CONTRIBUTING.md。先说明一点:测试脚本会使用一个真实的 Plan to Eat 账户,并创建真实数据 (之后会清理这些数据)。请使用你自己的账户。
🙏 支持 Plan to Eat
这个项目的存在完全是因为 Plan to Eat 很棒。如果你觉得这个项目有用,最好的支持方式是 通过我的推荐链接试用 Plan to Eat。 免费试用 14 天,无需银行卡。
许可证
MIT——请参阅 LICENSE。你想怎么用都行;只是如果 Plan to Eat 发布了破坏性变更,别怪我。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。