关于 chowdown
chowdown 是一款食谱应用,将 Cooklang 文件存储在用户自己的 Google Drive 中,并供 AI 助手访问。它结合食谱浏览、按食材发现内容和通过 OAuth 2.1 保护的 MCP 服务。
主要功能
- 01将食谱以 Cooklang 文件存于 Google Drive
- 02浏览和筛选食谱
- 03按现有食材查找食谱
- 04添加、编辑、标记和注释食谱
- 05管理收藏与笔记
适用场景
- 01按饮食类型或烹饪偏好搜索食谱
- 02查找可使用现有食材制作的菜品
- 03让助手浏览或更新食谱集
- 04用 Agent Skill 导入书签中的食谱链接
MCP 相关
MCP 服务提供食谱浏览、食材匹配、筛选和食谱管理工具,并设有读写权限范围。客户端通过服务地址连接并使用 OAuth 2.1 授权;使用前须先连接 Google Drive。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://chowdown.apps.mrida.ng/mcpclaude mcp add --transport http mridang-chowdown https://chowdown.apps.mrida.ng/mcp{"mcpServers":{"mridang-chowdown":{"type":"http","url":"https://chowdown.apps.mrida.ng/mcp"}}}在 Cursor 中打开{"servers":{"mridang-chowdown":{"type":"http","url":"https://chowdown.apps.mrida.ng/mcp"}}}在 VS Code 中打开{"mcpServers":{"mridang-chowdown":{"type":"http","url":"https://chowdown.apps.mrida.ng/mcp"}}}{"mcpServers":{"mridang-chowdown":{"serverUrl":"https://chowdown.apps.mrida.ng/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
🍳 chowdown
一款用于处理个人 Google Drive 中 Cooklang .cook 文件的食谱应用。基于 Next.js 构建,并通过 OpenNext 部署在 Cloudflare Workers 上。
Cloudflare Worker 负责实际工作:Google 登录、单独的“连接 Google Drive”步骤、将 Recipes 文件夹同步到 D1 缓存、REST API、MCP 服务(含其 OAuth 2.1 端点),以及用于添加标签和“查找相似内容”的模型调用(Workers AI)。Drive 始终是事实来源;D1 是缓存,因此页面只需一次往返即可完成渲染。
技术栈
- Next.js 16(App Router)、React 19 和 Tailwind 4,通过 OpenNext(
@opennextjs/cloudflare)运行在 Cloudflare Workers 上 - D1 与 Drizzle,以及 Workers AI 和 Images 绑定
- devbox 固定使用 Node 24
- 使用 Jest 进行单元测试,使用 Cypress 进行端到端测试
- 使用
@mridang/eslint-defaults进行代码检查 - 使用
@cooklang/cooklang-ts进行解析
Google 设置
登录和连接 Google Drive 是两个独立步骤,各自都有自己的 Google 同意屏幕:
- 登录仅请求身份信息(
openid email profile)。它会创建账户和签名会话 Cookie,不做其他操作。 - 连接 Google Drive(页眉、账户菜单以及需要 Drive 的页面上都有此按钮;
GET /auth/drive)会添加drive.file范围和离线刷新令牌,然后创建由应用管理的“Recipes”文件夹。drive.file属于非敏感权限范围,且只能访问 chowdown 创建的文件,因此无需通过 Google 验证,也不会发布到 Marketplace。
连接 Drive 之前,用户可以浏览应用并查看已有缓存内容,但任何读取或写入其 Drive 文件的操作都会被拒绝(REST API 返回 409 /problems/drive-not-connected,MCP 工具则返回一条说明该如何操作的错误结果)。
在 Google Cloud 中进行设置:
- 启用 Google Drive API。
- OAuth 同意屏幕:选择 External,添加
.../auth/drive.file范围,并将你的 Gmail 地址添加为测试用户(或发布到生产环境——仍无需审核)。 - OAuth 客户端 ID(Web 应用)→ 已获授权的重定向 URI:
http://localhost:3737/auth/callback(开发环境)https://chowdown.apps.mrida.ng/auth/callback(生产环境)
密钥:本地存放在 .env 中,生产环境使用 wrangler secret put <NAME>(参见 Deploy):
GOOGLE_OAUTH_CLIENT_ID=....apps.googleusercontent.com
GOOGLE_OAUTH_CLIENT_SECRET=...
SESSION_SECRET=... # openssl rand -base64 32 — signs the session cookie
TOKEN_ENCRYPTION_KEY=... # openssl rand -base64 32 — seals Drive refresh tokens
APP_URL 为可选项(公共源站地址,无法从请求中读取时使用)。
连接助手(MCP)
chowdown 是一个 MCP 服务,地址为 https://<your-domain>/mcp,并按照 MCP authorization spec 中的说明,通过 OAuth 2.1 进行保护。将该 URL 添加为 ChatGPT、Claude 或任何 MCP 客户端中的连接器;出现提示时,使用 Google 登录并批准即可。无需复制任何密钥。用户需要先连接 Google Drive(见上文);在此之前,系统会告知助手这一情况,而不是向其显示一个空集合。
chowdown 已在 MCP Registry 中登记,名称为 io.github.mridang/chowdown;登记文件是此仓库中的 server.json。
- 权限范围:
recipes:read(浏览和搜索)以及recipes:write(添加、编辑、添加标签、收藏、添加注释)。可以仅授予助手读取权限。 - 询问做什么菜:
browse_recipes(“我想做印度菜”“30 分钟内能做的素食”)、recipes_from_ingredients(“我有 3 个番茄和 400 g 意面”,返回现在能做什么,以及还差几种食材就能做什么)和list_filters。每道菜都会根据食材归类为纯素、素食、鱼素或非素食,因此可以按饮食类型分组和筛选结果;现有菜谱无需重新添加标签,也能享受此功能。 - 发现:
/.well-known/oauth-protected-resource/mcp(RFC 9728)和/.well-known/oauth-authorization-server(RFC 8414)。 - 客户端注册: Client ID Metadata Documents(首选)和动态注册(
/oauth/register,RFC 7591)。仅支持公共客户端,必须使用 PKCES256。 - 令牌: 不透明令牌,以哈希形式存储。访问令牌有效期为一小时;刷新令牌每次使用后都会轮换,重用旧令牌会撤销整个连接。
- 断开连接: 在应用中选择“已连接的应用”,或使用
POST /oauth/revoke。
REST API
应用的数据可通过 /api 下的 REST API 访问。该 API 按照
Zalando RESTful API guidelines 设计
(名词使用复数形式、JSON 使用 snake_case、RFC 9457 问题详情、游标分页、
JSON Merge Patch、ETag / If-Match、X-Flow-ID)。有意采用的例外是
/api 前缀以及不带连字符的路径段(recipes/imports,而非
recipe-imports)。
| 资源 | 方法 |
|---|---|
/api/recipes、/api/recipes/{recipe_id} | 列出、创建 · 读取、替换、修补、删除 |
/api/recipes/{recipe_id}/notes[/{note-id}] | 列出、创建 · 读取、替换、删除 |
/api/recipes/{recipe_id}/similar | 列出 |
/api/recipes/suggestions?q= | 列出 |
/api/recipes/imports[/{import-id}] | 列出、创建 · 读取、删除 |
/api/users/self | 读取、修补 |
/api/users/self/favourites[/{recipe_id}] | 列出 · 读取、设置、删除 |
/api/users/self/connections[/{grant_id}] | 列出 · 删除 |
/api/sessions/self | 删除(退出登录) |
身份验证使用签名会话 Cookie。写入操作必须来自应用自己的页面
(跨站写入会收到 403)。登录不会连接 Google Drive:用户在浏览器中连接 Drive 之前,写入操作和 /api/recipes/suggestions 都会返回 409 /problems/drive-not-connected。所有非资源内容均不属于 API:MCP(/mcp)、OAuth(/oauth/*、/.well-known/*)、Google 登录和 Drive 连接重定向(/auth/*)、健康检查(/health)、图片代理(/img)、CSP 报告(/csp/reports)。
本地开发
所有命令都通过 devbox 运行,它会固定使用 Node 24:
devbox run -- npx wrangler login # once: the AI binding is remote-only in dev
devbox run -- npm run migrate # apply D1 migrations to the local database
devbox run -- npm run build:views # once, and after changing src/views: the generated widget pages
devbox run -- npm run dev # next dev on http://localhost:3737
devbox run -- npm test # jest, including the MCP conformance suite
devbox run -- npm run lint # eslint
devbox run -- npm run typecheck # tsc --noEmit
devbox run -- npm run format # prettier
登录前,将 Google 设置 中列出的密钥放入 .env(已加入 gitignore)。http://localhost:3737 无需证书,因为 Google OAuth 允许 localhost 使用 http:将 http://localhost:3737/auth/callback 添加到 OAuth 客户端的重定向 URI 中。
部署
# one-time per environment
devbox run -- npx wrangler d1 create chowdown-db # paste the id into wrangler.jsonc
devbox run -- npx wrangler d1 migrations apply DB --remote
devbox run -- npx wrangler secret put GOOGLE_OAUTH_CLIENT_ID
devbox run -- npx wrangler secret put GOOGLE_OAUTH_CLIENT_SECRET
devbox run -- npx wrangler secret put SESSION_SECRET
devbox run -- npx wrangler secret put TOKEN_ENCRYPTION_KEY
# every release
devbox run -- npm run deploy # opennextjs-cloudflare build && wrangler deploy
自定义域名 chowdown.apps.mrida.ng 需要 Cloudflare 账户中有 apps.mrida.ng 区域,并且 Worker 需要 AI 和 Images 绑定(在 wrangler.jsonc 中声明)。
GitHub Actions(deploy.yml)会应用 D1 迁移,并在推送到 master 时进行部署。它需要 production 环境中的 CLOUDFLARE_API_TOKEN 密钥和 CLOUDFLARE_ACCOUNT_ID 变量。
运维
设置。 SESSION_SECRET 用于签署会话 Cookie,TOKEN_ENCRYPTION_KEY
用于封装 Drive 刷新令牌;两者都是 Worker 密钥。APP_URL 是公开源地址:在生产环境中设置它,因为未设置时,源地址会从请求的 Host 标头中读取。MCP_ALLOWED_ORIGINS(逗号分隔的精确源地址,例如 chrome-extension://abcdef)允许基于浏览器或 WebView 的 MCP 客户端调用 /mcp;对于在服务端运行的助手,请保持未设置。
速率限制。 共三层,成本从低到高:
- Cloudflare Workers 速率限制绑定(
wrangler.jsonc中的ratelimits,共 13 个),会在应用运行前由 Worker 检查。哪些请求计入哪个绑定,记录在src/lib/http/edge-limits.ts中,并有测试确保两者保持同步。这些限制按 Cloudflare 位置计算,且最终一致:它是用于拒绝流量洪泛的成本保护措施,而非计量系统。 还可选择添加一条 Cloudflare WAF 速率限制规则(控制面板: Security、WAF、Rate limiting rules),以便在 Worker 完全未被调用前阻止流量洪泛。 - D1 中精确且持久的计数器:OAuth 客户端注册、令牌端点、每用户 MCP 调用,以及导入、建议和调用模型的助手工具的每日限额(
src/lib/util/daily-budget.ts)。 - 请求内部的硬性上限:每次导入最多 10 个链接或食谱、请求正文大小、页面和图像字节数,以及 5,000 行 Cooklang 内容。
被拒绝的调用会返回 429,并附带 Retry-After。
检查。 devbox run -- npm test 会针对服务器对 2026-07-28 和 2025-11-25 版本的请求处理运行官方 MCP 一致性测试套件
(test/e2e/mcp.e2e.test.ts,其中也列出了已知缺口及其原因)。MCP 2024-11-05 客户端只能通过可流式 HTTP 使用(未提供 HTTP+SSE 传输)。
Agent 技能
技能是 AI Agent 可以加载并端到端执行任务的文件夹。
它们遵循开放的 Agent Skills 格式(包含 SKILL.md 和辅助脚本),因此可用于 Claude Code、Cowork、GitHub Copilot 以及其他能够读取该格式的 Agent。
| 技能 | 功能 |
|---|---|
import-bookmarked-recipes | 在你的浏览器书签中查找菜谱链接,通过 MCP 连接器将其导入 chowdown,补齐缺失的封面图片,验证导入结果,并且只会在你确认后才提供删除已导入书签的选项。也可以按计划运行(“定期导入我的菜谱”),这种情况下会导入菜谱,但绝不会删除书签。 |
要安装技能,请将其文件夹复制或符号链接到 Agent 的技能文件夹中:
# Claude Code (all projects)
ln -s "$PWD/skills/import-bookmarked-recipes" ~/.claude/skills/import-bookmarked-recipes
# GitHub Copilot (this repository)
mkdir -p .github/skills && cp -R skills/import-bookmarked-recipes .github/skills/
在 Cowork 中,将该文件夹压缩后作为自定义技能上传。还需要将 chowdown 添加为 Agent 的 MCP 连接器:使用主页或应用“Cook with AI”页面上的 MCP 服务地址,然后批准连接。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。