trpg-dice-mcp
# TRPG 掷骰 MCP Server v2.0
密码学安全随机的 TRPG 掷骰服务器,支持完整骰子表达式引擎、多系统规则预设、暗骰保密。
## 快速开始
### 配置 MCP 客户端
在你的 MCP 客户端配置中添加:
```json
{
"mcpServers": {
"trpg-dice": {
"command": "npx",
"args": ["-y", "trpg-dice-mcp"]
}
}
}
```
### Windows 客户端
部分 Windows 环境需要:
```json
{
"mcpServers": {
"trpg-dice": {
"command": "cmd",
"args": ["/c", "npx", "-y", "trpg-dice-mcp"]
}
}
}
```
## 工具一览
| 工具 | 用途 | 示例 |
|------|------|------|
| `roll_dice` | 掷骰表达式求值 | `3d6+2`, `4d6kh3`, `d%`, `(8d6)/2` |
| `roll_table` | 随机表抽取(范围/权重/等概率) | 遭遇表、战利品表 |
| `roll_check` | 技能/属性检定 | CoC 7e、D&D 5e、PbtA、GURPS |
| `roll_pool` | 骰池检定 | Shadowrun、WoD、Year Zero |
| `roll_fate` | FATE 检定 | 4dF + 修正值 |
| `pick_random` | 随机抽取 | 先攻排序、抽牌 |
| `get_roll_history` | 查询历史 | 最近掷骰记录 |
| `reveal_hidden_roll` | 揭示暗骰 | 追溯查看之前暗骰的完整结果 |
| `opposed_check` | 双方对抗检定 | 技能对抗、先攻对抗 |
## 支持的骰子表达式
### 基本语法
| 表达式 | 含义 |
|--------|------|
| `3d6` | 掷 3 颗 6 面骰 |
| `1d20+5` | d20 + 修正 5 |
| `4d6kh3` | 4d6 取最高的 3 个(D&D 属性) |
| `2d20kl1` | 2d20 取最低的 1 个(劣势) |
| `3d6!` | 爆炸骰(出 6 追加一骰) |
| `1d6r2` | 重骰直到结果 > 2 |
| `(8d6)/2` | 8d6 结果除以 2(向下取整) |
| `floor(3d6/2)` | 同上,显式 floor |
### 特殊骰
| 记号 | 含义 |
|------|------|
| `d%` / `d100` | 百分骰(1–100) |
| `dF` | Fudge 骰(-1/0/+1) |
| `d66` | 查表骰(11–66,36 个离散值) |
### 修饰符
| 修饰符 | 含义 |
|--------|------|
| `khN` | 保留最高的 N 个 |
| `klN` | 保留最低的 N 个 |
| `dhN` | 丢弃最高的 N 个 |
| `dlN` | 丢弃最低的 N 个 |
| `!` | 爆炸(出最大值追加一骰) |
| `!!` | 复合爆炸(累计为单骰值) |
| `!>N` | 阈值爆炸(出 ≥N 追加) |
| `rN` | 递归重骰直到结果 > N |
## 规则预设
| 预设 | 系统 | 骰子 | 判定 |
|------|------|------|------|
| `coc7` | 克苏鲁的呼唤 7 版 | 1d100 | ≤ 技能 |
| `dnd5e` | D&D 5 版 | 1d20+mod | ≥ DC |
| `pbta` | Powered by the Apocalypse | 2d6+mod | 固定阈值 |
| `gurps` | GURPS | 3d6 | ≤ 技能 |
| `runequest` | RuneQuest | 1d100 | ≤ 技能 |
| `fate` | FATE | 4dF+mod | vs 难度 |
模型可通过 `rules://presets/{name}` 资源查阅详细判定规则。
## 安全性
- **随机源**:使用 `node:crypto.randomInt()`,密码学安全,无模偏差
- **暗骰**:`hidden: true` 时,文本和结构化响应均只返回保密回执;完整结果写入本地 JSONL 文件。文件未加密。
- **揭示控制**:暗骰揭示默认启用,GM 可通过 `reveal_hidden_roll` 工具回溯查看暗骰结果
## 响应与批量抽取
所有工具同时返回完整 JSON 文本和 `structuredContent`,其中 `summary` 是可读摘要。查询历史和揭示暗骰的明细也包含在文本响应中。
`roll_table` 的 `results` 包含每次抽取;顶层 `selected`、`roll` 等字段保留第一次结果。`unique=true` 表示同一选项最多选一次,权重模式按剩余权重抽取。等概率模式只需提供 `label`,无需构造骰子表达式。
`shared_subroll=true` 可让同一次调用中重复选中的条目共享其子掷骰结果,默认 false。子表的等概率/权重模式使用自身选项;范围子表沿用父表表达式。范围表必须显式传 `dice`,并完整覆盖值域,除非设置 `allow_gap=true`。
## 取整与检定
- 除法默认向下取整;`rounding` 只改变除法的取整方式,普通小数加减保留小数。
- 显式函数覆盖内部除法的自动取整,如 `ceil(5/2)=3`;函数内部先按原值计算,再对整个参数取整。
- PbtA 无需 `target`。CoC 奖励/惩罚骰共用个位,比较完整百分骰候选值,00 按 100 处理。
- 优劣势要求表达式中恰好有一组未修饰的 1d20;奖励骰要求恰好有一组未修饰的 1d100/d%。
- 自定义 `degrees` 按顺序首个命中生效,覆盖预设;条件支持 roll/total/target/margin、比较、四则运算、括号和取整函数,不支持三元表达式。无效条件明确报错。
- GURPS 等预设沿用规则资源中声明的简化实现。`tens_crit` 保留每颗 d10 骰出 10 额外加一成功的简化行为,不包含 V5 的完整暴击规则。
## 本地数据与并发
默认目录为 `~/.trpg-dice-mcp`,可通过 MCP 进程的 `TRPG_DICE_DATA_DIR` 环境变量指定其他目录。不同目录可以隔离不同跑团的历史。
- `roll-history.json`:持久化计数器和最近 1000 条历史;单次查询最多 50 条。历史查询不会产生新的掷骰记录。
- `hidden-rolls.jsonl`:暗骰完整结果和揭示事件,兼容旧版 JSONL 记录。暗骰日志不随普通历史裁剪。
- 多个新版进程共享目录时,文件锁保护读写与编号分配;进程异常退出后可回收过期锁。
- 新写入的普通历史不会保存暗骰结果;旧文件不自动清理。`reveal_hidden_roll` 是显式揭示工具,客户端仍需自行管理谁可以调用它。
表达式最多 200 字符、每组最多 500 颗骰;每次工具调用含批量、重骰及爆炸在内最多 5000 颗。单颗爆炸达到 100 次迭代会返回截断提示。随机表最多 200 项、批量最多 100 次、嵌套深度最多 3 层。
测试包含原有解析器/属性测试,以及规则回归、工具 schema、暗骰脱敏、历史分页和两个真实 stdio 进程共享存储。所有存储测试均使用独立临时目录。
打包会自动构建 `dist/`。修改源码后需重新连接 MCP;使用同一数据目录的旧版进程也应一并重启。完整变更见 [CHANGELOG.md](CHANGELOG.md)。
## 开发
```bash
npm ci
npm run typecheck
npm test
npm pack --dry-run
```
### 项目结构
```
src/
├── index.ts # stdio 入口
├── server.ts # MCP 工具注册
├── rng/ # 随机数核心(SecureRng / SeededRng)
├── dice/ # 表达式引擎(tokenizer/parser/eval/range/table)
├── rules/ # 规则预设 + degrees DSL
├── resources/ # MCP Resources(规则速查)
├── state/ # 历史记录 + 暗骰存储
├── tools/ # 9 个 MCP 工具
└── utils/ # 格式化 / i18n
```
## 许可
MIT
TDQS
Scored across 9 tools
Each tool targets a distinct aspect of TRPG rolling: basic dice expressions, tables, skill checks, dice pools, FATE dice, arbitrary selection, history, hidden roll reveal, and opposed checks. No two tools have overlapping purposes, and the descriptions clarify niche uses like d66 or nested triggers.
All tool names follow a clear verb_first_noun pattern in snake_case (roll_dice, roll_table, pick_random, get_roll_history, reveal_hidden_roll). The roll_* prefix is used for dice-related tools, with only opposed_check deviating slightly but still readable and consistent in style.
9 tools is well-scoped for a TRPG dice server, covering the core surface without bloat. Each tool serves a distinct gameplay need, from basic rolls to history management, making the count appropriate.
The tool set covers the full life cycle of dice rolls: rolling (multiple types), evaluating checks/pools, handling tables, tracking history, revealing hidden rolls, and even opposed checks. Missing operations like clearing history or editing rolls are not essential for the domain, so the surface feels complete.