Skip to main content
Glama

bot-game-mcp

一个遵循标准 MCP(Model Context Protocol) 的 QQ 群聊桌游引擎,内置狼人杀、谁是卧底、大话骰和数字炸弹四款游戏。

  • 程序主导:座位、身份、词语、骰子、发言顺序、阶段流转、超时托管、结算和胜负,全部由引擎里的程序决定。

  • AI 裁判只负责推进:裁判由程序抽签选出,只做三件事——把程序给的消息原样发到群里、通过私聊把身份发给真人、把真人的发言转交给程序。它看不到 AI 玩家的身份,也不能改任何结果。

  • 两种玩法:可以全员都是 bot,也可以 bot 和真人同桌。真人在群里或私聊发「投3」「验5」「过」这样的自然语言,由程序解析。

  • 兼容主流 agent:支持 Streamable HTTP、旧版 HTTP+SSE 和 stdio(含桥接模式),能接入 Claude Code、Claude Desktop、Cursor、Cherry Studio、OpenAI Agents SDK,以及各类支持 MCP 的 QQ bot 框架。

flowchart LR
  subgraph QQ["QQ 群 / 私聊"]
    H["真人玩家"]
    A["AI 玩家 bot"]
    R["AI 裁判 bot<br/>(程序抽签产生)"]
  end
  E["bot-game-mcp 引擎<br/>身份 · 流程 · 结算 · 胜负"]
  H -- "群消息 / 私聊裁判" --> R
  R -- "relay_human_message(原文转交)" --> E
  E -- "referee_step → 待发消息" --> R
  R -- "发群消息 / 私聊发身份" --> H
  A <-- "get_my_view / speak / act" --> E

目录

更多文档:游戏规则与选项 · MCP 接口参考 · 接入各类客户端与 QQ 框架 · 架构与新增游戏 · 开发进度与测试记录

Related MCP server: gap

游戏

类型

名称

人数

简介

werewolf

狼人杀

6~16

狼人夜里刀人,好人白天发言投票。角色有预言家、女巫、猎人、守卫和白痴,6~12 人有预设板子,也可以自定义。

undercover

谁是卧底

4~12

每人只拿到一个词,卧底的词和大家的相近但不同,没人知道自己是不是卧底。内置 250 组词。

liars_dice

大话骰

2~8

每人摇骰藏着,轮流叫「N 个 F 点」,不信就开。1 点可以当任意点数,叫错的人扣命。

number_bomb

数字炸弹

2~20

轮流猜数,范围越缩越小,猜中炸弹就爆炸。规则简单,适合暖场。

完整规则、开局选项(create_game 的 options)和给 AI 玩家的提示见 docs/GAMES.md。运行时也能用 get_rules 工具或 botgame://rules/{game_type} 资源查看。

快速开始

需要 Node.js 22 或更高版本。

1. 安装与构建

git clone https://github.com/Gengetau/bot-game-mcp.git
cd bot-game-mcp
npm ci
npm run build
npm link            # 可选:之后可以直接用 bot-game-mcp 命令,否则用 node dist/cli.js

2. 先离线看一局(不需要任何 agent)

# 9 人狼人杀,其中 2 名「真人」,程序用随机策略代打,并按 QQ 消息的样子打印整局过程
bot-game-mcp simulate werewolf --players 9 --humans 2

bot-game-mcp simulate undercover --players 6 --humans 1 --seed 7   # 固定种子,结果可复现
bot-game-mcp simulate liars_dice --players 4 --cq                  # 消息输出成 CQ 码格式

模拟器会把真人的操作写成自然语言(「投3」「刀5」「过」……),交给与线上相同的解析逻辑处理。输出示例:

💬 [群] 🎲【狼人杀】对局 WW-CVVX 开始!
    本局裁判:裁判(AI,由程序抽签产生,只负责推进流程,不参与游戏、不决定任何结果)
    ...
🔒 [私聊 → 真人1] 🎴 你的身份是【猎人】(好人阵营)。
    技能:被狼人刀杀或被放逐出局时,可开枪带走一名玩家;被女巫毒死则不能开枪。
💬 [群] 🌙 第1夜降临,天黑请闭眼。有夜间能力的玩家请行动(限时 60 秒)。
💬 [群] ☀️ 第1天,天亮了。昨夜死亡的玩家:2号 AI-4、5号 AI-7。
...
💬 [群] 🏁 游戏结束!获胜方:好人阵营

3. 启动引擎

bot-game-mcp init-config     # 生成 botgame.config.json,里面已经填好随机密钥
# 编辑 botgame.config.json:把 agents 里的 id/name 改成各个 bot 的 QQ 号和昵称
bot-game-mcp serve           # 默认监听 http://127.0.0.1:7700/mcp

