Plan To Eat

io.github.alex-zwingli由 GitHub 帳號 alex-zwingli 發布v0.8.0更新於 Oct 31, 2026

Unofficial Plan to Eat client: recipes, meal planner, leftovers, freezer, and shopping list.

概覽

AI 產生的概覽

非官方的 Plan to Eat 用戶端,讓助理讀寫你的食譜、膳食計畫、冷凍庫存和購物清單。

可以做什麼
  • 搜尋、檢視、建立、修改和刪除食譜,包含食材、做法、時間、評分與標籤
  • 依日期範圍檢視計畫事件,並安排、移動、複製、排序、改份數或刪除食譜、備註和食材項目
  • 管理剩菜與冷凍份數,包括列出冷凍項目和標記已食用
  • 讀取購物清單及其商店與貨架分類,並新增、改名、改數量、移動、移除或還原項目
  • 查詢菜式、菜系、主要食材、標籤、商店、貨架分類、菜單、好友和數量統計
適用情境
適合已有 Plan to Eat 帳號、希望透過助理而非網頁應用來安排一週餐食、匯入或編輯食譜、整理購物清單的使用者。
執行需求
以 stdio 在本機執行,可透過 npx 或全域 npm 安裝;需要 Node 18+ 和 Plan to Eat 帳號。需在宿主環境設定 PLAN_TO_EAT_USERNAME 與 PLAN_TO_EAT_PASSWORD,PLAN_TO_EAT_SESSION_FILE 為選用,用於指定 cookie 工作階段快取位置。需要連線至 Plan to Eat 網站的網路。
安裝前請注意
伺服器會在宿主設定中保存你的 Plan to Eat 電子郵件和密碼並代為登入,請勿寫入會提交的檔案。預設會把 cookie 工作階段快取到磁碟,可用 PLAN_TO_EAT_SESSION_FILE 關閉。相關工具會寫入、移動和刪除食譜、計畫事件與購物清單項目,誤操作會改動真實帳號資料。它是基於逆向介面的非官方用戶端,介面可能隨時變動。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Plan To Eat,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

🍽️ plan-to-eat-mcp

Stop typing recipes. Start telling them. Hand your favorite LLM the keys to your Plan to Eat recipe book, planner, and shopping list — over the Model Context Protocol.

A drop-in MCP server, a CLI, and a standalone Node client that give Claude, ChatGPT, any MCP-aware assistant, or your own shell full read/write access to your Plan to Eat account.

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.

…or, when you'd rather not talk to anything:

console
$ plan-to-eat get-planner-week 2026-05-04start_date  2026-05-04end_date    2026-05-10
ID        DATE        SECTION    KIND        RECIPE_ID  RECIPE_TITLE        DESCRIPTION            SERVINGS────────  ──────────  ─────────  ──────────  ─────────  ──────────────────  ─────────────────────  ────────67698872  2026-05-05  breakfast  recipe      17314561   Breakfast Sandwich                         867483177  2026-05-05  dinner     ingredient                                 Asparagus (in season)  067710784  2026-05-06  dinner     note                                       Cucumber salad         0
3 rows

That's it. No recipe re-typing. No copy-pasting URLs into a phone app. Just talk.


❤️ Why Plan to Eat?

If you're not already using it, Plan to Eat is genuinely the best meal-planning app I've ever used:

  • A clip-anywhere recipe importer that actually works on real-world food blogs.
  • Drag-and-drop weekly planner that automatically rolls ingredients into a shopping list, with smart units and pantry deduplication.
  • Yours forever — your recipe book is portable, exportable, and not held hostage by an algorithm.
  • Family-friendly — share recipes and menus with friends in-app.
  • 14-day free trial, no credit card needed.

👉 Sign up with my referral link — you get the trial, and I get a tiny thank-you. Win/win.


