{
  "markdown": "# srdcheck\n\n**A shared rules rail for agents: named, cited checks with explicit boundaries,\nso every caller can use the same deterministic result without mistaking a\npartial check for global legality.**\n\nMachine verdicts over specific rules of the System Reference Document 5.2.1:\ncited when a rule is applied, reproducible, offline, and honest enough to refuse\nquestions outside the shipped scope. The rules lawyer for agents — including an\nagent acting as the authorized DM.\n\n**Agents start here → [SKILL.md](SKILL.md)** — the front door: when to call this, worked examples, MUST/MUST NOTs. Family contract: [FAMILY.md](FAMILY.md).\n\n> **Status: v0.9.0 alpha — young but real, building in the open.** The kill tests that shaped the product — including the one that killed half our original idea — are in [eval/RESULTS-phase0.md](eval/RESULTS-phase0.md); the with/without-rails demo is in [demo/mage-hand/](demo/mage-hand/); the truth scorecard below is generated by CI.\n\nRuntime and operating-system guarantees are defined in the [support matrix](docs/support-matrix.md): Python 3.10–3.13, a full Ubuntu suite, and explicit installed-artifact smoke contracts on Windows and macOS.\n\n## Why this exists\n\nA game increasingly runs not as one model but as *several agents sharing one evolving state* — a GM, player agents, a rules referee, tool-callers. The moment more than one mind adjudicates, the binding problem stops being any single agent's knowledge or attention budget and becomes **consistency**: five capable models will each read the SRD and rule on grapple, concentration, or a death save a little differently, and the shared game state quietly desyncs. No amount of individual intelligence guarantees they agree with *each other*, and every re-derivation is another chance to drift. The fix is a deterministic rail they all call — the same [atoms](docs/atom-concordance.md), the same citations, the same verdict every time — so every applied-rule result carries one provenance any agent (or a human) can audit. Table rulings retain separate ruling lineage. That is where srdcheck stops being a convenience and becomes load-bearing.\n\nEven at a table of one, the rail earns its place. A model running a game is a brilliant improviser with a finite attention budget: every mechanical micro-check it handles in-context — *is this legal, is that slot spent, does the reaction refresh this round* — spends tokens and attention that belong to the only work that needs a mind, the story. And the checks a model *can* answer, it cannot **prove**, cannot **reproduce**, and — as our own benchmark showed — will not **refuse** when the question is outside the rules' jurisdiction.\n\nWe tested this before building. Frontier models answered our SRD rules questions nearly perfectly — and confidently ruled on house rules, GM discretion, and content that doesn't exist in the SRD, where the only correct answer is \"not my call.\" Small local models got 19–30% wrong with zero refusals. So srdcheck does not compete with what models know. It is a rail: structured facts in, a deterministic scoped result out, with citations whenever it applies a rule — and the *same* rail for every agent at the table.\n\n## What it is\n\nsrdcheck answers named, bounded questions such as: *does this proposal pass the\nmodeled action-economy check?* and *which modeled budget option kinds remain?*\nSee the generated [capability and claim map](docs/capability-map.md) for the\ncanonical checked and unchecked scope of every tool.\n\n- **Verdicts, not vibes.** Exit code `0` = passes the checked scope, `1` =\n  conflicts with the checked scope, `2` = cannot adjudicate. Every applied rule\n  carries its SRD citation; boundary refusals do not invent citations.\n- **Scope and provenance travel with the verdict.** Verdict schema 4.0 keeps\n  `coverage_level`, `checked_scope`, `unchecked_scope`, and `assumptions` on\n  every result and separately reports asserted/consumed/derived/missing facts,\n  the advisory `rule_result`, any scoped DM `table_decision`, and explicit\n  `state_mutation`. Every legal explanation says it is legal only within that\n  checked scope.\n- **Judge, never simulate.** No dice, no narration, no owned game state. State comes in with the query; a verdict goes out. The kernel is a stateless pure function — embeddable in anyone's DM product, VTT, or agent.\n- **State commits fail closed.** `event.apply` emits an idempotent transition\n  proposal bound to the exact evaluated state; `transition.commit` rejects a\n  stale/out-of-order proposal and returns the same semantic receipt on retry.\n  The agent-DM or host still performs the atomic state write. See\n  [safe state transitions](docs/state-transitions.md).\n- **Agent-DM rulings persist without hidden state.** Supply a portable table-policy\n  manifest and request/encounter/session/campaign IDs to existing query tools.\n  Matching rulings apply automatically, remain distinct from the SRD result,\n  and carry explicit table-authority lineage. See\n  [table policies](docs/table-policies.md).\n- **Deterministic and fast.** No LLM call anywhere in the verdict path. Runs local and offline.\n- **Observable without recording the table.** Opt-in metadata-only lifecycle\n  events carry request/verdict IDs, versions, refusal class, and timing on\n  stderr or a caller sink. Raw prompts, state, rulings, citations, and error\n  messages are excluded by contract; SRDCheck persists nothing.\n- **For agents first.** MCP + CLI, `--pipe`, `--schema`, `tool.json` at the repo\n  root. Humans get plain-English *why* in the same payload; agents treat that\n  prose as explanatory, not contractual.\n\n- **Rulesets are adapters.** The kernel knows no game; all rule content loads from adapter packages, each carrying its own provenance manifest — source document, hash, license, attribution — that every applied-rule result cites through. The SRD 5.2.1 adapter ships in this repo as the reference implementation. Anyone can build an adapter for another ruleset — a community, a private table, or a publisher shipping a first-party adapter for their own IP — and their content never passes through this project. The adapter catalog points; it never hosts.\n\nSee [docs/product-truths.md](docs/product-truths.md) for the invariants this\nproject holds itself to, [docs/anatomy-of-a-turn.md](docs/anatomy-of-a-turn.md)\nfor executable-today versus target examples, and\n[docs/compatibility-policy.md](docs/compatibility-policy.md) for the N/N-1\nmachine contract and correction policy.\n\nMaintainer and acquisition diligence lives in the\n[takeover inventory](docs/TAKEOVER.md), with linked architecture, release,\nincident-response, and support runbooks. Unchecked takeover items are explicit\ngaps, not implied readiness.\n\n**Show your work.** A big context window can *read* the SRD; srdcheck's value is the layer above — a consistent, cited set of rule atoms and a shared schema that several agents can rely on without each re-deriving the rules into context and drifting apart. [`docs/atom-concordance.md`](docs/atom-concordance.md) is the audit trail for that layer: every rule the engine applies, mapped to the exact SRD text it's grounded in (forward and inverse), generated and CI-checked-fresh, with a verbatim-citation oracle proving each quote really is on its cited page. A machine-readable [`atom-concordance.json`](docs/atom-concordance.json) is the slim index an agent can load to know what the rail covers and where it came from.\n\n## What srdcheck does not check yet\n\nHonesty is the product (truth T8), so the boundaries are stated, not implied. The current SRD adapter covers combat-turn fundamentals; it does **not** yet check:\n\n- **Feature prerequisites.** `turn.plan` judges the turn's *action economy* — that you spent at most one action, one bonus action, one reaction, one spell slot. It does not verify that a feature actually grants a given action. A lone two-weapon-fighting offhand attack is \"action-economy legal\" even though the 2024 rules require the Attack action first; that prerequisite lives in the character's features, which this version doesn't model. The success message says so explicitly.\n- **Per-spell effects.** Damage/HP, death saves, and saving throws are now modeled (the reducer folds `damage`/`heal`/`death-save`; `save.check` and `concentration.check` resolve caller-rolled saves), but *what a given spell does* — Fireball's 8d6, Hold Person's paralysis on a failed save — is the long-tail swamp and stays refused. srdcheck computes the save; it does not roll the dice or apply the spell's bespoke effect.\n- **Condition coverage is surface-specific.** All 15 SRD conditions are\n  registry-anchored and classified clause by clause, while each query claims\n  only the effects it actually consumes: attack modifiers, modeled action\n  economy and Speed, selected save/check effects, damage typing, immunity, and\n  Reaction blocking through Incapacitated and its definitional embeds. The\n  [completeness oracle](tests/test_condition_completeness.py) proves its named\n  attack/turn surfaces; it does not imply that every condition clause is checked\n  by every tool. Positional geometry, initiative order, and stealth/perception\n  contests remain explicit boundaries.\n- **Content outside the SRD 5.2.1** — anything not in the SRD returns exit 2 from `jurisdiction`; in adapter 0.2.1 the name registries cover spells, creatures, conditions, **classes, subclasses, species, feats, and backgrounds** (census-anchored against the source text in CI). Background coverage is jurisdiction-only: it recognizes the four backgrounds actually present in SRD 5.2.1 (Acolyte, Criminal, Sage, and Soldier) but does not yet expose their mechanics as structured facts.\n- **Misspelled or unknown query fields refuse loudly** (adapter 0.2.1): every query validates its params against the declared schema — an unrecognized field returns exit 2 naming the offender, never a silently-defaulted verdict. A drift oracle in CI keeps handlers and schemas from ever diverging again.\n- **Facts are requested only while they can change the result.** A granted Mage\n  Hand use refuses with `missing-fact` until its relevant distance and, when it\n  carries or manipulates an object, weight are supplied. A prohibition or an\n  already-exceeded limit is decisive and does not trigger an irrelevant repair\n  loop. A `turn.plan` move requires explicit `feet`; omission is never treated\n  as a zero-foot move.\n\nNonsensical inputs (negative Speed, a 99th-level spell, exhaustion past 6) return exit 2 rather than a confident-looking answer. When in doubt, srdcheck refuses — a wrong verdict is the only unforgivable bug.\n\n## Try it now\n\n```console\n$ pip install git+https://github.com/chaoz23/srdcheck\n$ python -m srdcheck jurisdiction \"Fireball\"          # exit 0 — known content\n$ python -m srdcheck jurisdiction \"Hexblade\"          # exit 2 — not in the SRD, honestly refused\n$ python -m srdcheck query mage-hand.use '{\"kind\": \"attack\"}'\n{\n  \"verdict\": \"illegal\",\n  \"exit_code\": 1,\n  \"why\": \"The hand can't attack.\",\n  \"citations\": [{\"section\": \"SRD 5.2.1 p.145 'Spells > Mage Hand'\", \"page\": 145,\n                 \"quote\": \"The hand can't attack\"}],\n  \"rule_ids\": [\"mage-hand.cant-attack\"],\n  \"adapter\": \"srd-5.2.1@0.2.1\",\n  \"coverage_level\": \"rule-surface-complete\",\n  \"checked_scope\": [\"listed uses and prohibitions\", \"10-pound limit\", \"30-foot range for the proposal\"],\n  \"unchecked_scope\": [\"fine-manipulation ambiguity\", \"duration or range trigger tracking across events\", \"narrative consequences\"],\n  \"assumptions\": [\"the supplied use kind describes the proposal\", \"supplied weight and distance facts are accurate when relevant to the result\"]\n}\n$ python -m srdcheck query mage-hand.use '{\"kind\": \"attack\"}' --table-evaluation\n# deterministic table.evaluation/1.0; status=findings, authority=self_attested\n$ python -m srdcheck query save.check '{\"modifier\":2,\"dc\":10,\"d20_result\":12,\"save_ability\":\"dex\",\"saver_conditions\":[]}' \\\n    --table-evaluation --table-context '{\"session_id\":\"session-7\",\"correlation_id\":\"discord-42\"}'\n$ python -m srdcheck cite \"Command\"                    # verbatim SRD text + page for any registered name\n$ python -m srdcheck --schema                          # I/O contract for agents\n$ python -m srdcheck capabilities                      # engine, protocol, adapters, digests, tools\n```\n\nDeterministic, offline, and no tokens. CI gates 100-verdict p95 latency below\n100 ms; lower local observations are not a compatibility promise. The query\nsurface is young and growing slice by slice — the architecture (kernel +\n[adapters](docs/adapter-spec.md), spec at v0.9 RC) is the point.\n\n`query` and `--pipe` accept `--table-evaluation` for portfolio hosts that need\nthe shared `table.evaluation/1.0` envelope. Legal/illegal verdicts become\ncomplete checked-clean/finding results only within the named query scope;\nmissing facts, unsupported content, ambiguity, and DM discretion remain\nnon-clean. The subject carries a machine-readable `srdcheck-query-scope:*`\nreference; optional `--table-context` JSON can add caller-owned `session_id`,\n`entity_refs`, and a `correlation_id` (emitted as `correlation:*`). Rule and\ncitation evidence is self-contained and keyed by every finding evidence ref.\nEvery result is `self_attested`, including when the calling agent is the DM:\nthis adapter cannot grant table, encounter-state, action, or protected-host\nauthority.\n\nFor a live agent-DM host, use the Discord message or resolved-intent event\nsnowflake as the privacy-safe request join key:\n\n```bash\npython -m srdcheck query mage-hand.use '{\"kind\":\"attack\"}' \\\n  --trace --request-id 123456789012345678\n```\n\nThe verdict stays on stdout; canonical metadata-only NDJSON goes to stderr.\nSee [privacy-safe observability](docs/observability.md) for the event schema,\nMCP configuration, retention boundary, and residual metadata risk.\n\n## For agents (MCP)\n\nsrdcheck is an MCP server with zero dependencies — stdlib only. After `pip install`, the command is `srdcheck-mcp`; from a clone it's:\n\n```json\n{\n  \"mcpServers\": {\n    \"srdcheck\": {\n      \"command\": \"python3\",\n      \"args\": [\"-m\", \"srdcheck.mcp\"],\n      \"cwd\": \"/path/to/srdcheck\"\n    }\n  }\n}\n```\n\nThe complete tool inventory and each tool's checked/unchecked scope are generated\nfrom runtime metadata in the [capability map](docs/capability-map.md); CI rejects\nstale or incomplete inventory. Every call returns the same verdict object as the\nCLI as structured content. Applied-rule results carry their source citations;\nboundary refusals do not invent provenance. An `illegal` verdict is a result,\nnot an error; `cannot-adjudicate` is an honest refusal, not a failure. Tool\ndescriptions and schemas come from loaded adapters, so new adapters extend the\ntool list without kernel changes. See also [`tool.json`](tool.json) for the CLI\nsurface. The opt-in `table_evaluation` MCP tool accepts `{query_type, params,\ncontext?}` and emits the same shared envelope without changing native query-tool\nresponses.\n\nEvery first-party `cannot-adjudicate` result carries stable recovery metadata\nunder `data`: a reason code, recoverability, exact missing-input paths, and a\nsuggested next action. That tells an agent whether to repair the request,\nprovide facts, select an adapter, use another capability, resolve a table\nruling, reconcile stale state, or stop—without parsing `why`. When DM authority is required, an\nauthorized agent-DM can rule directly; another caller can escalate. See the\n[machine-actionable refusal contract](docs/refusal-recovery.md).\n\n## As a Python library\n\nConsume a ruleset's content through a stable, versioned interface — no coupling to internal file paths:\n\n```python\nfrom srdcheck import load_adapter, available_adapters\n\navailable_adapters()               # ['srd-5.1', 'srd-5.2.1', 'toy-tictactoe']\na = load_adapter(\"srd-5.2.1\")      # a versioned identifier\na.categories()                     # the content categories this adapter carries\na.names(\"creature\")                # every creature name (326, complete from the stat blocks)\na.record(\"creature\", \"Ghast\")      # {\"name\": \"Ghast\", \"cr\": \"2\", \"xp\": 450, \"citation\": \"SRD 5.2.1 p.287\"}\na.query(\"encounter.xp-budget\", {\"level\": 3, \"difficulty\": \"moderate\"})  # a verdict dict\n```\n\n**Cross-version edition-trap detection** — catch a name that was valid in an older edition but renamed/removed in the current one (the classic LLM failure, e.g. \"Goblin\" in 2014 → \"Goblin Warrior\" in 2024):\n\n```python\nfrom srdcheck import edition_check\nedition_check(\"Goblin\", \"creature\")          # exit 1 — a srd-5.1 name, not in 5.2.1;\n                                             #   data.candidates_in_current suggests Goblin Warrior/Minion\nedition_check(\"Aboleth\", \"creature\")         # exit 0 — valid in both\n# or from the CLI: srdcheck edition-check \"Goblin\" --category creature\n```\n\nAdapter identifiers carry their version, so `load_adapter(\"srd-5.2.1\")` and `load_adapter(\"srd-5.1\")` coexist without a breaking change; `edition_check` is caller-parameterized (`current` / `priors`), so it generalizes to any versions and any category. The handle is content-neutral: it knows about categories and records, never about a specific ruleset's vocabulary.\n\n## The benchmark\n\n[`bench/`](bench/) is the rules-fidelity referee: versioned question sets with SRD-cited gold verdicts, a harness that scores any model or agent (`gemini:`, `ollama:`, or `cmd:your-agent` on stdin/stdout), and a [generated scorecard](bench/scorecard.md) that reports wrong-rate, refusal-rate, and false-confidence separately, per category, with no aggregate number — ever. A [generated leaderboard](bench/LEADERBOARD.md) ranks subjects by wrong-count alone (the one unforgivable failure), and any third party can [submit a tamper-checked result](bench/README.md#get-on-the-leaderboard) — you can't grade your own homework, because the golds are the set's. Published findings: frontier models ace codified rules and fail by *false confidence* exactly where the rules end — and, on a [per-horizon drift lane](bench/README.md#published-findings-so-far) whose gold verdicts are derived by the engine itself, they don't drift even at 30-round horizons, while a local 8B model's errors are mistakes of rule-knowledge, not memory. Benchmark your own DM product with one command.\n\n## Truth scorecard\n\nEvery tagged release publishes a scorecard against the product truths — generated by CI, never hand-edited, no aggregate score.\n\n<!-- truth-scorecard:start -->\nGenerated by `scripts/truth_scorecard.py` — regenerated and diff-checked in CI, never hand-edited. Statuses are honest: *structural* and *held in review* mean exactly that.\n\n| truth | claim | status | evidence |\n|---|---|---|---|\n| T1 | wrong verdicts | enforced in CI | 712 tests including gold suites ported from the Phase 0 eval; any wrong verdict fails the build |\n| T2 | no citation, no rule | enforced in CI | 90/90 rule atoms carry verbatim source quotes; applied-rule paths cite, while boundary refusals do not invent provenance |\n| T3 | advise, never overrule | structural | the API has no blocking or veto interface to wire; verdicts are advisory by construction |\n| T4 | one payload, two audiences | enforced in CI | every verdict carries machine fields plus a templated plain-English why; schema-tested |\n| T5 | enumeration is the direction | proven for shipped slices | consistency sweeps (50 turn states + toy boards) verify enumerate/validate agreement in both directions on every push; creature-complete enumeration remains a target |\n| T6 | judge, never simulate | enforced in CI | determinism test plus a purity lint: no randomness anywhere in the kernel, no network or subprocess in the verdict path |\n| T7 | mechanism never knows the game | enforced in CI | kernel lint scans every kernel module for game vocabulary (it caught a real violation during development) |\n| T8 | honest boundaries | enforced in CI | refusal goldens: unknown content, unmodeled conditions, and genuinely ambiguous rules text all return exit 2; ambiguity cites its source, while registry and input boundaries may have no citation |\n| T9 | never a single number | enforced in CI | bench scorecard freshness test; per-category tables, no aggregate score exists anywhere in this repository — even the leaderboard ranks by wrong-count alone (T1) and shows the other failure modes unblended |\n| T10 | stranger-agent bootstrap | enforced in CI | cold-start conformance test reaches a first verdict from tool.json/--schema/MCP alone (24 tools); live probe: a frontier model given only tool.json produced a correct first verdict in 1 attempt(s), 3.9s (2026-07-16) |\n| T11 | table speed | enforced in CI | p95 latency budget test: 100 verdicts must stay under 100 ms at p95; lower local observations are not a compatibility promise |\n| T12 | never sell what the model has | held in review | a strategy invariant: features pitched on knowledge parity are cut in review — enforced by humans and admitted as such |\n| T13 | the benchmark is a product | shipped | bench/ publishes 5 sets across 5 subjects with cited gold verdicts, incl. a per-horizon drift lane whose golds are engine-derived; a generated LEADERBOARD ranks any subject; cmd: driver + validate command let a third party submit a tamper-checked result |\n| T14 | every derived state has a lineage | enforced in CI | event.apply stamps every successful derived transition (predecessor hash, causing event, rule ids, rule-vs-ruling kind); tests cover replay verification, tamper detection, the schema minimality ratchet, and reducer/validator agreement; demo replays 15 rounds hash-for-hash |\n<!-- truth-scorecard:end -->\n\n## Licensing\n\n- Code: MIT.\n- `data/`: includes material derived from the System Reference Document 5.2.1 under CC-BY-4.0 — see `srdcheck/adapters/srd-5.2.1/sources/README.md` for provenance and the required attribution.\n- srdcheck is unofficial and is not affiliated with or endorsed by Wizards of the Coast.\n\n## vs alternatives\n\n- **Just asking the LLM** — frontier models know these rules nearly perfectly (we [measured it](eval/RESULTS-phase0.md) and killed half our own idea). What they can't do by construction: *prove* a verdict, *reproduce* it, or *refuse* when the question is outside the rules' jurisdiction — they claimed rules authority in the discretion zone in 5 of 6 [demo runs](demo/mage-hand/). srdcheck sells proof, refusal, determinism, and economy — never knowledge.\n- **Lookup APIs and reference MCP servers** (Open5e, 5e-srd-api and their wrappers) — they answer *\"what does the book say,\"* not *\"is this legal given this state.\"* Complementary, not competing; srdcheck cites the same text they serve.\n- **Closed engines inside AI-DM products** — the strongest products in this vertical run deterministic rules layers, each rebuilt privately, uncited, unbenchmarked, and locked to their platform. srdcheck is that layer open, cited, benchmarked, and embeddable — including in theirs.\n- **Simulator libraries** (combat engines, character libraries) — they *run* games and own state. srdcheck judges and owns nothing (state travels with the query, stamped with lineage), which is exactly what makes it embeddable anywhere.\n\n## Prior art\n\nsrdcheck stands on lessons from Temple of Elemental Evil / Temple+ (dispatcher architecture), PCGen (prerequisite predicates), the FoundryVTT PF2e system (rules as data), Datasworn (official rules-as-JSON precedent), and FIREBALL (structured play state). Patterns were studied; no code was taken from any of them.\n\n<!-- MCP registry ownership marker (do not remove): binds this repo's PyPI package to its registry namespace. -->\nmcp-name: io.github.chaoz23/srdcheck\n\n\n## Formula blanks (v0.3)\n\nIf a rule is a formula, the verdict is the formula — a **number** appears\nonly when the caller supplied every blank. Once the required size/free-hand\nprerequisite facts are supplied, `grapple.initiate` without `str_modifier` +\n`proficiency_bonus` returns `dc_formula` and no `dc`;\n`passive.perception` without `perception_modifier` returns `score_formula`\nand no `score`. Origin: a live table where the base-8 rendered as \"DC 8\"\nwhen the true DC was 13. srdcheck stays lookup-pure: the formula is the rule\ntext, filling caller-supplied blanks is arithmetic — deriving the blanks\nfrom a sheet is charactercheck's lane, never this one.\n\n\n## Spell & feature facts (v0.4)\n\n```\nsrdcheck query spell.facts '{\"name\": \"Protection from Evil and Good\", \"cast_at\": 1000}'\nsrdcheck query feature.uses '{\"feature\": \"divine-sense\", \"charisma_modifier\": 4}'\n```\n\nCasting time, range, components, duration, concentration — the facts a DM\nmisremembers at 2am — as cited verdicts, census-anchored over all 336 SRD\nspells (the build fails if any spell parses incompletely). `cast_at` adds\n`expires_at` as pure arithmetic on the caller's own clock: srdcheck holds no\nstate and no clock. `feature.uses` covers the SRD's use-count *formulas*\nunder the formula-blanks discipline. Origin: a 10-minute ward narrated as\nactive for seventy minutes, caught by the human player.\n\n## Writing your own adapter (v0.5)\n\nThe kernel knows no game — and now the kit proves it. Three bundled adapters\nspan the tiers (registry-only `srd-5.1`, full `srd-5.2.1`, tutorial\n`toy-tictactoe`):\n\n```\nsrdcheck new-adapter my-ruleset     # conformant skeleton\nsrdcheck conformance <adapter-id>   # the bar every adapter must clear\n```\n\nConformance is the entry ticket: provenance manifest with a hash-pinned\nsource, schema-declared inputs that refuse unknown keys, crash-free honest\nrefusal, census-anchored registries. Golden-verdict pinning\n(`scripts/build_golden.py --check`, in CI) guarantees kit refactors are\nbyte-invisible to existing consumers. Guide: [docs/ADAPTER-GUIDE.md](docs/ADAPTER-GUIDE.md).\n",
  "bytes": 25761,
  "sha": "73fc4c00aa6dd279f1c2e557de73722920c6c2b9740828af5e3db88b1de8d1b2",
  "repo_slug": "chaoz23/srdcheck",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_chaoz23_srdcheck_2741ba2e/readme"
}