dmcheck-mcp

dmcheck-mcp

MCP server for refereeing tabletop RPG sessions by analyzing transcripts against a configurable charter, providing deterministic findings on rule violations like unanswered questions or unacknowledged dice rolls.

Category
访问服务器

README

dmcheck

Deterministic conduct verdicts for live tabletop sessions — CI for running a game.

Feed it a session transcript (and optionally an engine event ledger) plus a table charter, and it returns named findings — the player whose question was never answered, the dice roll nobody acknowledged, the turn that began without anyone being told, the spoiler that leaked into the channel, the five-minute dead air. Every finding cites the charter rule it violates, with the evidence attached.

Cold-boot probe (2026-07-24): a fresh agent session given only this repo URL installed and refereed a session in 2 commands, verified all three exit-code legs against the docs, and confirmed the no-false-accusation contract held (a consumed roll produced silence). Its friction notes shipped as 0.1.1 (--dice-bot, dmcheck charter).

The design contract: a false accusation is the unforgivable bug. A rule fires only when the transcript provably shows the violation — ambiguity produces silence, never noise. The verdict path is model-free and deterministic: same transcript, same findings, every time.

30 seconds to a refereed session

$ pip install dmcheck          # stdlib only, no dependencies
$ dmcheck run session.jsonl --gm "Greta"
{
 "messages": 9,
 "findings": [
  {"rule": "R2", "summary": "unconsumed-roll: a dice result was never followed by any GM message",
   "charter": "roll_ack_within_messages=4",
   "detail": "dice result from DiceBot never followed by a GM message",
   "evidence": {"index": 6, "author": "DiceBot", "content": "Bram rolls 1d20+4: [18] = 22"}},
  ...
 ],
 "counts": {"R1": 1, "R2": 1, "R6": 1, "R7": 1, "R8": 1}
}

Transcript formats: JSONL of {ts, author, content}, or a JSON array of Discord-API-shaped messages ({timestamp, author: {username}, content}) in either order.

The rule set (each one paid for by a real table failure)

Rule Fires when Origin story
R1 a player's question got no GM response within threshold a player asked the DM a lore question; another player ended up answering
R2 a dice result was never followed by any GM message "did I hit?" — a player's successful attack roll sat unacknowledged
R3 an engine event was never narrated to the table the state engine resolved a hit the table never heard about
R4 a turn began and the GM never addressed the actor by name "isn't it her turn?" — asked by a player, which is one player too many
R5 someone acted out of initiative (needs the ledger) engine rejected it silently; the table never knew
R6 a configured hidden term appeared in a GM message a module's secret state names leaked into narration
R7 GM dead air beyond threshold while a player waited 30 seconds reads as thinking; five minutes reads as absence
R8 the session ended with open R1–R3 findings in its tail sessions should end in a defined state — that's what makes the next one possible

These came from running a hybrid table — human and AI players, an AI GM — on Discord, where every one of these failures actually happened and got codified the same week. They apply equally to human GMs: run dmcheck over your own exported game log and see what your table's transcript says.

Live mode (0.2): the referee sits AT the table

dmcheck watch runs the same engine over a growing session — stdin JSONL or a tailed file — and emits lifecycle events: OPEN when a violation becomes provable (thresholds fully elapsed; no predictions, ever), RESOLVED when a living condition heals (the engine event finally got narrated). --notify-cmd fires your own hook per OPEN finding — dmcheck itself never posts anywhere. At session end a closed-mode pass runs, so watch's final state provably equals dmcheck run on the full transcript (tested).

$ your-chat-fetcher | dmcheck watch - --gm "Rob" --notify-cmd 'notify-dm.sh'
{"event": "open", "rule": "R2", "detail": "dice result from RollBot never followed by a GM message", ...}
{"event": "resolved", "rule": "R3", ...}
{"event": "session_end", "open": ["R1"], "open_count": 1}
$ dmcheck explain R2            # the rule, its charter knobs, and the table failure that earned it
$ dmcheck lint-charter my.json  # unknown keys / bad thresholds refuse loudly

The point of live: every failure the rules encode was recoverable in the moment it happened — the unanswered question, the stale roll, the missing cue all had a seconds-wide window where a nudge saved the beat. Post-hoc tells you what went wrong last night; watch taps the GM's shoulder before the player feels it.

The charter is config, not code

charters/default.json ships thresholds and conventions derived from a real table's protocol. Override any of it — cue conventions, dead-air tolerance, dice-bot names, hidden-term lists — and version it. A league or organized-play program could publish a charter the way they publish a player's guide; dmcheck then referees any table against it.

$ dmcheck run session.jsonl --charter our-table.json --ledger events.jsonl
$ dmcheck rules            # the rule set with definitions
$ dmcheck charter          # print the effective charter — copy, edit, version it
$ dmcheck run session.jsonl --gm "Rob" --dice-bot "RollBot"   # quick overrides, no file needed
$ dmcheck --schema         # machine-readable I/O contract

For agents

  • tool.json at the repo root; --schema; exit codes: 0 clean · 1 findings · 2 charter/input unusable.
  • MCP server: dmcheck-mcp (stdio) with tools run and rules.
  • Findings are structured JSON with rule id, charter citation, human-readable detail, and an evidence span — built to be consumed by a GM agent that fixes its own procedure between beats.

What it does NOT do (on purpose)

  • No rules adjudication — whether the attack was legal is srdcheck's job.
  • No character math — that's charactercheck. (srdcheck judges the rules, charactercheck derives the actor, dmcheck referees the table.)
  • No narrative-quality judging — whether the prose was good is taste, and taste is not checkable. dmcheck checks procedure only.
  • No model calls, no scores — deterministic findings per rule, never a blended "DM grade."

Credits

The rule set was distilled from live hybrid (human + AI) table sessions; the Router+Detector pattern in native-gaming-harness independently converged on the same idea, which we take as evidence it's the load-bearing piece. dmcheck is game-system-agnostic and unaffiliated with any publisher.

<!-- MCP registry ownership marker (do not remove): binds this repo's PyPI package to its registry namespace. --> mcp-name: io.github.chaoz23/dmcheck

Bootstrap a new table (v0.3)

dmcheck init charter.json --gm YOUR-NAME

Writes a starter charter (versioned, effective-dated, lint-clean by construction) and prints the session-zero checklist S1–S8 — including S3c: sheet accountability is declared out loud at session zero, then settlement quizzes are graded silently. The referee that judges your table also hands you its constitution.

Per-seat cue policy (R4, hardened). Agent seats behind mention-gated transports (e.g. Discord allowBots="mentions") never receive name-in-prose cues. Declare it:

"seats": {"Shalia": {"cue_requires_mention": true, "mention": "<@1493...>"}}

R4 then counts a cue only if the literal mention string is present. Origin: a live session where "Shalia — you're up" was posted, looked like a cue, and was provably undeliverable — R4 passed on it. Never again.

Ledger format (the declared standard). dmcheck's ledger is JSONL: {ts, type: turn|act|event, actor, text} — one line per engine event. No lightweight OSS session-ledger existed when we surveyed (2026-07-26), so this format is the interchange standard our stack shares: engines tap their logs into it; run, watch, and settlement all consume it.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选
mcp-server-qdrant

mcp-server-qdrant

这个仓库展示了如何为向量搜索引擎 Qdrant 创建一个 MCP (Managed Control Plane) 服务器的示例。

官方
精选