✨ What this gives you

  • 🤖 MCP server out of the box — point Claude Desktop, Claude Code, OpenClaw, or any MCP-compatible host at it and start talking to your recipe book.
  • ⌨️ A CLI over the same tools — every MCP tool is also a plan-to-eat subcommand, with tables for humans and --json for scripts. One registry feeds both surfaces, so they can't drift.
  • 🔐 Auto-auth & auto-recovery — set your credentials once, the server handles login, caches the cookie session to disk, and silently re-auths whenever Plan to Eat invalidates it.
  • 🧰 36 tools, all the verbs that matter — full recipe CRUD, full meal-planner CRUD (add / move / duplicate / delete recipes, notes, and ingredient entries), reorder events in a slot, leftovers as a first-class workflow, freezer tracking, browse courses & cuisines & tags, count what's in your queue.
  • 🗓️ Real planner control — view a week's plan with recipe titles pre-joined, schedule recipes on dates, attach prep notes, reschedule with one tool call, change servings, duplicate, search for duplicates, reorder same-slot events.
  • 🛒 A shopping list you can actually work with — read it with the store and aisle each item is filed under, add items (Plan to Eat guesses the aisle and reuses the store you last picked), retitle or re-quantify a line, move items between stores, remove them, put them back.
  • ❄️ Freezer tracking — after cooking, mark N portions as frozen with freeze_recipe_portions; check what's stashed with list_frozen_recipes; consume entries when you eat them (soft-delete, history preserved).
  • 🍳 Real CRUD — including ingredient lists with proper units, directions, prep/cook times, nutrition, ratings, and tags.
  • 📦 Tiny runtime — no Playwright, no headless browser, no native modules. Just fetch, the MCP SDK, and Zod. Boots in under a second.
  • 🦺 100% TypeScript — fully typed Recipe, Ingredient, PlannerEvent shapes plus a generic _json<T> so your tools never have to guess what comes back.
  • 📚 A library too — core/client.ts is a clean, plain-Node API client you can drop into any script.
  • 🧠 Bundled Claude Code skill — .claude/skills/plan-to-eat/SKILL.md teaches any agent the common workflows and gotchas (the supper-vs-dinner alias, the description-vs-title mismatch, etc.) so it doesn't have to rediscover them.

Reverse-engineered from the live web app. There's no public Plan to Eat API, but the desktop site uses these same endpoints internally. Use at your own risk — they could change anything at any time.


🚀 Quick start

bash
npx -y plan-to-eat-mcp          # run the MCP servernpm i -g plan-to-eat-mcp        # …or install both bins on PATH

Requires Node 18+ (for built-in fetch) and a Plan to Eat account.

The package ships two bins: plan-to-eat-mcp (the MCP server) and plan-to-eat (the CLI). To run the CLI through npx without installing, note that you have to select it explicitly, since the default bin is the server:

bash
npx -y -p plan-to-eat-mcp plan-to-eat --help
Building from a clone instead (for development, or the Claude Code plugin)
bash
git clone https://github.com/alex-zwingli/plan-to-eat-mcp.gitcd plan-to-eat-mcpnpm installnpm run build

The build emits CommonJS to dist/.

Configuration

VarRequiredDefaultDescription
PLAN_TO_EAT_USERNAMEyes—Plan to Eat login email
PLAN_TO_EAT_PASSWORDyes—Plan to Eat password
PLAN_TO_EAT_SESSION_FILEno~/.plan-to-eat-session.jsonWhere the cookie session is cached. Set to "" to disable caching.

The CLI also reads a .env in the working directory (shell variables win). The MCP server does not — MCP hosts pass env explicitly, as shown below.


🤖 Use it with an agent

Any host that can launch a local stdio MCP server works. The server needs one command, two env vars, and nothing else — no ports, no OAuth, no daemon.

Claude Code, the easy way: install the plugin

The repo ships as a Claude Code plugin — MCP server and both skills in one step:

bash
export [email protected]export PLAN_TO_EAT_PASSWORD=hunter2
git clone https://github.com/alex-zwingli/plan-to-eat-mcp.gitcd plan-to-eat-mcp && npm install && npm run build
claude plugin marketplace add "$(pwd)"claude plugin install plan-to-eat@plan-to-eat

That gives you:

ComponentWhat it is
MCP server plan-to-eatall 36 tools
Skill plan-to-eathow to use the MCP tools well — workflows and gotchas
Skill plan-to-eat-clithe same, for agents driving the CLI instead

Confirm with claude plugin details plan-to-eat@plan-to-eat and claude mcp list. The server reads PLAN_TO_EAT_USERNAME / PLAN_TO_EAT_PASSWORD from the environment Claude Code was launched with, so export them in your shell profile rather than committing them anywhere.

Claude Code, manually

bash
claude mcp add plan-to-eat \  --env [email protected] \  --env PLAN_TO_EAT_PASSWORD=hunter2 \  -- npx -y plan-to-eat-mcp

Add --scope user to make it available in every project instead of just this one. Check it connected with claude mcp list, or /mcp inside a session.

Claude Desktop

Edit claude_desktop_config.json — Settings → Developer → Edit Config, or:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
jsonc
{  "mcpServers": {    "plan-to-eat": {      "command": "npx",      "args": ["-y", "plan-to-eat-mcp"],      "env": {        "PLAN_TO_EAT_USERNAME": "[email protected]",        "PLAN_TO_EAT_PASSWORD": "hunter2"      }    }  }}

Restart Claude Desktop, and you're cooking.

Any other MCP host

Cursor, Windsurf, Zed, Cline, Continue, OpenClaw, VS Code's MCP support, and custom SDK clients all take the same three things. Point them at:

FieldValue
Transportstdio
Commandnpx
Args["-y", "plan-to-eat-mcp"]
EnvPLAN_TO_EAT_USERNAME, PLAN_TO_EAT_PASSWORD

Most of them use the same mcpServers JSON block as Claude Desktop above — often in .cursor/mcp.json, .vscode/mcp.json, or the host's settings UI.

If you installed globally (npm i -g plan-to-eat-mcp), use the plan-to-eat-mcp bin as the command and drop the args entirely. If you built from a clone, the command is node with ["/absolute/path/to/plan-to-eat-mcp/dist/mcp/server.js"].

Absolute paths matter for the clone route. MCP hosts don't launch servers from your project directory, so a relative path will fail to resolve. The npx command above sidesteps this entirely.

Verify it works

bash
[email protected] PLAN_TO_EAT_PASSWORD=hunter2 npx -y plan-to-eat-mcp

You should see [plan-to-eat] mcp server ready on stdio (36 tools) on stderr. That's the server waiting for a client — Ctrl-C out. If instead you get a credentials error, fix that before wiring up a host, where the failure is harder to see.

Teach your agent the workflows

Two skills ship in .claude/skills/, covering the common flows and the sharp edges (the supper-vs-dinner alias, the description-vs-title mismatch on note entries, checking for duplicates before scheduling):

  • plan-to-eat — for agents calling the MCP tools.
  • plan-to-eat-cli — for agents that have a shell but no MCP server. Same 30 capabilities, driven through subcommands, with --json for parsing.

The plugin install above registers both. Agents on other hosts can read them as plain context — point them at the files, or paste one into your system prompt.

Or install just the skills, into any of 18+ agents, with the skills.sh CLI:

bash
npx skills add alex-zwingli/plan-to-eat-mcp

That copies both SKILL.md files into .agents/skills/ and symlinks them for Claude Code, Cursor, Codex, Copilot, Gemini CLI and the rest. Add --skill plan-to-eat-cli to take only one. Note that this installs the skills and not the server — each skill's setup section walks the agent through building the MCP server or CLI if it isn't already there.

For OpenClaw agents, both skills are on ClawHub:

bash
clawhub install plan-to-eat        # MCP toolsclawhub install plan-to-eat-cli    # shell / CLI

Their frontmatter declares the credentials and binaries each one needs under metadata.openclaw, so ClawHub can check your environment at install time.


⌨️ Use it from the terminal

Every MCP tool is also a subcommand. Underscores become dashes; both spellings work.

bash
npm i -g plan-to-eat-mcpplan-to-eat --help

Or without installing — note the -p, since the package's default bin is the MCP server, not the CLI:

bash
npx -y -p plan-to-eat-mcp plan-to-eat --help
console
$ plan-to-eat list-frozen-recipesID      RECIPE_ID  COUNT  SERVINGS  FROZEN_ON──────  ─────────  ─────  ────────  ──────────227854  44676380   6      1.0       2025-05-04227908  17314561   3      1.0       2025-05-05
2 rows
$ plan-to-eat add-planner-note "Defrost chicken" 2026-05-05 dinnerid       67710999date     2026-05-05section  dinner
$ plan-to-eat get-counts --json | jq .frozen10
  • Positional or flagged — get-recipe 123 and get-recipe --id 123 are the same. <command> --help lists which arguments are positional.
  • --json prints the raw payload instead of a table, for piping into jq.
  • Arrays repeat the flag (--event_ids 11 --event_ids 22) or take JSON (--event_ids '[11,22]'). Object arguments take JSON: --ingredients '{"title":"bread","amount":"2"}'.
  • Validation is the same Zod schema the MCP server uses, so a bad enum or a malformed date fails the same way in both surfaces.

🧰 The 36 tools

Each is an MCP tool and a CLI subcommand — add_planner_recipe the tool is plan-to-eat add-planner-recipe in the shell. Full reference with input schemas and return shapes: docs/TOOLS.md.

Recipes

ToolWhat it does
list_recipesYour whole recipe book, optionally filtered by title words (search), course, or owned_only. Brief rows (id, title, course, tags, …; full for every field) — no ingredients.
get_recipeOne recipe with directions, ingredients, tags, prep_notes, comments.
create_recipeCreate. Only title is required.
update_recipePatch any subset of fields.
delete_recipeDelete by id.

Planner — read

ToolWhat it does
list_planner_eventsAll planner entries, no date filter.
get_planner_weekEvents in a date range, with recipe_title pre-joined. end_date defaults to start_date + 6 days.

Planner — write

ToolWhat it does
add_planner_recipeSchedule a recipe on a date + section.
add_planner_ingredientAttach a freeform ingredient ("2 lbs ground beef") to a meal slot.
add_planner_noteAttach a freeform note ("Defrost chicken") to a meal slot.
add_leftover_mealSchedule a leftover from a previously planned recipe event (duplicate with plan_leftover + optional move).
move_planner_eventReschedule any planner event to a new date/section.
reorder_planner_eventsReorder events within a section (pass ids in desired order).
update_planner_entry_textEdit the text of a note or ingredient entry.
set_planner_servingsChange servings on a recipe event.
duplicate_planner_eventDuplicate any event. Optional plan_leftover.
delete_planner_eventDelete by id.
find_planned_datesFind planner events for a recipe in a date range. Useful for duplicate checks.

Freezer

ToolWhat it does
list_frozen_recipesWhat's currently in the freezer. {include_consumed: true} to also see history.
freeze_recipe_portionsMark N portions of a cooked recipe as frozen, tied to the planner event they came from.
delete_frozen_recipeMark a frozen entry as consumed (soft-delete: API zeroes count, row persists).

Shopping list

A line is addressed by its item_ids array, not a scalar id — Plan to Eat merges duplicate ingredients into one line that keeps every underlying row id.

ToolWhat it does
get_shopping_listThe list, each line with the store (store_title) and aisle it's filed under, and which recipes pulled it in.
add_shopping_list_itemsAdd items. Only title required; the aisle is guessed and the store defaults to the one last used for that item.
update_shopping_list_itemsRetitle / re-quantify a line, or move any number of lines to a different store or aisle.
remove_shopping_list_itemsTake lines off the list (soft delete).
restore_shopping_list_itemsPut removed lines back.

Lookup tables & extras

ToolWhat it does
list_courses / list_cuisines / list_main_ingredients / list_tagsLookup tables.
list_stores / list_grocery_categoriesYour stores and grocery aisles — the ids store_id and category_id want.
list_menusSaved menus.
list_friendsFriends list.
get_counts{ friends, queued, frozen } from the recipe-book widget.
update_planner_optionsSet planner display preferences (timezone, start day, nutrition columns). Rarely needed.

📚 Use the client as a library