每个 bot(无论将来当玩家还是裁判)在 auth.agents 里各占一行。它的身份由密钥决定,不能冒充别人。只想在本机试玩的话,也可以不写配置直接 bot-game-mcp serve,这时是 open 模式,agent 调用 login 工具认领 QQ 号即可。

4. 把 agent 接上来

以 Claude Code 为例:

claude mcp add --transport http bot-game http://127.0.0.1:7700/mcp \
  --header "Authorization: Bearer <这个 bot 的密钥>"

只支持 stdio 的客户端可以用桥接模式(bot-game-mcp bridge --url … --key …)。其他客户端和 QQ 框架的接法见 docs/CLIENTS.md,配置样例在 examples/。

给 agent 的系统提示词可以直接用 MCP prompt:裁判用 referee,玩家用 player(也可以读取资源 botgame://guide/referee、botgame://guide/player)。

一局游戏是怎么跑起来的

分工

事项

谁负责

座位、身份、词语、骰子、炸弹数字

程序(crypto.randomInt)

谁当裁判

程序抽签:优先选报名为 referee 的 AI,否则在报名为 either 的 AI 里随机选

发言顺序、阶段流转、限时、超时托管

程序

投票、技能、出价的结算和胜负判定

程序

把消息发到群里、私聊给真人发身份和提示

AI 裁判(原样转发 referee_step 返回的消息)

把真人在群里或私聊里说的话交给程序

AI 裁判(relay_human_message,原文转交,由程序解析)

AI 玩家查看自己的身份、发言、行动

AI 玩家(get_my_view / speak / act,直接和程序交互)

AI 玩家的私密信息只出现在它自己的 get_my_view 里,不经过裁判。真人没法调用工具,所以真人的身份和夜间提示由程序生成好,再交给裁判私聊发出。

流程

  1. 开房:某个 bot 调用 create_game(game_type, group_id),把返回的 group_message 发到群里。

  2. 报名:其他 bot 调用 join_game,可以选择当玩家(player)、只当裁判(referee)或都行(either)。真人在群里发「加入」,由已报名的 AI 用 relay_human_message 转交;也可以直接用 add_human_player 登记。

  3. 开局:房主调用 start_game。程序抽签选出裁判,随机排座位、发身份。

  4. 裁判循环:裁判反复调用 referee_step(wait_seconds=25)。拿到 deliveries 后按顺序发送:to=group 的发到群里,to=private 的私聊给对应的真人。期间收到的每一条真人消息(群聊和私聊都算)都用 relay_human_message 转交。直到返回 finished=true 为止。

  5. AI 玩家循环:AI 玩家反复调用 get_my_view(wait_seconds=50),轮到自己时再调用 speak 或 act。可用的动作和参数都在返回的 todo.actions 里。

  6. 结算:程序公布胜负和所有人的身份。之后任何人都能用 get_game_log 查看完整复盘。

sequenceDiagram
  participant H as 真人玩家
  participant R as AI 裁判
  participant E as 引擎(程序)
  participant A as AI 玩家
  R->>E: referee_step(wait_seconds=25)
  E-->>R: deliveries:开局公告 + 给真人的身份私聊
  R->>H: 私聊「🎴 你的身份是【预言家】……」
  A->>E: get_my_view(wait_seconds=50)
  E-->>A: you:狼人;todo:选择今晚刀谁
  A->>E: act({"action":"kill","target":3})
  H->>R: 私聊「验5」
  R->>E: relay_human_message(qq_id, "验5", channel=private)
  E->>E: 收齐行动或超时托管,然后结算
  R->>E: referee_step
  E-->>R: 「🔍 5号是好人」(私聊)、「☀️ 天亮了……」(群)
  R->>H: 依次发出

纯 bot 与人机混玩

  • 纯 bot:所有玩家都是 AI。裁判照样把公开消息发到群里,群友可以围观。如果完全不需要往 QQ 发消息(比如做 agent 对战测试),开房时加 auto_referee: true,程序会自己推进。

  • bot + 真人:真人发「加入」报名。开局后,裁判私聊发身份;真人在群里发言、投票,夜间行动则私聊裁判。到了限时还没行动的玩家由程序托管(弃票、跳过,或按该游戏规则随机行动)。

  • 谁替 AI 玩家发言:AI 玩家报名时 self_post 默认为 true,speak 的结果会带上 post_to_group,由它自己把发言发到群里。设为 false 时,改由裁判以「【3号 小克】……」的格式代发。

真人可以发的指令(节选)

游戏

例子

通用

发言结束:过、说完了;报名:加入、退出

狼人杀

投票:投3、弃票;夜间私聊裁判:刀3、验5、守2、救、毒4、不用;猎人:开枪3、不开枪

谁是卧底

描述直接在群里说,说完发 过;投票:投3

大话骰

叫数:4个6、五个三;开骰:开

数字炸弹

50、我猜 37

座位可以写成 3、3号、三号、@昵称 或 QQ 的 @。具体以裁判私聊和群里的提示为准,提示里会写明当前能用的指令。

MCP 接口一览

17 个工具,全部带有 readOnlyHint、destructiveHint 等注解。业务错误会以 isError: true 的工具结果返回,并附带中文原因和下一步建议。

分类

工具

身份

login(open 模式认领 QQ 号)、whoami

大厅

list_games、get_rules、create_game、join_game、add_human_player、leave_game、start_game、abort_game

玩家

get_my_view(支持长轮询)、speak、act、get_game_log

裁判

referee_step(推进 + 取待发消息,支持长轮询)、relay_human_message、referee_takeover

此外还有:

  • 资源:botgame://guide/overview、botgame://guide/referee、botgame://guide/player、botgame://rules/{game_type}。

  • 提示词:referee、player。

参数说明见 docs/TOOLS.md。这份文件由代码生成,与实现保持一致。

referee_step 的消息可以选三种格式:text(纯文本,附 mentions 列表)、cq(CQ 码字符串)、onebot(OneBot v11 消息段数组,可以直接交给 send_group_msg 或 send_private_msg)。

配置

配置文件按这个顺序查找:--config 参数、环境变量 BOTGAME_CONFIG、当前目录下的 botgame.config.json。示例见 examples/botgame.config.example.json。

字段

默认值

说明

host

127.0.0.1

监听地址。要对外开放时请配合 allowedHosts 和 HTTPS 反向代理

port

7700

端口

path

/mcp

Streamable HTTP 端点

allowedHosts

—

Host 头白名单,用于防范 DNS rebinding。监听 0.0.0.0 时建议配置

legacySse

true

是否开启旧版 HTTP+SSE 传输(/sse + /messages)

publicApi

true

是否开启只读观战接口 /api/games、/api/games/:id。对局结束前只返回公开记录

stateFile

./data/botgame-state.json

存档文件,重启后对局会继续。设为 null 则只存在内存里

auth.mode

有 agents 时为 keys,否则为 open

keys:必须带密钥;open:用 login 认领 QQ 号

auth.agents[]

[]

{ key, id, name, admin? },每个 bot 一个密钥

auth.adminKeys

[]

管理员密钥,可以中止任意对局

refereeStaleSeconds

120

裁判失联多少秒后,候补裁判可以用 referee_takeover 接管

lobbyTtlMinutes

120

报名阶段超过这个时间自动关闭

idleGameTtlMinutes

360

进行中的对局闲置多久后自动中止

sessionIdleMinutes

30

HTTP 会话闲置多久后关闭

seed

—

固定随机种子,只用于测试复现,生产环境不要设置

可以用环境变量覆盖:BOTGAME_HOST、BOTGAME_PORT、BOTGAME_STATE_FILE(设为空字符串表示只用内存)、BOTGAME_AUTH_MODE、BOTGAME_ADMIN_KEY、BOTGAME_SEED。stdio 模式用 BOTGAME_AGENT_ID、BOTGAME_AGENT_NAME、BOTGAME_AGENT_ADMIN=1 指定身份;桥接模式可以用 BOTGAME_URL、BOTGAME_KEY 代替命令行参数。

密钥可以三种方式携带,任选其一:Authorization: Bearer <key>、X-API-Key: <key>、URL 参数 ?key=<key>。URL 参数主要是给只能填地址的旧 SSE 客户端用的。

命令行

bot-game-mcp [serve] [--config 文件] [--host 地址] [--port 端口] [--state 文件 | --no-state]
bot-game-mcp stdio   [--agent-id QQ号 --agent-name 昵称] [--state 文件 | --no-state]
bot-game-mcp bridge  --url http://主机:7700/mcp [--key 密钥]
bot-game-mcp simulate <游戏> [--players N] [--humans N] [--seed S] [--options JSON] [--afk 0.1] [--cq]
bot-game-mcp gen-key [-n 3]
bot-game-mcp init-config [--force]

安全与公平

接入安全

  • 默认只监听本机。要对外开放时,建议使用 keys 模式,在前面加一层 HTTPS 反向代理,并配置 allowedHosts。

  • keys 模式下,身份由密钥决定,比较时使用常数时间算法。同一个 MCP 会话中途换密钥会被拒绝(403)。

  • open 模式下,第一次 login 某个 QQ 号会返回一个 secret,之后在别的会话登录这个号就必须带上它。存档里只保存 secret 的哈希。这个模式适合本机或可信的小群。

  • 请勿把密钥提交到仓库。botgame.config.json 和 data/ 已在 .gitignore 中。

游戏公平

  • 身份、词语、骰子和炸弹数字都用 crypto.randomInt 生成,座位默认也随机打乱。

  • 每个 AI 只能看到自己座位的私密信息。裁判的视角里没有身份,只有流程信息。

  • 真人座位的私密信息只通过裁判私聊发给本人。即使有人用真人的 QQ 号连上 MCP,也只能看到公开信息;open 模式下也不能认领正在参赛的真人 QQ 号。

  • 需要保密的阶段(例如夜晚)不会公布谁还没行动,并且设有最短时长(狼人杀默认 20 秒),防止有人从「这个阶段结束得多快」推断出神职是否还活着。狼人杀的女巫阶段只要板子里有女巫就每晚都开,不会因为女巫死了而跳过。

  • 程序在超时托管时只用该玩家自己能看到的信息。

  • 裁判用 relay_human_message 的 action 参数替真人提交结构化指令时(只在文字识别失败但意思明确时使用),程序会私聊告诉这位真人具体提交了什么,方便当事人监督。

  • 玩家的发言和昵称在拼进消息之前会先清洗,使其中的 CQ 码和内部 @ 占位符失效,所以不能借发言 @ 全体成员或冒充程序消息。

  • 只有候补裁判(或管理员)才能接管失联的裁判,程序自动主持的对局不能被接管。

  • 游戏正常结束后,完整复盘(含所有私密信息)对所有人公开,可以事后核对。中止的对局不公开私密记录。

已知限制

  • 裁判能看到发给真人的私聊。 真人的身份和夜间结果是通过裁判 bot 私聊发出的,所以裁判 bot 能看到这些内容,比如真人狼人收到的狼队友名单。裁判一定不是本局玩家,指南也明确要求它不得泄露。如果对公平要求更高,建议准备一个专门的 bot,以 join_as: "referee" 报名当裁判,不让它参赛。

  • QQ 私聊有条件。 真人需要先加裁判 bot 为好友,或者所用的 QQ 框架支持群临时会话,否则发不出私聊。开局前请在群里提醒大家。

  • 一个群同时只能有一局。

  • 报名超时关闭时不会通知群里。 报名阶段还没有裁判,没人能发消息,所以报名超时(默认 2 小时)不会在群里公告。进行中的对局被中止时,会由裁判发出公告。

  • 狼人杀连续 6 个昼夜无人死亡判为平局。 这是为了防止对局卡死。

  • 只支持单实例部署。 引擎是单进程,状态存放在一个 JSON 文件里,适合一台机器服务若干个群。

开发

npm run typecheck     # 类型检查(含测试代码)
npm test              # 单元测试 + 集成测试(含 HTTP、SSE、桥接端到端)
npm run build         # 编译到 dist/
npm run docs          # 根据代码重新生成 docs/GAMES.md 和 docs/TOOLS.md
npm run dev -- serve  # 用 tsx 直接运行源码
npm run simulate -- werewolf --players 12 --options '{"win_mode":"all"}'
src/
  core/        引擎核心:类型、BaseGame 基类、GameManager(大厅/阶段/投递/长轮询/裁判)、随机数、文本解析、存档
  games/       werewolf/ undercover/ liars-dice/ number-bomb/,以及注册表 index.ts
  mcp/         MCP 服务器:工具、资源、提示词、认证、消息渲染(text/CQ/OneBot)、指南文本
  server/      传输层:HTTP(Streamable HTTP + 旧版 SSE + 观战 API)、stdio、bridge、运行时
  sim/         离线模拟器
  cli.ts       命令行入口
test/          vitest 测试
scripts/       文档生成脚本
docs/          文档
examples/      配置与客户端样例

新增一款游戏只需要继承 BaseGame,实现 start、onAction、advance 和两个视图方法,再在 src/games/index.ts 里注册即可。详见 docs/ARCHITECTURE.md。

许可证

MIT

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    B
    maintenance
    MCP server that bridges multiple AI agents for unified local chat, supporting private messages, chat rooms, role queues, and broadcast with fixed identities and rate limiting.
    14
    1
    -
  • A
    license
    A
    quality
    C
    maintenance
    Enables any local AI agent to play turn-based games over MCP by exposing reset, observe, and act verbs with structured observations and validated legal actions.
    6
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI models and human players to play tic-tac-toe together through MCP, with server-enforced rules, turn-based waiting, and live board state via tools, resources, and prompts.
    MIT