Skip to main content
Glama
deanxizian

balatro-codex-mcp

by deanxizian

balatro-codex-mcp

balatro-codex-mcp 让 Codex 桌面端通过本地 STDIO MCP 工具控制 Steam 版 《Balatro / 小丑牌》。Python Server 只暴露经过约束的正常游戏动作,不向 Codex 提供任意 JSON-RPC、调试、作弊、存档读写、截图或返回菜单能力。

项目基于:

架构

Codex 桌面端
  ↓ STDIO MCP(唯一游戏控制入口)
本项目的 Python MCP Server
  ↓ HTTP JSON-RPC 2.0(默认 http://127.0.0.1:12346)
BalatroBot
  ↓ 游戏内 Mod API
Steam 版 Balatro

MCP Server 和 BalatroBot 使用独立生命周期。Codex 启动 MCP Server 时,Server 会尽力读取 rpc.discover,但绝不会启动、关闭、重置游戏或加载存档;即使 BalatroBot 离线,MCP 初始化和 tools/list 仍会成功,balatro_health 会返回 可执行的修复命令。

为什么 Codex 桌面端使用 MCP

MCP 把参数类型、工具说明、只读/写入提示和 server-level instructions 一起交给 Codex。模型调用 balatro_play_cards(cards=[...], expected_state_token="..."), 而不是通过 Shell 拼接 BalatroBot JSON。这样可以集中执行:

  • 0-based 索引和完整排列校验

  • state_token 乐观并发保护

  • 写锁内二次状态校验

  • 写操作禁止自动重试

  • 工具白名单和危险接口隔离

  • stdout 仅承载 MCP 协议,诊断日志只写 stderr

Related MCP server: claude-computer-use-mcp

Balatro、Lovely、Steamodded 与 BalatroBot

  • Balatro 是 Steam 游戏本体。

  • Lovely Injector 把 Mod 加载能力注入 Balatro 的 LÖVE 运行时。

  • Steamodded 是 Balatro 的 Mod loader/API。

  • BalatroBot 是运行在游戏内的 Mod,并在本机提供 HTTP JSON-RPC 2.0。

  • 本项目 不重写或修改 BalatroBot,只把它的正常游戏 API 收窄为 Codex MCP 工具。

安装 Mod 时遵循 BalatroBot 安装文档Lovely 文档Steamodded 文档。本项目脚本不会复制、 删除或修改游戏、Mod 和存档文件。

前置条件

  • macOS 与 Steam 版 Balatro 1.0.1+

  • Lovely 0.8.0+

  • Steamodded 1.0.0-beta-1221a+

  • BalatroBot Mod v1.5.2

  • Python 3.13+(项目 .python-version 固定 3.13 系列)

  • uv

  • Codex 桌面端;建议同时有 Codex CLI

BalatroBot 当前常见路径:

游戏:
~/Library/Application Support/Steam/steamapps/common/Balatro/Balatro.app

Lovely:
~/Library/Application Support/Steam/steamapps/common/Balatro/liblovely.dylib

Mods:
~/Library/Application Support/Balatro/Mods

BalatroBot:
~/Library/Application Support/Balatro/Mods/balatrobot

Quick Start

在项目根目录:

uv sync
./scripts/doctor_macos.sh
./scripts/start_balatro_macos.sh --fast

启动脚本在前台运行 BalatroBot v1.5.2,默认显示游戏窗口。不要关闭这个终端; Ctrl+C 会直接转发给 BalatroBot。--fast 可省略,也可以追加任何 balatrobot serve 参数,例如 --no-shaders。脚本不会后台运行、不会杀死占用端口 的进程,也不会重置游戏或存档。

打开另一个终端:

./scripts/verify_connection.sh
./scripts/configure_codex_mcp.sh

然后:

  1. 重启 Codex 桌面端。

  2. 打开本项目。

  3. 在对话框输入 /mcp

  4. 确认 balatro 已连接。

  5. 输入下文“推荐游戏提示词”。

如果 doctor_macos.sh 报告 Mod 或游戏缺失,先按上游文档补齐;该脚本是只读检查, 不会自动安装或修改系统。

安装 Python 项目

uv sync

该命令创建项目私有环境并生成/使用 uv.lock。完成后,真正交给 Codex 的入口是:

<仓库绝对路径>/.venv/bin/balatro-codex-mcp

可以直接验证入口存在:

test -x .venv/bin/balatro-codex-mcp

不用 uv run 启动 Codex MCP 的原因是:macOS GUI 进程未必继承 Homebrew 或用户 Shell 的 PATH.venv/bin 中的绝对控制台入口已经包含正确的 Python 环境, Codex 无需找到 uvpython3 或 Homebrew。

macOS 检查与启动 BalatroBot

只读检查:

./scripts/doctor_macos.sh

它检查 macOS、uv、Python 3.13+、Steam Balatro、Lovely、Steamodded、BalatroBot Mod、12346 端口、BalatroBot health、Codex CLI、项目 .venv 和绝对 MCP 入口。

前台启动:

./scripts/start_balatro_macos.sh

快速模式:

./scripts/start_balatro_macos.sh --fast

额外参数原样传给上游:

./scripts/start_balatro_macos.sh --fast --no-shaders --fps-cap 60

脚本使用上游推荐的 uvx balatrobot serve 路径并明确固定 v1.5.2。在 macOS, BalatroBot CLI 直接执行:

~/Library/Application Support/Steam/steamapps/common/Balatro/
Balatro.app/Contents/MacOS/love

同时通过 DYLD_INSERT_LIBRARIES 加载 liblovely.dylib。这是 BalatroBot 当前 macOS launcher 的实现;不是鼠标、OCR、截图或 UI 自动化。

只读验证 health

BalatroBot 启动后,在第二个终端运行:

./scripts/verify_connection.sh

该脚本严格只调用:

  • health

  • rpc.discover

  • gamestate

它不会调用 startplaydiscardbuysellrerollpacknext_round 或任何其他写操作。

配置 Codex 桌面端 MCP

自动配置:

./scripts/configure_codex_mcp.sh

脚本先确认 .venv 和绝对入口存在,然后执行等价于:

codex mcp add balatro \
  --env BALATROBOT_URL=http://127.0.0.1:12346 \
  -- /ABSOLUTE/PATH/TO/balatro-codex-mcp/.venv/bin/balatro-codex-mcp

如果 balatro 已存在,脚本会停止并要求先检查/移除旧配置,不会静默覆盖。成功后 会运行:

codex mcp list

也可以在 Codex 桌面端手动添加:

Settings → MCP servers → Add server → STDIO
Name: balatro
Command: <仓库绝对路径>/.venv/bin/balatro-codex-mcp
Environment: BALATROBOT_URL=http://127.0.0.1:12346

保存后必须重启 Codex 桌面端。重启后在对话框输入:

/mcp

确认 balatro 状态为 connected。可参考 .codex/config.toml.example;示例只含占位路径, 不包含开发机用户名。

环境变量

变量

默认值

说明

BALATROBOT_URL

http://127.0.0.1:12346

BalatroBot JSON-RPC 根地址

BALATROBOT_TIMEOUT

15

单次 HTTP 超时秒数

BALATROBOT_ALLOW_NON_LOOPBACK

0

仅显式设为 1 才允许非回环地址

BALATROBOT_READ_RETRIES

1

只读连接级重试次数,范围 0–3

默认只接受 localhost127.0.0.1::1。URL 不允许凭据、额外路径、query 或 fragment。非回环模式会扩大信任边界,不建议用于普通本地游戏。

MCP 工具

所有工具都有 balatro_ 前缀。

只读工具

工具

用途

balatro_health()

MCP/BalatroBot 状态、health、版本、当前阶段、discover 结果、缺失能力和 macOS 修复命令

balatro_capabilities(refresh=false)

安全上游方法的精简 OpenRPC 参数与 required states;可强制刷新缓存

balatro_get_state(view="decision")

读取紧凑 decision 或保留全部未知字段的 full state

balatro_available_actions()

当前允许/不允许动作、原因、参数、有效索引范围与 token

写工具

每个写工具都强制要求 expected_state_token,不提供可选默认值。

工具

上游方法

主要约束

balatro_start_run(deck, stake, expected_state_token, seed=None)

start

MENU

balatro_select_blind(expected_state_token)

select

BLIND_SELECT

balatro_skip_blind(expected_state_token)

skip

Boss Blind 禁止跳过

balatro_play_cards(cards, expected_state_token)

play

1–5 张、唯一、有效手牌索引

balatro_discard_cards(cards, expected_state_token)

discard

检查剩余弃牌和高亮上限

balatro_cash_out(expected_state_token)

cash_out

ROUND_EVAL

balatro_buy_shop_item(kind, index, expected_state_token)

buy

kind 转为 card/voucher/pack 参数

balatro_reroll_shop(expected_state_token)

reroll

SHOP,检查明显资金不足

balatro_sell_item(kind, index, expected_state_token)

sell

joker/consumable,拒绝 Eternal

balatro_use_consumable(consumable_index, target_cards, expected_state_token)

use

不猜测目标数量

balatro_choose_pack_item(item_index, target_cards, expected_state_token)

pack

转为 {card, targets}

balatro_skip_pack(expected_state_token)

pack

转为 {skip: true}

balatro_rearrange(area, order, expected_state_token)

rearrange

order 必须是完整排列

balatro_next_round(expected_state_token)

next_round

SHOP

所有写操作统一执行:

  1. 读取最新 gamestate

  2. 计算并比较 token。

  3. 校验阶段、参数、资源和索引。

  4. 获取唯一写锁。

  5. 在锁内再次读取状态并校验 token。

  6. 向 BalatroBot 发送恰好一次写 RPC。

  7. 再次读取状态;如果该只读请求失败,使用写响应中的 gamestate 作为明确降级。

  8. 返回上游结果、旧/新 token、完整新 decision state、warnings,并写动作日志。

decision state、state_token 与 0-based 索引

balatro_get_state(view="decision") 保留当前阶段、seed、deck、stake、ante、round、 Blind 目标分数/奖励(上游提供时)/特殊效果、分数、钱、bankrupt_at(上游提供时)、 剩余手数/弃牌数、胜负、手牌、Joker、消耗牌、voucher、商店、补充包、reroll 费用、槽位上限、可用动作、warnings 和 state_token

每张卡或物品都保留原始 BalatroBot 字段,并额外提供:

  • 当前 index

  • balatrobot_idkeylabel/name

  • description

  • ranksuit

  • enhancementeditionsealdebuff

  • buy_costsell_value

所有索引均为 0-based。任何状态改变后,手牌、商店、Joker、消耗牌和 Pack 的 旧索引立即失效。

state_token 使用 action-relevant 状态的规范化 JSON、稳定 key 排序和 SHA-256 生成。同一状态重复读取会得到相同 token;阶段、主要资源、手牌顺序、商店、 Joker、消耗牌或 Pack 改变都会换 token。

如果传入旧 token,工具返回 STALE_STATE、实际 token 和最新 decision state, 且不会执行上游写操作。正确处理方式是重新决策,不是盲目重试原动作。

开始或继续一局

推荐把下面整段交给 Codex:

请用 balatro MCP 玩小丑牌。先调用 balatro_health,再读取
balatro_get_state(view="decision")。如果已有一局,继续当前局,不要返回菜单,
不要开始新局覆盖它;如果状态是 MENU,则用 RED deck、WHITE stake 开始一局。
每次动作前都重新读取最新 decision state,只使用 available_actions 中允许的动作,
所有索引按 0-based,并把最新 state_token 作为 expected_state_token。每个写操作后
检查 new_state。不要盲目重试失败工具,不要跳过 Boss Blind;商店操作前检查钱和
槽位。进入 GAME_OVER 后停止操作,汇总 ante、round、胜负和关键 Joker。

如果只想继续、不允许开始新局,把其中 MENU 分支改为“若为 MENU,只报告当前没有 进行中的局,不要调用 balatro_start_run”。

常见错误

错误/现象

含义与处理

CONNECTION_FAILED

在独立终端运行 ./scripts/doctor_macos.sh,再运行 ./scripts/start_balatro_macos.sh --fast

UPSTREAM_TIMEOUT

确认游戏未卡死;动作结果未知时先读状态,绝不能重复写操作

STALE_STATE

使用错误附带的 latest_state 重新决策

INVALID_GAME_STATE

当前界面不允许该动作;读 balatro_available_actions

INDEX_OUT_OF_RANGE

状态已变化或索引错误;重新读取 decision state

DUPLICATE_INDEX

卡牌索引或排列有重复

INCOMPLETE_PERMUTATION

rearrange.order 必须包含区域的全部索引且只出现一次

INSUFFICIENT_MONEY / NO_FREE_SLOT

先卖出、选择其他物品或离开商店

BOSS_BLIND_CANNOT_BE_SKIPPED

必须选择并打 Boss Blind

12346 被占用

启动脚本会报出监听进程但不会杀进程;确认是否已有 BalatroBot

balatro 配置已存在

codex mcp get balatro 检查;确认后用移除脚本,再重新添加

/mcp 看不到新配置

完整重启 Codex 桌面端,并确认配置使用 .venv/bin 的绝对入口

更新 BalatroBot 后验证接口

  1. 阅读新 release 的 pyproject.tomlsrc/lua/utils/openrpc.jsonsrc/lua/utils/gamestate.luasrc/lua/endpoints/*.lua

  2. 更新 scripts/start_balatro_macos.sh 中的固定版本。

  3. 启动新版本后运行只读验证:

    ./scripts/verify_connection.sh
  4. 在 Codex 中调用:

    balatro_capabilities(refresh=true)
  5. 运行完整项目验收:

    uv sync
    uv run ruff check .
    uv run ruff format --check .
    uv run ty check
    uv run pytest

如果上游方法参数或状态发生变化,更新兼容表、action guard、工具说明、README 和 tools/list 测试后再允许游戏写操作。

当前上游差异与已知限制

实施时核对了 v1.5.2 和 main,而不是依赖旧教程。发现:

  1. BalatroBot package/release 为 v1.5.2,但 v1.5.2 内嵌 OpenRPC info.version 仍为 1.5.1;main 的相同文件写为 1.5.2。health 中的版本因此 明确标注来源为 rpc.discover.info.version

  2. 当前 rpc.discover 没有发布 endpoint 的 requires_state。项目以 v1.5.2 src/lua/endpoints/*.lua 的实际约束补齐,并在 capabilities 中标注来源。

  3. OpenRPC 的 State enum 没列出 SMODS_BOOSTER_OPENED,但实际 pack.lua 明确要求该状态;项目按运行中的实际 endpoint 名称处理。 同时,v1.5.1/v1.5.2 的 rpc.discover 漏列了实际已注册的 pack endpoint; 项目仅对这两个已核实版本使用 endpoint 兼容表,并在 capabilities 的 compatible_openrpc_omissions 中明确报告,不把它误报为缺失能力。

  4. v1.5.2 gamestate 没有显式暴露 bankrupt_at 或 Blind 奖励。decision state 在上游缺失时返回 null,不伪造数据;购买的最终合法性由 BalatroBot 决定。

  5. 消耗牌目标数量不是当前 OpenRPC 参数 schema 的一部分。项目只校验类型、唯一性 和索引范围,具体数量遵从描述和 BalatroBot 错误。

  6. view="full" 保留上游未知字段;decision 是面向决策的非破坏性字段重组,但不 承诺包含与动作无关的未来顶层字段。

  7. 这是控制接口,不负责安装 Mod,不使用 OCR、截图识别或鼠标坐标,也不在开发 验收中自动开始真实游戏。

日志

  • 动作日志:logs/actions.jsonl

  • 轮转:单文件约 2 MB,保留 3 个备份

  • BalatroBot 自身日志:上游默认 logs/<timestamp>/<port>.log

  • MCP 普通日志:stderr

  • MCP stdout:只含协议数据

动作日志只记录动作名、上游方法、参数形状/索引摘要、结果与 token;不会写环境变量、 完整状态或 seed 值。

移除 Codex MCP 配置

./scripts/remove_codex_mcp.sh

脚本会先显示即将执行的 codex mcp remove balatro,并且只移除名为 balatro 的 Codex MCP 配置。它不会删除项目、虚拟环境、BalatroBot Mod 或游戏存档。

安全边界

本项目绝不注册或转发以下 BalatroBot 能力:

  • add

  • set

  • load

  • save

  • screenshot

  • menu

同样不存在 execute_rawcall_method、任意 JSON-RPC、debugeval、改钱、 改分、生成 Joker、跳 Ante、强制胜利或加载 checkpoint 工具。这些名称不会出现在 tools/list

其他边界:

  • MCP 是 Codex 唯一的游戏控制入口。

  • 写 RPC 自动重试次数永远为 0。

  • 所有写操作共用一个 asyncio.Lock

  • 只读连接失败可以有限重试。

  • HTTP 客户端是单个可复用的 httpx.AsyncClient

  • 进程退出时关闭 HTTP client 和动作日志,不遗留阻止退出的后台任务。

  • 不修改 BalatroBot 上游源码。

  • 不修改 Balatro 存档。

  • 返回主菜单只能由用户直接在游戏界面操作。

  • GAME_OVER 后 instructions 要求停止动作并总结。

开发与测试

默认测试全部使用 httpx.MockTransport,不需要 Balatro 或 BalatroBot:

uv sync
uv run ruff check .
uv run ruff format --check .
uv run ty check
uv run pytest

测试覆盖连接拒绝、超时、HTTP/JSON/JSON-RPC 错误、ID 不匹配、discover 缓存、 unknown fields、decision view、稳定 token、stale 拒绝、索引与排列、参数转换、 写操作零重试、并发写串行化、危险工具缺失,以及 BalatroBot 离线时的真实 STDIO MCP 初始化和 tools/list

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Reasoning, code, anti-deception, memory harness MCP tools. Stdio or HTTPS api.ejentum.com/mcp

  • A paid remote MCP for OpenAI Codex agent coordination MCP, built to return verdicts, receipts, usage

  • A paid remote MCP for OpenAI Codex context compressor, built to return verdicts, receipts, usage log

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/deanxizian/balatro-codex-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server