ts
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 recipeconst [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);

The client stashes credentials internally on first login so it can transparently re-authenticate if the cached cookies expire mid-session.

The tool registry is exported too, if you want to build your own adapter over the same 36 capabilities:

ts
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 seesconst recipe = await getRecipe.run(pte, { id: 123 });

🧪 API reference (the parts that work)

All paths under https://app.plantoeat.com.

JSON endpoints (/api/v1/*)

MethodPathNotes
GET/api/v1/recipes/lite_plusThe whole recipe book as one array of light listings (title, course/cuisine/main-ingredient titles, tags, flags; no ingredients). What the web app's recipe grid uses. Includes inactive/removed/hidden rows — filter on active, remove, hidden. Ignores paging params, but doesn't need them. ?ids[]=1&ids[]=2 is how the web app refreshes specific cards.
GET/api/v1/recipesDon't use for listing. Returns only the oldest 500 recipes by id, with ingredients embedded. Ignores every paging/sorting param tried: page, per_page, offset, limit, start, after_id, page[number], sort, order, q, search. /api/v1/recipes/search, /api/v1/recipes/count and /api/v2/recipes are 404; /recipes.json is 406.
GET/api/v1/recipes/:idSingle recipe with directions, ingredients, tags, prep_notes, comments.
POST/api/v1/recipesCreate. Body: { "recipe": {...} }. Returns 201 + full recipe.
PUT/api/v1/recipes/:idUpdate. Same body shape.
DELETE/api/v1/recipes/:idDelete. Returns the deleted recipe.
GET/api/v1/courses, /cuisines, /main_ingredients, /tagsLookup tables.
GET/api/v1/eventsPlanner entries (calendar). Returns the entire calendar — filter by date client-side.
GET/api/v1/menusSaved menus.
GET/api/v1/shopping_listSync metadata only (updated_items, last_sync_time) — not the list.
GET/api/v1/shopping_list/itemsThe shopping list itself, one entry per merged line.
GET/api/v1/storesGrocery stores.
GET/api/v1/grocery_categoriesGrocery aisles.
GET/api/v1/friendsFriends.
GET/api/v1/frozen_recipesFreezer: [{id, recipe_id, count, servings, frozen_on}].
DELETE/api/v1/frozen_recipes/:idSoft-delete (sets count: 0; row persists). Returns the updated row.
GET/recipes/counts/{ friends, queued, frozen }. (Note: not under /api/v1.)

Planner write endpoints (/planner/*)

A different style: form-encoded bodies, text/javascript (empty) responses. The server mutates state and the UI re-fetches separately. Required headers: X-CSRF-Token, X-Requested-With: XMLHttpRequest, Accept: text/javascript. Because the response body is empty, the client recovers any new event ID by diffing /api/v1/events before and after.

MethodPathBody
POST/planner/createrid=<recipeId>&date=YYYY-MM-DD&section=... (recipe), or date=...&section=...&eventType=note|ingredient&title=<text>
POST/planner/create/rid=<id>&frozen_id=&date=...&section=... (frozen-recipe variant — note the trailing slash)
POST/planner/updateeventid=<id>&date=...&section=...&readonly=false (move/reschedule)
POST/planner/update/<id>description=<text> (edit note/ingredient text)
POST/planner/update_servingevent=<id>&serving=<n>
POST/planner/duplicateid=<id>&plan_leftover=true|false&readonly=false
POST/planner/update_orderids=e<id1>,e<id2> — reorder events in a section
POST/planner/destroyid=<id>&readonly=false
POST/planner/update_planner_optionsNested Rails keys: user[time_zone]=...&calendar_settings[show_calories]=1&...
POST/frozen_recipesid=<recipe_id>&eid=<event_id>&count=<n>&servings=<per-portion> — freeze N portions
GET/planner/search_datesReturns rendered HTML, not JSON — not used by the client. We filter /api/v1/events instead.

section values are breakfast, lunch, dinner, snacks. Note that the server may normalize dinner → supper based on the user's per-account preference; reads will reflect the canonical name.

Authentication

Cookie-based. The client supports two flows:

  1. Login. POST /login with login[email] and login[password] plus the authenticity_token from the meta tag on GET /login. Server returns a 302 and sets cookies.
  2. Reuse cookies. The "remember me" pair ptermid2 (user id) and ptermxt2 (long-lived token) is sufficient on its own — stash those and skip re-login until they're invalidated.

Write requests need an X-CSRF-Token header. The client grabs it from the <meta name="csrf-token"> tag on the /recipes page on demand.

HTTP Basic auth on /api/v1/... is not supported (returns 401).

Recipe payload shape

The single-recipe response has 65 fields. Writable on POST/PUT include: title, description, source, url, servings, yield, scaling, prep_time, cook_time, total_time (minutes), course_id, cuisine_id, main_ingredient_id, tag_titles (comma list), directions (free text), private, draft, rating, nutrition strings (calories, sodium, etc.), and ingredients.

Ingredients use Rails nested-attributes — the wire field is recipe_ingredients_attributes, not ingredients. The client and the create_recipe / update_recipe tools accept the friendlier name ingredients and translate. Each entry:

json
{ "title": "water", "amount": "1", "unit": "cup", "note": "", "position": 1 }

To delete an existing ingredient on update, include its id plus "_destroy": true. The server back-fills amount_float, metric_amount, metric_unit, and similar_titles.


📁 Layout

One package, three layers. The logic lives in core/; the MCP server and the CLI are thin adapters over the same registry.

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

Adding a tool means adding one entry to src/core/tools.ts. It appears in the MCP server and the CLI at once, with the same name, schema, and description — they can't drift apart.

Other files worth knowing:

  • docs/TOOLS.md — per-tool reference with input/output shapes and gotchas. Hand-written; npm run check:docs fails if it and the registry disagree about which tools exist.
  • .claude/skills/plan-to-eat/SKILL.md — how to use the MCP tools well.
  • .claude/skills/plan-to-eat-cli/SKILL.md — the same, for the CLI.
  • .claude-plugin/ — Claude Code plugin and marketplace manifests.
  • .mcp.json — the plugin's MCP server declaration.
  • dist/ — emitted by npm run build.

Upgrading from ≤0.4? The server moved from dist/server.js to dist/mcp/server.js. The old path still works — it's a shim that loads the new one — so existing host configs and deployments keep running. New configs should use the new path or the plan-to-eat-mcp bin.

Playwright was used during reverse engineering and is kept as a devDependency for any future API-discovery work; the runtime depends only on fetch, the MCP SDK, and Zod.

Scripts

CommandWhat it does
npm run buildCompile src/**/*.ts to dist/.
npm run watchSame, in watch mode.
npm startRun the compiled MCP server (dist/mcp/server.js).
npm run cli -- <command>Run the CLI without linking it globally.
npm run verifySmoke-test the client end-to-end against your account (recipes).
npm run verify:plannerSmoke-test the planner write endpoints (creates + cleans up test events on a date 6 months out).
npm testSmoke-test the MCP server end-to-end (spawns it and calls tools).
npm run check:docsCheck docs/TOOLS.md covers exactly the registered tools.
npm run test:unitOffline unit tests with fetch stubbed. Touches nothing; CI runs these.
npm run cleanRemove dist/.

The verify* and test scripts hit your real account (test:unit doesn't). They create and delete their own test data, but they are not a dry run — see CONTRIBUTING.md.


🤝 Contributing

Bug reports, new endpoints, and upstream-breakage fixes are all welcome — see CONTRIBUTING.md. The one thing to know up front: the test scripts run against a real Plan to Eat account and create real data (then clean it up). Use your own.


🙏 Support Plan to Eat

This whole project exists because Plan to Eat is great. If you find this useful, the best thing you can do is give Plan to Eat a try with my referral link. Free 14-day trial, no card needed.

License

MIT — see LICENSE. Do whatever you want with it; just don't blame me if Plan to Eat ships a breaking change.

來源:README.md,提交 a23db4a

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

2
  1. v0.8.0最新Oct 17, 2026
  2. v0.7.3Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分