Skip to main content
Glama
ampdot-io

anova-oven-mcp

by ampdot-io

Anova Precision Oven 库 + MCP 服务器

该项目包含两个刻意分离的层:

  • anova_oven:一个异步 Python 库,用于 Anova 认证、设备发现、温度读取、烹饪控制、阶段和 APO 2.0 WebRTC 摄像头帧。

  • anova_oven_mcp:基于该库的精简 MCP 2.x 适配器。

这种分离让未来可复用于 Raspberry Pi 服务或扩展,同时使 MCP 不成为核心依赖。

功能

  • 捕获一帧 JPEG 摄像头帧,或作为异步迭代器持续消费帧。

  • 读取四个物理烹饪传感器:干式顶部、干式底部、湿球和食物探针。当前生效的干式控制值单独返回。

  • 启动和停止烹饪。定时阶段支持 1 秒至烤箱最大时长的 359,940 秒(99 小时 59 分钟);若省略时长,则将持续运行直至停止。

  • 支持探针终止的烹饪,也支持顺序执行、定时、预热延迟或手动推进的阶段。

  • 替换进行中烹饪的阶段列表。

  • 返回 UTC 时刻的时、分、秒。

  • 从 macOS Keychain、权限为 0600 的私有文件或注入的环境机密中加载凭据。

Related MCP server: fireboard-mcp

重要状态与安全说明

烹饪命令会真实地触发设备动作。启动或更改烹饪的 MCP 工具必须带有 acknowledge_physical_action=true,并会校验烤箱文档中规定的温度、定时器、探针、加热元件、蒸汽、风扇和支架限制。

摄像头通路是私有移动应用协议,不属于 Anova 文档化的 Personal Access Token 命令范围。它当前要求:

  • Anova Precision Oven 2.0

  • 存在进行中的烹饪

  • 兼容或更新的固件

  • 有效的 Anova 订阅

实时视频的命令或响应形式可能随未来的 Anova 应用/后端版本而变化。签名后的播放 URL 只保存在内部,库或 MCP 服务器绝不会返回这些 URL。

已完成的实测传感器、烹饪、摄像头和测试后安全检查,请参见 VALIDATION.md。

安装

需要 Python 3.11 或更高版本,推荐使用 Python 3.12。

python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[server]"

仅使用库而不需要 MCP 或视频:

python -m pip install -e .

可选的扩展有 camera、mcp、server 和 test。基础安装可保持核心库轻量;若缺少可选运行时环境,anova-oven-mcp 命令会提示安装 mcp 或 server 附加模块。

凭据

默认凭据的搜索顺序是:

  1. ANOVA_FIREBASE_REFRESH_TOKEN

  2. 由 ANOVA_FIREBASE_REFRESH_TOKEN_FILE 指定的文件

  3. macOS Keychain 的通用密码条目,其中:

    • service:com.codex.anova-camera.firebase-refresh-token

    • account:anova-oven-mcp

固定的 Keychain 账户名可避免同一 service 下较旧的凭据被意外选中。Keychain 的读取和令牌轮换均直接使用 Apple 的 Security 框架,因此机密不会出现在进程参数中。

不要将刷新令牌写入源代码、MCP 配置、shell 历史或日志。对于 Raspberry Pi 的部署,推荐使用主机密钥管理器,或 root 拥有且权限为 0600 的凭据文件:

chmod 600 /run/credentials/anova-refresh-token
export ANOVA_FIREBASE_REFRESH_TOKEN_FILE=/run/credentials/anova-refresh-token

若已配对多台烤箱,请在进程环境中设置 ANOVA_OVEN_ID。MCP 的 device-list 工具只会返回脱敏后的 ID;完整 ID 需在模型可见的上下文之外配置。

MCP 服务器

本地默认使用 stdio,因此不会打开监听端口:

.venv/bin/anova-oven-mcp

通用的桌面 MCP 配置如下:

{
  "mcpServers": {
    "anova-oven": {
      "command": "/absolute/path/to/anova-oven-mcp/.venv/bin/anova-oven-mcp"
    }
  }
}

可用工具:

工具

用途

oven_list_devices

列出已配对的烤箱,仅显示脱敏 ID

oven_get_temperatures

读取全部四个物理传感器温度以及干式控制值

oven_get_camera_frame

返回一帧 image/jpeg MCP 图像

oven_start_cook

启动单阶段定时、探针或无限期烹饪

oven_start_staged_cook

启动多阶段烹饪

oven_configure_stages

替换进行中烹饪的阶段列表

oven_start_stage

切换到已配置的阶段 UUID

oven_stop_cook

停止烹饪并关闭实时视频

get_utc_time

返回 UTC 时、分、秒

Claude Code 和 Claude Desktop

与 Claude(程序)配套的配置器可以将这个本地 stdio 服务器注册到 Claude Code、Claude Desktop 或两者。它不会把 Anova 凭据复制进任一客户端。

先预览将要做的更改:

python scripts/configure_claude.py --dry-run

配置两个客户端(Claude Code 默认使用用户作用域):

python scripts/configure_claude.py --target both

其他可用选项:

# One client only
python scripts/configure_claude.py --target code
python scripts/configure_claude.py --target desktop

# Update an existing same-named Claude Code entry
python scripts/configure_claude.py --target code --replace

# Remove the entry from both clients
python scripts/configure_claude.py --remove

Claude Desktop 配置会以原子方式合并,保留其他服务器并创建带时间戳、权限为 0600 的备份。随后请退出并重新打开 Claude Desktop。如需在本地检出之外分发此项目,Anthropic 当前最推荐的格式是可安装的 MCP Bundle(.mcpb)。

未来若用于 Pi 服务,同一个适配器也可改用 Streamable HTTP:

anova-oven-mcp --transport streamable-http

这会绑定到 127.0.0.1:8766。非回环绑定需要 --allow-lan;在引入带认证的反向代理或 MCP 授权层之前,请勿暴露该服务。

库使用示例

import asyncio

from anova_oven import CookPlan, CookingStage, PrecisionOvenClient


async def main() -> None:
    async with PrecisionOvenClient() as oven:
        temperatures = await oven.get_temperatures()
        print(temperatures.as_dict())

        plan = CookPlan(
            title="Two-stage example",
            stages=(
                CookingStage(
                    title="Warm",
                    target_celsius=60,
                    duration_seconds=600,
                ),
                CookingStage(
                    title="Finish",
                    target_celsius=180,
                    duration_seconds=300,
                ),
            ),
        )

        # This physically starts the oven:
        receipt = await oven.start_cook(plan)
        print(receipt.stage_ids)

        try:
            frame = await oven.capture_frame(timeout=60)
            with open("oven-frame.jpg", "wb") as output:
                output.write(frame.jpeg_bytes)
        finally:
            await oven.stop_cook()


asyncio.run(main())

对于连续多帧,可将 oven.frames() 用作异步迭代器。MCP 有意只提供单帧图像,因为无限持续流式工具调用在主机间移植性较差。

验证

python -m pip install -e ".[server,test]"
ruff check .
mypy src
pytest
python -m pip check

只读账户检查如下:

python scripts/live_read_only.py

受保护的摄像头自动测件会启动一个最低温度的三分钟烹饪,等待独立状态事件确认烹饪启动后,捕获一帧,再“尽责进行媒体清理”之前发出物理停止命令:

python scripts/live_camera_smoke.py --acknowledge-empty-oven-and-start-cook

该测试已在 APO 2.0 上成功完成。所捕获的验证帧已放入项目 oven-camera-smoke.jpg。

协议来源

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for interacting with Fireboard BBQ temperature monitoring. Enables querying devices, live probe temperatures, Drive fan controller status, and historical cook sessions.
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables MCP clients to monitor and control a Bambu Lab P1S printer over the local network, including status, file management, slicing, and print operations.
    11
    MIT