关于 openfoodfacts-mcp-server
面向需要使用 Open Food Facts 包装食品数据的个人和应用的 MCP 服务,支持条码查询、筛选搜索、产品比较和规范标签查找,并保留缺失数据而不作填补。
主要功能
- 01按条码查询产品
- 02按文本、标签、过敏原和营养筛选
- 03比较营养数据和产品评分
- 04将词语解析为规范分类标签
适用场景
- 01通过产品条码查看配料和过敏原
- 02查找符合营养或过敏原条件的产品
- 03比较所选产品的营养评分
MCP 相关
通过 MCP 工具提供产品查询、搜索、比较和分类词汇浏览。支持 STDIO 和 Streamable HTTP 传输。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://openfoodfacts.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-openfoodfacts https://openfoodfacts.caseyjhand.com/mcp{"mcpServers":{"cyanheads-openfoodfacts":{"type":"http","url":"https://openfoodfacts.caseyjhand.com/mcp"}}}在 Cursor 中打开{"servers":{"cyanheads-openfoodfacts":{"type":"http","url":"https://openfoodfacts.caseyjhand.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"cyanheads-openfoodfacts":{"type":"http","url":"https://openfoodfacts.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-openfoodfacts":{"serverUrl":"https://openfoodfacts.caseyjhand.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
4| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| fields | array | 否 | 要返回的字段子集。省略时返回所有标准字段。只需要得分或配料时,可用此项减少负载。无法单独读取的字段会连同其依赖字段一起返回:nutriments 会包含 serving_size、serving_quantity 和 serving_quantity_unit,以便每份数值带有对应的分母;serving_quantity_unit 也会包含其所描述的数量。requested_fields 会回显实际获取的完整字段集。 |
| barcode | string | 是 | 产品条码,仅含数字:去除前导零后为 4–40 位数字。Open Food Facts 的主键;off_search_products 行中的条码可直接使用。示例:"3017620422003"(Nutella FR)。 |
详细介绍
@cyanheads/openfoodfacts-mcp-server
通过条码查找食品,按关键词、标签、过敏原或营养筛选条件搜索,逐一比较产品,并通过 MCP 浏览规范标签词汇表。支持 STDIO 或 Streamable HTTP。
概览
来自 Open Food Facts 的包装食品数据。Open Food Facts 是一个由众包贡献构建、收录了 300 多万种产品的数据库。通过条码查找商品,按文本、标签、过敏原和营养阈值搜索,逐一比较产品,并将日常用语解析为筛选器采用的规范标签。
工具
| 工具 | 描述 |
|---|---|
off_get_product | 通过条码获取单个产品:配料、过敏原及微量成分、添加剂、评分、营养信息和标签 |
off_search_products | 按文本、标签筛选条件、过敏原排除项和营养阈值搜索(每 100 g;液体按每 100 ml);返回包含条码的摘要行 |
off_compare_products | 每次调用最多通过条码比较 10 种产品的营养信息(每 100 g;液体按每 100 ml)、Nutri-Score、NOVA 和 Green-Score |
off_browse_taxonomy | 将日常用语解析为 off_search_products 用作筛选条件的规范标签 ID |
功能参考
off_get_product 工具
barcode只能包含数字;去掉任意前导零后,长度为 4–40 位;可选的fields会精简响应,并一并获取字段所依赖的数据(nutriments会带上份量),requested_fields会回显实际获取的字段- 返回配料(原始文本及最多三层深度的解析树,包含
percent_estimate)、allergens_tags、traces_tags、additives_tags、ingredients_analysis_tags(对纯素、素食和棕榈油的判定)、nutriscore_grade、nova_group、ecoscore_grade(Green-Score)、nutriments(每份以及每 100 g;液体为每 100 ml)、类别/标签/包装/产地/国家标签、image_url和completeness(0–1) traces_tags: ["en:none"]表示标签注明不含痕量成分,而空数组表示尚未录入相关信息;如果没有贡献者记录某个条形码,则会以not_found失败
off_search_products 工具
query(最多 24 个词,每个词都必须匹配名称、通用名称、类别、标签或品牌;标点会分隔词语,因此milk-chocolate要求两者都匹配),以及标签筛选条件categories_tag、brands_tag、labels_tag(最多 10 个)、allergens_tag、traces_tag、ingredients_analysis_tag、additives_tag、nutrition_grade、nova_group、countries_tag、exclude_allergens/exclude_traces列表(各最多 14 个),以及最多 18 个nutrient_filters(每 100 g;液体为每 100 ml);所有条件按 AND 组合;可选sort_bypage_size默认为 20,每次调用最多返回 50 个;较大的值(最多 10,000)仍只返回 50 个,并在page_size_capped中标记;page按每页 50 个计数。每行包含barcode、product_name、brands、nutriscore_grade、nova_group、ecoscore_grade和categories_tags,另有total、total_is_lower_bound、last_page、omitted和truncated(表示此页之后还有匹配项)。排除条件会添加exclusion_coverage,因为未录入过敏原数据的产品也会通过这些条件;nutrient_filters会添加indexed_nutriments(筛选条件检查的索引值,可能与off_get_product返回的值不同)query或nutrient_filters搜索使用文本索引,其更新滞后于实时数据库(在text_index_snapshot中标记),且最多只能获取前 10,000 条结果;使用additives_tag会因additives_filter_needs_tag_search被拒绝。仅使用标签的搜索会读取实时数据库,最多支持到第 10 页。超出任一上限的页面会以page_out_of_range失败
off_compare_products 工具
- 接受 2–100 个
barcodes,每个条形码对应一行,并按输入顺序排列;重复条形码只比较一次;超过第 10 个不同条形码的条目会列在unprocessed中,不会被获取 - 每行包含
found、nutriscore_grade、nova_group、ecoscore_grade、能量、脂肪、饱和脂肪、糖、盐、蛋白质和纤维(每 100 g;液体为每 100 ml),以及completeness;缺失值保持缺失,不会推算补齐 not_found列出没有贡献者记录的条形码,failed列出获取失败的条形码,两者都包含reason;获取失败的条形码不会生成对应行,也不会阻止处理其他条形码
off_browse_taxonomy 工具
facet可选categories、labels、allergens、additives、countries、nova_groups、nutrition_grades之一;search会匹配标签 ID、名称或同义词中的子字符串(“shellfish” →en:crustaceans);limit(默认为 20)每次最多返回 100 个(即使指定的值最高为 200,也仍只返回 100 个);结果被截断时会说明匹配数量;不支持分页- 返回由
id和name组成的tags[],其中id可直接用于off_search_products,无需修改;nova_groups和nutrition_grades会完整返回,并附带total_in_facet - 五个开放类别会查询实时 Open Food Facts 分类体系;若其不可用,则会回退到较小的离线样本,并附带
notice;省略search时只返回该样本
功能
基于 @cyanheads/mcp-ts-core 构建:支持 stdio 和 Streamable HTTP 传输、可插拔身份验证(none / jwt / oauth)、可切换存储(in-memory、filesystem、Supabase、Cloudflare KV/R2/D1),以及结构化日志记录和可选的 OpenTelemetry 跟踪。
Open Food Facts 专属功能:
- 无需 API 密钥;内置符合 Open Food Facts 条款要求的标识性
User-Agent - 按端点设置请求预算(产品每分钟 15 次、搜索每分钟 10 次、分类体系每分钟 10 次);瞬时故障最多重试 4 次
- 将营养成分从带连字符的键规范化(
energy-kcal_100g→energy_kcal_100g),并提供additional_100g/additional_serving映射,为每种营养成分标注单位 - 标签筛选器使用规范 ID(
en:organic、en:no-gluten);文本搜索中的大小写变体、同义词或品牌名称会先转换为规范形式(US→en:united-states) - 每个字段均由贡献者录入,因此缺失字段表示尚未记录;Nutri-Score、NOVA 和 Green-Score 是 Open Food Facts 自行计算的评级,会按原样返回,并附带地区公式说明
适合 Agent 的输出:
- 每份营养数据都会注明其分母:
serving_size、serving_quantity、serving_quantity_unit;若未记录分母,则会附上说明 - 优雅处理部分失败:
off_compare_products会同时返回已解析的行以及not_found和failed项 - 明确标注计数边界:搜索结果中包含
total_is_lower_bound、last_page和omitted - 失败类型明确:每种失败都包含声明的
reason(upstream_error、upstream_timeout、upstream_rejected、rate_limited,以及各工具对应的输入原因)和恢复提示;上游响应不完整时,会作为可重试的upstream_error处理,绝不会返回空结果或标记为未找到
开始使用
公共托管实例
可使用公共实例 https://openfoodfacts.caseyjhand.com/mcp,无需安装。该实例使用 Streamable HTTP;各客户端的配置格式各不相同。
使用 Claude Code:
claude mcp add --transport http openfoodfacts-mcp-server https://openfoodfacts.caseyjhand.com/mcp
使用 Cline(cline_mcp_settings.json):
{
"mcpServers": {
"openfoodfacts-mcp-server": {
"type": "streamableHttp",
"url": "https://openfoodfacts.caseyjhand.com/mcp"
}
}
}
使用 Cursor(mcp.json):
{
"mcpServers": {
"openfoodfacts-mcp-server": {
"url": "https://openfoodfacts.caseyjhand.com/mcp"
}
}
}
Claude Desktop 可在 Customize → Connectors 中添加远程服务。
自托管 / 本地运行
无需 API 密钥。将以下内容添加到 MCP 客户端配置文件中。
{
"mcpServers": {
"openfoodfacts-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/openfoodfacts-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
也可使用 npx(无需 Bun):
{
"mcpServers": {
"openfoodfacts-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/openfoodfacts-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
也可使用 Docker:
{
"mcpServers": {
"openfoodfacts-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/openfoodfacts-mcp-server:latest"
]
}
}
}
使用 Streamable HTTP 时,设置传输方式并启动服务:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
前置条件
- Bun v1.4.0 或更高版本(或 Node.js v24+)。
- 无需 API 密钥或账户。Open Food Facts 要求客户端标识自身;服务的
User-Agent无需配置即可满足此要求。
安装
- 克隆仓库:
git clone https://github.com/cyanheads/openfoodfacts-mcp-server.git
- 进入目录:
cd openfoodfacts-mcp-server
- 安装依赖:
bun install
- 配置环境:
cp .env.example .env
# edit .env if you need to override rate limits or the base URL
配置
| 变量 | 描述 | 默认值 |
|---|---|---|
OFF_BASE_URL | Open Food Facts API 基础 URL。 | https://world.openfoodfacts.org |
OFF_RATE_LIMIT_PRODUCT | 产品读取预算(请求/分钟)。默认值为 Open Food Facts 公布的每 IP 限额;如果多个客户端共用一个出站 IP,请调低此值。 | 15 |
OFF_RATE_LIMIT_SEARCH | 搜索预算(请求/分钟)。默认值为 Open Food Facts 公布的每 IP 限额。 | 10 |
OFF_RATE_LIMIT_TAXONOMY | 分类体系查询预算(请求/分钟),由 off_browse_taxonomy、文本搜索中的标签规范化以及排除项检查共用。 | 10 |
MCP_TRANSPORT_TYPE | 传输方式:stdio 或 http。 | stdio |
MCP_HTTP_PORT | HTTP 服务端口。 | 3010 |
MCP_AUTH_MODE | 身份验证模式:none、jwt 或 oauth。 | none |
MCP_LOG_LEVEL | 日志级别(debug、info、warning、error)。 | info |
LOG_TOOL_FAILURE_PAYLOADS | 记录每次失败的工具调用的参数和结果;按键名对内容脱敏,并将大小限制为 LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES(默认值为 16384)。自由格式值中的密钥不会被脱敏。 | false |
OTEL_ENABLED | 启用 OpenTelemetry 插桩。 | false |
完整的可选覆盖项列表请参见 .env.example。
运行服务
本地开发
-
构建并运行:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:http -
运行检查和测试:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t openfoodfacts-mcp-server .
docker run --rm -p 3010:3010 openfoodfacts-mcp-server
Dockerfile 默认使用 HTTP 传输、无状态会话模式,并将日志写入 /var/log/openfoodfacts-mcp-server。默认会安装 OpenTelemetry 对等依赖;若要省略这些依赖,请使用 --build-arg OTEL_ENABLED=false 进行构建。
项目结构
| 目录 | 用途 |
|---|---|
src/index.ts | createApp() 入口点——注册工具并初始化服务。 |
src/config | 使用 Zod 解析并验证特定于服务端的环境变量。 |
src/mcp-server/tools | 工具定义(*.tool.ts)。 |
src/services/openfoodfacts | Open Food Facts API 客户端——HTTP、速率限制、重试、字段规范化。 |
src/services/taxonomy | 标签词汇——实时解析、离线示例和标签值规范化。 |
src/utils | 对文本输出中由贡献者提供的值进行 Markdown 转义。 |
tests/ | 与 src/ 结构对应的单元测试和集成测试。 |
开发指南
开发指南和架构规则请参见 CLAUDE.md。简要说明:
- 处理程序抛出异常,框架负责捕获——工具逻辑中不要使用
try/catch - 使用
ctx.log进行请求范围内的日志记录,使用ctx.state进行租户范围内的存储 - 通过
src/mcp-server/tools/definitions/index.ts中的汇总文件注册新工具 - 封装外部 API 调用:验证原始数据 → 规范化为领域类型 → 返回输出架构;绝不捏造缺失字段
贡献
欢迎提交问题——表单及如何提交有效报告,请参见 CONTRIBUTING.md。请通过私密披露报告漏洞,切勿公开提交问题。提交前请运行检查和测试:
bun run devcheck
bun run test
许可证
Apache-2.0——详情请参见 LICENSE。Open Food Facts 数据采用 Open Database License(ODbL)1.0 发布;下游使用时必须注明来源为 Open Food Facts。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。