Skip to main content
Glama

cozyvtt-mcp

cozyvtt-mcp MCP server – quality and maintenance score on Glama

English | 中文

MCP (Model Context Protocol) bridge for CozyVTT — the self-hosted, open-source virtual tabletop. It lets an AI agent join a campaign as DM/KP: narrate over chat, roll server-authoritative dice on the server, move tokens, switch maps, manage initiative, and settle character sheets.

Built for and tested with Hermes Agent, but works with any MCP client (stdio transport).

Upgrading

This README describes how to install and use the current release; the change history lives in CHANGELOG.md. Two migration points are worth knowing before you wire up a client:

  • Three tools were renamed in 0.3.0: campaign_status → campaign_get, initiative_state → initiative_read, token_hp → token_hp_update. No aliases are registered — update client tool selections. Old-to-new mapping.

  • chat_read paginates with limit/cursor (the offset argument was removed in 0.2.0).

The default tool set is every tool; optional presets are described under Tool sets.

Related MCP server: RPG Ledger MCP Server

Tool sets

The default is every tool. Optional registration-time filtering drops excluded tools from tools/list entirely; it changes nothing about how the remaining tools behave. Choose comma-separated presets (union); duplicates are accepted and all wins. The flag overrides COZYVTT_MCP_TOOLSETS. Empty values or unknown names fail with valid preset names and counts. --list-toolsets prints all memberships and the default, then exits successfully without connecting to CozyVTT.

Preset

Tools

Selection

play

20

campaign_get, chat_read, chat_send, creature_search, dice_roll, events_poll, initiative_manage, initiative_read, map_create, map_delete, map_list, map_switch, session_list, session_manage, session_notes_update, token_add, token_delete, token_hp_update, token_move, token_place_creature

docs

9

All document_* tools plus campaign_document_list

roster

7

All character_* tools

macros

4

All saved_roll_* tools

admin

1

campaign_transfer_dm

all (default)

41

Every tool

.venv/bin/python server.py --toolsets play,macros
COZYVTT_MCP_TOOLSETS=docs,roster .venv/bin/python server.py
.venv/bin/python server.py --list-toolsets

For an MCP client, append "--toolsets", "play" to its server args, or set COZYVTT_MCP_TOOLSETS in its server env.

Measured with .venv/bin/python scripts/measure_tool_budget.py (offline stdio). Bytes sum UTF-8 JSON tool definitions, excluding JSON-RPC envelope/list separators; tokens are estimates (bytes // 4), not tokenizer measurements.

Preset

JSON bytes

Estimated tokens

Savings vs all

play

30,925

7,731

48%

docs

13,418

3,354

77%

roster

9,152

2,288

85%

macros

4,664

1,166

92%

admin

1,199

299

98%

all

59,358

14,839

0%

The surface also includes map_create, map_delete, token_delete, and character_delete. Create maps from existing image assets; use map_switch before deleting the current map. token_delete removes a map token; token_hp_update changes sheet HP using a character ID. character_delete permanently deletes an owned sheet. Add roster or docs when a session needs those tools.

Compatibility

cozyvtt-mcp

CozyVTT

Notes

0.6.1

v1.5.3 (1dd6bcc)

Tooling-only patch: configurable smoke pins and offline deployment-evidence validation. 503 offline tests on Python 3.12.13, including the v0.6.0 contract coverage; 41 runtime tools and parameter schemas unchanged. No new live campaign run performed for this patch.

0.6.0

v1.5.3 (1dd6bcc)

Offline review of v1.5.0→v1.5.3 (REST/WS docs + implementation): scope-aware document edits, Keeper-note filtering, newer input limits, conservative dice throttling, campaign.access.revoked. 456 offline tests on Python 3.12.13; 41 tools and parameter schemas unchanged. No live v1.5.3 campaign run; v1.5.0 remains the last live-smoked baseline.

0.5.0

v1.5.0 (b03e287)

Exact pinned baseline. 379 offline tests on Python 3.12.13 (89 adaptation + 62 helper + 228 historical); recorded 2026-10-04 15:44 CST DM read-only REST/passive WS smoke: 16/16 checks, post-cleanup teardown and observed exit 0. Deployment identity is operator-attested.

0.4.0

v1.2.2 / v1.4.0

Dual baseline. Tool-set presets plus map_create/map_delete/token_delete/character_delete. Offline contract suite 228/228; the Dockerfile was replayed inside the real python:3.12-slim rootfs (hash-checked layers) and boots with no environment set, listing 41 tools. No live campaign run, and no OCI image was built (no Docker daemon on the build host).

0.3.0

v1.2.2 / v1.4.0

Dual baseline. Parameter descriptions, MCP annotations, container image. Offline suite 176/176; image built and booted (37 tools, no environment). No live campaign run.

0.2.0

v1.2.2 / v1.4.0

Dual baseline: retain original tools; new REST routes degrade explicitly on old instances. Offline suite 176/176; live v1.4.0 smoke (read/write + Documents/Saved Rolls round-trips) passed 2026-09-17.

0.1.1

v1.2.2

Previous 20-tool release

The recorded DM run used CALL_OF_CTHULHU_7E in PREPARATION: 22 requests (1 login + 21 GETs), one passive WS connection, and only authenticate / initiative.request_state emits. No live campaign writes, conflict-write roundtrip, multi-user visibility or secret-recipient isolation were tested. Optional character/document checks were skipped (zero character sheets/readable documents); session, Saved Roll and custom creature lists were empty. This is an explicit version pin, not a v1.5.x/future-compatibility promise; older compatibility rows remain historical evidence only. See CHANGELOG for the final verification and limits.

The compatibility table describes supported contracts, not an inferred server version. New feature availability is unknown until established; an empty list or a business 404 is not evidence that the route is missing. See SPEC v2 for the complete 41-tool contract.

The current default baseline is CozyVTT v1.5.3. Its selected offline contract coverage does not certify full compatibility or live behavior; see the versioned evidence in CHANGELOG.md.

Features

41 tools returning {ok, data?, error?} for tool-body results. MCP argument validation remains handled by FastMCP:

  • Session/campaign: campaign_get (role and owner reported separately; new capability keys may be unknown), session_manage, session_list, session_notes_update, campaign_transfer_dm (owner reclaim uses the same tool), map_list, map_switch

  • Narration: chat_send (DM / PLAYER), chat_read

  • Dice: dice_roll (server-authoritative results; is_secret=true (wire field: secret) delivers to the roller and DMs on v1.4.0), events_poll (recent buffered dice events, not durable history; DICE_ROLL events are absent from chat history)

  • Tokens/maps: token_add (integer sizes 1..10), token_move, token_hp_update, token_place_creature, token_delete, map_create, map_delete, creature_search (SRD + custom library).

  • Combat: initiative_manage (add / remove / roll / set / reorder / start / next / end), initiative_read (note: CoC7e initiative is DEX-ordered, no roll — this is upstream rules behavior, and roll is gated accordingly)

  • Characters: character_list, character_get, character_create, character_delete, character_validate, character_update (rules math is done by the agent; the bridge just writes values)

  • Documents: document_upload, document_create, document_list, campaign_document_list, document_read, document_update, document_share, document_unshare, document_delete

  • Saved Rolls: saved_roll_list, saved_roll_create, saved_roll_update, saved_roll_delete (private to the current user and campaign; 50 macros per user/campaign, server-validated expressions). saved_roll_list returns complete macros — there is no saved_roll_get.

  • Hit Dice: character_hitdice_spend (DND_5E only; dispatches one spend without rolling dice or healing)

System gating

The bridge stays game-system agnostic, but a few capabilities only make sense under a specific rule system. Those are gated against the campaign's gameSystem (fetched once, cached; enum: DND_5E / PATHFINDER_2E / SHADOWRUN_6E / CALL_OF_CTHULHU_7E):

Capability

Allowed systems

Why

creature_search source=srd

DND_5E

The SRD library is seeded from Open5e — a D&D 5e data source

initiative_manage action=roll

DND_5E, PATHFINDER_2E, SHADOWRUN_6E

The server derives the initiative dice per system; CoC7e doesn't roll at all (DEX order)

character_hitdice_spend

DND_5E

Only the system gate is enforced locally. No reliable WS capability probe exists; dispatch always remains pending.

Gated calls return a clear {ok: false, error} explaining which systems are allowed, instead of emitting an event the server would ignore or misinterpret. Campaigns with no gameSystem set (flexible) fail closed. With no source specified, non-5e campaigns search only custom; 5e campaigns may search both sources. campaign_get().features reports the current campaign's available gated capabilities.

Architecture

MCP client (stdio)
  └─ server.py (FastMCP, lazy init, synchronous first-call self-check)
      ├─ auth.py        — rememberMe login, 10-min keepalive, 3-min re-login spacing, 429 backoff
      ├─ client.py      — REST wrapper: one 401→re-login→retry, 429 exponential backoff (1/2/4s, ≤3)
      ├─ ws_listener.py — socket.io listener, 500-event ring buffer, one reconnect worker
      └─ tools/         — 41 MCP tools (read/write, documents, campaign additions)

Design notes:

  • Dice discipline: rolls are generated and persisted by the server. Public results go to the table; reviewed v1.4.0 sends secret results to the roller and DMs. The bridge provides recent buffered events, not a durable roll-history query.

  • Rules live outside the bridge: skill checks, SAN loss, damage — computed by the agent/GM, the bridge only performs authoritative rolls and writes results. The bridge is game-system agnostic.

  • token_move uses REST PUT; the server checks DM/controlledBy permissions, and the bridge additionally rejects spectators. REST persistence does not imply a map.changed broadcast. map_switch saves through REST then explicitly dispatches map.change through WS; a WS failure preserves the successful REST result and never replays it. On both REST and WS token.move, PLAYER must use the current campaign map while DM may use any map of this campaign.

Result and update contracts

  • Resource IDs identify one URL segment. Empty IDs and ./.. are rejected; separators in other IDs are encoded so a malformed ID cannot select a different resource through URL normalization.

  • Transient login failures wait at least 180 seconds, including any longer server Retry-After. A login 401 stops password retries until you correct the configured credentials and restart the bridge; repeatedly invoking tools cannot bypass this block.

  • Keepalive does not extend an absolute sign-in lifetime. Session-expiry 401 gets one bounded recovery attempt; policy 403 retains its upstream code. The bridge has no MFA login/enrolment workflow.

  • For newer server validation, send whole-square token coordinates, MAP image assets and maps at most 500 squares wide/high. Use grid sizes 10..500; the server may substitute 50 outside that range. Dice labels should fit 200 characters for character_name and 300 for purpose. The bridge preserves server refusals and returned coordinates without silently coercing inputs.

  • Malformed business REST responses return INVALID_RESPONSE with the actual HTTP status. A write may already have happened: inspect state before retrying. In particular, an invalid map-switch response prevents the later WS broadcast. Raw document content, conditional reads and /health reachability retain their separate handling.

  • dice_roll, chat_send, token_hp_update, initiative_manage, and character_hitdice_spend return sent: true, confirmed: false, status: "pending". Read business broadcasts and system.error with events_poll; do not blindly replay writes. Neither baseline provides correlated business ACKs. Dice may carry purpose and character_name (wire: characterName) for Custom Roll display. Hit Dice spend, rolling, and healing are separate operations, not a transaction; an old server may silently ignore the spend event.

  • events_poll returns the oldest unread events first. Save next_seq for the next since; latest_seq is its compatibility alias. high_water_seq is the buffer high-water mark, not a pagination cursor. Check gap, cursor_reset, has_more, connected, and authenticated.

  • character_update(character_id, data={"data": {"hp": {"current": 5}}}) recursively merges sheet fields before PUT. Unspecified fields survive; arrays/scalars replace values and null is explicit. Top-level fields are name, data, and tokenImageUrl. Every accepted update reads under the process lock and sends the exact updatedAt value as a guard when present. A 409 is returned without retry; if the timestamp is absent, the legacy unguarded path remains. This protects only edits after the tool GET, not stale intent from an earlier read. The upstream parsed validator may discard undeclared fixed-system fields even when preserved in the outbound merge.

  • character_create creates the card, checks the roster, then assigns it only if not confirmed as assigned. If assignment fails, the error includes the created character ID: assign that card in the UI instead of creating another. CoC conditions/Mythos/spells/appearance/notes and DND legacy/new hit-dice fields survive character merges; The server may withhold Keeper notes; do not fill in omitted private fields.

  • session_manage uses REST. Pause/end resolve campaign.activeSession.id; start creates a session. End accepts notes (≤2000 characters, shared with the campaign) and save_state=true. Empty end notes do not clear old notes; use session_notes_update(session_id,notes="") to clear. session_list includes active sessions among the most recent 50.

  • Documents use scope USER (personal), CAMPAIGN, or GLOBAL. document_list filters the asset library; campaign_document_list discovers shared private documents too. Typed txt/md create/update is limited to 900 KiB UTF-8; file uploads use the instance limit (default 50 MiB). PDF content cannot be edited. Consult canEdit/canChange when supplied; edit rights depend on asset scope and current membership. Unsharing removes only one link and cannot revoke native/global access; shared:false indicates a native campaign document. Deleting removes the asset and all its links.

  • WS reconnects use fresh, URL-scoped Cookies and request current initiative state after campaign authentication. Use HTTPS for remote deployments.

  • chat_read paginates with limit + cursor: read the newest page first, then pass the returned pagination.nextCursor back as cursor, and stop when it is null. Instances without cursor metadata serve only the latest page and say so (This instance does not support reliable cursor pagination for history; only the latest page can be read.) instead of repeating it.

  • Raw document reads preserve MIME type and ETag. Text returns {mime_type,etag,content}; PDFs are written to the project's downloads/<document_id>.pdf and return {mime_type,etag,file_path,file_size}. Pass etag as If-None-Match; a 304 returns {not_modified:true} so the caller can reuse existing content. Downloads are Git-ignored and local copies survive upstream deletion.

  • REST 401 invalidates existing WS authentication and campaign caches; losing campaign membership cancels WS authentication and clears cached authority; the reconnect worker retains its existing bounded backoff. campaign_transfer_dm clears role and system caches, and the bridge buffers character.updated, campaign.dm.transferred, roster.updated, dice.historyCleared, campaign.role.changed, map:settings:updated, token:appeared, token:disappeared, and campaign.access.revoked for events_poll. Revocation also produces system.error; only sign-out requests a credential refresh, subject to cooldown and the login-rejection block.

  • character_validate always includes validation_reliable:false: CozyVTT v1.5.0 fixes the v1.4.0 validation defect; the bridge retains the false flag because a running server may be unverified.

  • initiative_read(refresh=true) requests fresh state and reports unknown on timeout; use the returned server token coordinates because the server may clamp positions to the map.

  • Route-missing 404 — upstream message exactly The requested resource does not exist — returns This CozyVTT instance does not provide this feature; upgrade to a supported version and retry. Other 404s return Resource not found or inaccessible to the current account (HTTP 404): <upstream message>. Error data preserves the status and upstream detail. Uploading a DOCUMENT to an old upload route may return 400; that error is preserved without retrying with a different type or scope.

Requirements

  • Python ≥ 3.11

  • A CozyVTT v1.5.3 instance (the current default baseline; see compatibility evidence and limits) and a campaign where your account has the permissions required by the tools

  • uv (recommended) or pip

Install

git clone https://github.com/yanjingzhaisun/cozyvtt-mcp.git
cd cozyvtt-mcp
uv sync   # or: python -m venv .venv && .venv/bin/pip install fastmcp requests "python-socketio[client]" websocket-client

Docker (stdio)

docker build -t cozyvtt-mcp:0.6.1 .
docker run --rm -i --env-file /path/to/cozyvtt.env cozyvtt-mcp:0.6.1

Use -i to keep stdin open; MCP uses stdin/stdout, without a network port or TTY. The image installs only compatible, hash-checked runtime wheels from uv.lock, including fastmcp, requests, python-socketio[client], and websocket-client. No editable package install or dependency re-resolution is performed. Credentials are supplied at runtime. Without any COZYVTT variables, initialize and tools/list still work; only business tool calls initialize authentication. Mount upload files inside the container and pass those container paths to document_upload. Mount /app/downloads if binary downloads must survive container removal.

Wheel URLs come from the lock as direct links with sha256 hashes, so only the host serving those blobs is configurable. The default is the canonical CDN; builders in mainland China can use a mirror, which serves byte-identical files (the hashes still verify):

docker build --build-arg WHEEL_BASE=https://mirrors.aliyun.com/pypi/packages -t cozyvtt-mcp:0.6.1 .

scripts/docker_requirements.py --wheel-base "" keeps the lock file's own URLs.

Configuration

Environment variables (no secrets in the repo):

Var

Example

Notes

COZYVTT_URL

http://localhost:8899

Your instance URL

COZYVTT_EMAIL

dm@example.local

DM account

COZYVTT_PASSWORD

—

DM password

COZYVTT_CAMPAIGN_ID

uuid

Target campaign

Hermes Agent (config.yaml)

mcp_servers:
  cozyvtt:
    command: /path/to/cozyvtt-mcp/.venv/bin/python
    args: [/path/to/cozyvtt-mcp/server.py]
    env:
      COZYVTT_URL: "http://localhost:8899"
      COZYVTT_EMAIL: "dm@example.local"
      COZYVTT_PASSWORD: "<secret>"
      COZYVTT_CAMPAIGN_ID: "<campaign-uuid>"

Restart Hermes after registering (MCP servers are not hot-reloaded).

Generic MCP client

Any stdio-capable client: command = the venv python, args = server.py, env as above.

Testing

.venv/bin/python -m pytest -q

The guarded smoke helper retains its original scripts/smoke_v150.py filename and accepts any explicit upstream pin. --deployed-version defaults to v1.5.3; --deployed-revision defaults to 1dd6bccd536afe1defc48dfc42378653e86d6343 and requires a full 40-character hexadecimal revision. The nonempty version and revision must exactly match cozyvtt_version and source_revision in the JSON file supplied with --deployment-evidence. Both values are emitted in the report. To smoke an older or different revision, supply both flags and its matching evidence.

Create an evidence file outside the repository using this structure, replacing evidence with the actual operator verification record (never credentials):

{
  "cozyvtt_version": "v1.5.3",
  "source_revision": "1dd6bccd536afe1defc48dfc42378653e86d6343",
  "evidence": "Replace with the operator's deployment verification record"
}

Check the pin offline before a live run:

COZYVTT_SMOKE=1 .venv/bin/python scripts/smoke_v150.py \
  --dry-run --allow-login \
  --deployed-version v1.5.3 \
  --deployed-revision 1dd6bccd536afe1defc48dfc42378653e86d6343 \
  --deployment-evidence /path/to/deployment-evidence.json \
  --report /path/to/smoke-dry-run.json

--dry-run checks evidence without reading credentials, initializing the bridge, or contacting the network. Its report is identified as a dry run and does not prove live compatibility. It still requires COZYVTT_SMOKE=1, an explicit --cookie-file or --allow-login choice, evidence, and a report path.

For an authorized live read-only smoke, set COZYVTT_URL, COZYVTT_CAMPAIGN_ID, COZYVTT_EMAIL and COZYVTT_PASSWORD in the environment as described under Configuration, then run:

COZYVTT_SMOKE=1 .venv/bin/python scripts/smoke_v150.py \
  --allow-login \
  --deployed-version v1.5.3 \
  --deployed-revision 1dd6bccd536afe1defc48dfc42378653e86d6343 \
  --deployment-evidence /path/to/deployment-evidence.json \
  --report /path/to/smoke-report.json

Alternatively, replace --allow-login with --cookie-file /path/to/session-cookie.txt: the file must be outside the repository with mode 0600; no default credential path exists. Add --ws only when passive WS observation is authorized. The helper retains its HTTP/WS allowlists, single-login/connection limits, read-only state comparisons and teardown checks. Deployment identity is operator-attested; /health does not discover the server version.

(scripts/smoke_write.py writes chat, a public roll, and a secret roll — run it manually and only on a throwaway campaign. It checks sender and unique purpose; proving that players do not receive secret rolls additionally requires an independent player connection.)

Offline tests block TCP connections and include real FastMCP in-memory and stdio checks; they do not require campaign credentials. Live integration against an attested v1.5.0 instance was verified 2026-10-04 with authenticated read-only REST and passive WS state reads; no campaign writes or multi-user isolation were tested. Historical v1.4.0 read/write evidence remains historical. The local venv used for verification runs Python 3.12.13; Python 3.13 remains unverified.

Troubleshooting

  • Logs: logs/cozyvtt-mcp.log (auth events, WS state, tool calls; never contains passwords)

  • Repeated 401: reviewed v1.4.0 limits failed credential attempts to 5 per 15 minutes/IP. Successful credential requests do not count there; older accounting is unverified. The bridge enforces a re-login interval of at least 3 minutes, including failed attempts; Retry-After may extend it.

  • events_poll empty: may mean no new events. Inspect connected, authenticated, last_error, and connection_error; the single WS worker retries disconnected or rejected connections. Initialization failures can be retried after a 180-second cooldown without restarting.

  • CoC7e initiative doesn't roll dice: upstream behavior — CoC7e initiative is DEX-ordered, no roll is produced

License

MIT (see LICENSE). CozyVTT itself is AGPLv3 — this project is an independent API client and contains no CozyVTT code.

Ecosystem

  • dnd5e-rules — deterministic D&D 5e rules calculations (pure functions, SRD 5.1 data under CC-BY-4.0). The rules layer we pair with this bridge: the server rolls the dice, the bridge carries them, this library does the math, the agent narrates.

Available Tools

41 tools
campaign_document_listCampaign Document ListA
Read-onlyIdempotent

List native and shared documents visible in the configured campaign. Use document_list for asset-library filters and document_read for content. Read-only for members. shared=false identifies a native document without a separate link to revoke; document_unshare cannot remove that source of access. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, and non-destructive behavior. The description adds valuable beyond-annotation context: 'Read-only for members,' the subtle shared=false native-document access nuance, and the return contract ({ok:true,data} vs {ok:false,error}). No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Each sentence earns its place: purpose, sibling routing, access implications, and error contract. The description is efficient and front-loaded with the core purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read-only list tool with an output schema and strong annotations, the description covers purpose, alternatives, behavioral nuance, and error patterns. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the schema fully describes the input surface. Baseline 4 applies; no parameter-specific semantics are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States exactly what the tool does: 'List native and shared documents visible in the configured campaign.' It also distinguishes itself from siblings by naming document_list and document_read for alternative purposes, making the tool's role clear and distinct.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance: use document_list for asset-library filters and document_read for content. This tells an agent when not to use this tool, which is strong usage differentiation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

campaign_getCampaign GetA
Read-onlyIdempotent

Read campaign identity, role, health, current map, and capability evidence. Use this for orientation; use map_list for all maps and session_list for sessions. Read-only for campaign members; /health reachability is not feature support, and unprobed capabilities remain unknown. Repeating reads does not change game state. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds meaningful behavioral context beyond the annotations: read-only access for campaign members, the caveat that /health reachability does not imply feature support, unknown unprobed capabilities, and idempotence via repeating reads not changing state. It also discloses return-shape and error-handling behavior, which annotations do not cover.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: purpose, usage guidance, behavioral caveats, and failure semantics are all included without redundant padding. The key orientation purpose is front-loaded, and the caveats are grouped logically.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters, rich annotations, and an output schema, the description fully covers what an agent needs to correctly select and invoke this tool. It explains orientation scope, sibling routing, membership permissions, idempotence, and error response behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has 0 parameters and schema coverage is 100%, so there are no parameter semantics to explain. The description appropriately avoids fabricating parameter guidance, meeting the baseline for a no-parameter tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Read' and the resource scope: campaign identity, role, health, current map, and capability evidence. It also distinguishes itself from map_list and session_list, making its purpose specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says 'Use this for orientation' and directs the agent to alternatives: 'use map_list for all maps and session_list for sessions.' This gives clear when-to-use guidance and names the sibling tools that handle related but different needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

campaign_transfer_dmCampaign Transfer DmA
Destructive

Transfer the campaign DM role to an existing member, or reclaim it as owner. Use campaign_get to inspect current role/ownership first. Upstream permits DM, owner, or admin; owner reclaim uses the owner's own ID. The old DM becomes PLAYER, ownerId stays unchanged, and local role/system caches are invalidated after success. Do not simulate this with separate role edits. Role changes and broadcasts are not guaranteed idempotent; inspect campaign_get before considering another transfer. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
user_idYesExisting campaign member UUID to become DM; the owner passes their own user UUID to reclaim the role.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=true, and idempotentHint=false. The description adds specific behavioral context: 'The old DM becomes PLAYER, ownerId stays unchanged, and local role/system caches are invalidated after success.' It also warns 'Role changes and broadcasts are not guaranteed idempotent,' which aligns with the idempotentHint. This goes beyond the annotations by detailing the side effects. However, it does not state what permissions the caller must hold (e.g., must be admin/owner to transfer), which is a minor gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is about four sentences, each carrying distinct information: purpose, prerequisite, side effects, and return format. It is front-loaded with the action and includes a warning. No filler, but it could be slightly tightened (e.g., merging the return-format sentences). Still, every sentence earns its place, so a 4 is appropriate.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the purpose, prerequisites, side effects, non-idempotency, explicit do-not instructions, and return value format ({ok:true,data} vs {ok:false,error}). It also distinguishes tool-body failures from MCP argument errors. Given the tool's complexity and the existing output schema (which presumably defines the data structure), nothing essential is missing for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides 100% coverage with a clear description: 'Existing campaign member UUID to become DM; the owner passes their own user UUID to reclaim the role.' The description repeats the same idea ('owner reclaim uses the owner's own ID') but adds no new meaning. Per the rubric, when schema coverage is high, baseline is 3, and the description does not elevate it further.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action: 'Transfer the campaign DM role to an existing member, or reclaim it as owner.' It names the resource (campaign DM role) and the two modes, clearly distinguishing it from sibling tools like campaign_get (inspection) and character_update (different resource). The verb 'transfer' is precise and leaves no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly directs the agent to 'Use campaign_get to inspect current role/ownership first' and reiterates 'inspect campaign_get before considering another transfer.' It also provides an explicit negative: 'Do not simulate this with separate role edits.' This gives clear when-to-use and when-not-to-use guidance, plus a precondition that prevents misuse.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

character_createCharacter CreateA

Create a character sheet and ensure it appears in the current campaign roster. Use character_update for an existing sheet and token_add to place a linked token; creation does not place one. Campaign gameSystem determines the initial schema; upstream validates membership and sheet data. Do not trust character_validate as a save gate. After POST, the bridge reads the roster and assigns only if not found. This is not atomic or idempotent: assignment failure returns ok=false with the created character ID in data; missing ID means creation status is unknown. Inspect the roster/UI and recover the existing sheet instead of creating a duplicate. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
dataNoOptional initial sheet-field object for the campaign system, not a nested request patch; null omits it and lets upstream choose defaults.
nameYesNew sheet display name, 1..200 characters; passed without trimming.
token_image_urlNoOptional artwork URL for the sheet; empty string omits it. This does not create a map token.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the annotations: it discloses that the operation is not atomic or idempotent, explains the roster read-back and conditional assignment, details failure return shapes including ok=false with a created character ID, and notes when creation status is unknown. Annotations only carry high-level hints, so this behavioral detail is highly valuable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and each subsequent sentence provides operationally relevant information about alternatives, failure modes, and recovery. It is long, but the density of caveats is justified for a create tool with non-idempotent behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the full schema descriptions, annotations, and output schema, this description closes the remaining gaps: error contracts, non-idempotency, recovery advice, and the fact that campaign gameSystem determines the initial schema. Nothing an agent needs to invoke this tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the input schema already fully documents all three parameters: name length/trimming, data object semantics, and token_image_url default/omission. The description adds the gameSystem-dependent schema context, but parameter meaning is already carried by the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states exactly what the tool does: it creates a new character sheet and ensures it appears in the current campaign roster. It explicitly contrasts with character_update for existing sheets and token_add for token placement, so an agent can distinguish this tool from its siblings immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives direct routing guidance: use character_update for existing sheets and token_add for placing a linked token, and clarifies creation does not place one. It also warns not to trust character_validate as a save gate, providing concrete when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

character_deleteCharacter DeleteA
DestructiveIdempotent

Delete a character sheet permanently (owner only). Use character_get to inspect the sheet first and character_update to edit it; use token_delete to remove only a placed map token. This deletes the sheet itself, not just its campaign assignment. DM authority alone does not grant deletion rights. It has no undo tool and does not remove map tokens. Repeating leaves the sheet absent but may return a not-found error. Returns upstream {message} in data; REST permission and resource errors retain diagnostics. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
character_idYesCharacter sheet ID owned by the authenticated user; not a map token ID.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare destructiveHint=true, readOnlyHint=false, and idempotentHint=true, but the description adds crucial context: the deletion is permanent with no undo, it does not remove map tokens, re-invocation may return a not-found error, and the exact success/failure response shapes are specified. This exceeds what annotations alone provide and does not contradict them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than average, but every sentence adds necessary operational context: scope, alternatives, side effects, repeat behavior, and error contract. It is front-loaded with the core purpose and then flows logically through exclusions and return behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With one parameter, a rich output schema, and annotations covering safety and idempotency, the description still provides everything an agent needs: ownership requirements, no undo, no token removal, repeat behavior, and a precise success/error return contract. Nothing important is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already covers the single parameter at 100%, including that it must be a character sheet ID owned by the user, not a map token ID. The description reinforces this in prose but does not add substantially new parameter-level meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: 'Delete a character sheet permanently (owner only).' It clearly distinguishes itself from sibling tools by noting it is different from token_delete and character_update, so an agent can correctly identify the operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use and when-not-to-use guidance, including 'use character_get to inspect the sheet first,' 'use token_delete to remove only a placed map token,' and the exclusion that 'DM authority alone does not grant deletion rights.' This fully routes the agent to the correct sibling alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

character_getCharacter GetA
Read-onlyIdempotent

Read a full character sheet by ID, preserving unknown fields. Use character_list to discover roster IDs and character_update to patch a sheet. Upstream allows the owner or campaign members to read; keeper data.notes are not private DM fields. Interpret data using the character's own gameSystem, preserving CoC fields and DND hitDice structures. Repeated reads do not alter the sheet. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
character_idYesExisting character ID, normally discovered with character_list; the sheet may use its own gameSystem.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, openWorld, idempotent, and non-destructive hints, but the description adds meaningful context beyond them: preserving unknown fields, gameSystem-specific interpretation, visibility of keeper data.notes, repeated reads not altering the sheet, and the ok/error return envelope. This is substantial added behavioral detail with no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense yet compact, with the primary action front-loaded and every sentence earning its place by adding routing, permission, data-interpretation, or error-handling context. There is no filler or repetition of annotation values.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a single simple parameter, rich annotations, and a thorough description covering discovery, permissions, data semantics, idempotency, and failure modes, an agent has everything needed to select and invoke this tool correctly. The output schema also covers return-value structure, so nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already documents character_id fully at 100% coverage. The description reinforces that the ID is discovered via character_list and that the sheet may use its own gameSystem, but it does not add significant new meaning beyond the schema's parameter description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Read a full character sheet by ID', which clearly states the operation. It also distinguishes itself from sibling tools by explicitly naming character_list for roster discovery and character_update for patching, so an agent can tell them apart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit routing guidance: 'Use character_list to discover roster IDs and character_update to patch a sheet.' It also gives access context by explaining who upstream allows to read, which helps an agent decide when this tool is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

character_hitdice_spendCharacter Hitdice SpendA
Destructive

Spend one remaining use from a DND_5E character's Hit Dice pool through WS. Use character_get to inspect pools first; dice_roll and token_hp_update perform rolling and healing separately, with no shared transaction. Upstream requires the character owner or DM and campaign assignment. index selects an array entry, not a dice count. Repeating spends again. Only the system is gated locally: there is no v1.5.0 permits the owner or DM but never a spectator. There is no reliable capability probe, and older servers may silently ignore this event. Returns sent:true,confirmed:false,status:"pending" inside data: dispatch is not a business ACK. Read events_poll for results/system.error and inspect state before further action; never blindly resend. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
indexYesZero-based integer >=0 selecting an entry in sheet data.hitDice; inspect character_get for valid pools and remaining uses.
character_idYesCampaign-assigned DND_5E sheet ID whose Hit Dice pool is spent; not a map token ID.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With destructive/non-idempotent annotations already set, the description adds real value: async dispatch semantics (sent:true,confirmed:false,status:"pending" is not a business ACK), no shared transaction with healing, no reliable capability probe, older servers silently ignoring the event, and retry guidance via events_poll. However, the corrupted sentence "there is no v1.5.0 permits the owner or DM but never a spectator" is incoherent and leaves the gating model ambiguous.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The critical spend/async/retry information is reasonably front-loaded, but the description is long for two parameters and contains a broken, self-contradicting sentence about gating that costs reader comprehension. Some hedging ("no reliable capability probe," "may silently ignore") earns its place, but the corrupted line does not.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a destructive mutation tool with an output schema and full annotations, the description covers auth requirements, async result handling, error shapes ({ok:false,error} vs MCP argument errors), and retry discipline. The only real gap is the garbled gating sentence, which leaves the spectator/permission model unclear.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds a useful anti-pattern clarification that index "selects an array entry, not a dice count," plus the guidance to inspect character_get for valid pools and remaining uses. This meaningfully supplements the schema without contradicting it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb+resource+scope: "Spend one remaining use from a DND_5E character's Hit Dice pool through WS." It explicitly distinguishes itself from roll/heal siblings (dice_roll, token_hp_update). The trailing garbled sentence about gating slightly muddies the otherwise clear purpose, so it falls short of a clean 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It names prerequisites (owner or DM, campaign assignment), routes the agent to character_get for inspection, and clarifies that dice_roll/token_hp_update handle rolling and healing separately with no shared transaction. It also prescribes post-call behavior (read events_poll before further action, never blindly resend). It stops short of an explicit when-not-to-use rule, so 4 rather than 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

character_listCharacter ListA
Read-onlyIdempotent

List the configured campaign roster to discover character IDs and assignments. Use character_get for one full sheet or character_create to add a sheet. Read-only for campaign members; no creation or roster changes occur on repeat calls. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint, idempotentHint, openWorldHint, and destructiveHint. The description adds valuable behavioral context beyond those: no creation or roster changes on repeat calls, the successful return shape {ok:true,data}, failure shape {ok:false,error}, and the distinction between tool-body failures and MCP argument-schema errors. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is four sentences and every sentence earns its place: what it does, sibling routing, idempotency/read-only guarantee, and return/error behavior. The primary purpose is front-loaded, and there is no redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter list operation with rich annotations and an output schema, the description is complete. It covers the operation's scope, safety, idempotency, return format, error format, and the relationship to sibling tools—everything an agent needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the baseline is 4. The description adds no parameter details because none are needed; the schema already reflects an empty parameter set. There is no gap requiring compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: "List the configured campaign roster to discover character IDs and assignments." It also differentiates itself from character_get and character_create, so an agent can distinguish it from close siblings without opening their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when to use this tool versus alternatives: "Use character_get for one full sheet or character_create to add a sheet." It also clarifies that the operation is read-only and safe on repeat calls, giving clear context for invocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

character_updateCharacter UpdateA
Destructive

Patch an existing sheet while preserving unspecified fields (owner or campaign DM). Use character_get first; use token_hp_update for a signed HP change and character_create for a new sheet. data is a request-field object, e.g. {"data":{"hp":{"current":5}}}. Only name/data/tokenImageUrl are allowed at the top level. Nested data dictionaries merge recursively after a GET; arrays/scalars replace whole values and null is an explicit value, not deletion. The caller calculates rules values using the sheet's own gameSystem. Updates are locked only within this process; concurrent browser saves may be lost outside this tool's GET-to-PUT window. On servers supporting updatedAt guards, changes after this tool's GET produce a visible conflict; this does not protect stale intent from an earlier character_get. Upstream parsed validation may discard undeclared fixed-system fields even though this bridge preserves them outbound. REST errors retain diagnostics. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
dataYesNonempty request patch containing only name, data, tokenImageUrl. Sheet changes go inside data as an object; arrays replace, null is explicit.
character_idYesExisting sheet ID to modify; upstream enforces owner or campaign DM access.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes far beyond the destructive/openWorld/idempotent annotations: recursive merge semantics, array/scalar replacement, null-as-explicit-value, in-process locking scope, lost concurrent browser saves, updatedAt guard conflicts, and stale-intent caveat. It also discloses which fields upstream validation may discard and how errors surface.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose, prerequisites, and alternatives before the caveats. Dense and long, but nearly every sentence carries distinct, non-redundant operational information; only the concurrency/validation sentences could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, yet the description still summarizes return shapes ({ok:true,data} vs {ok:false,error}) and distinguishes tool-body failures from MCP argument-schema errors. Combined with the merge and concurrency rules, nothing material is missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real meaning: the 'request-field object' shape with an example, the top-level allowlist (name/data/tokenImageUrl), and the recursive merge rule for nested dictionaries. The example `{"data":{"hp":{"current":5}}}` is not in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Patch an existing sheet') plus the defining behavioral trait ('preserving unspecified fields'). Names the siblings it is not (token_hp_update, character_create) so an agent can distinguish it without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly prescribes prerequisites and alternatives: 'Use character_get first', 'use token_hp_update for a signed HP change', 'character_create for a new sheet'. When-to-use and when-to-use-something-else are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

character_validateCharacter ValidateA
Read-onlyIdempotent

Read upstream validation diagnostics for an owned character with a fixed gameSystem. Use character_get to inspect fields; do not use this as a reliable save gate. v1.4.0 ignores validation failures, so isValid=true does not prove validity; older-version reliability is unknown. Always adds validation_reliable=false and validation_note. Owner-only upstream read; repeating it does not repair or save data. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
character_idYesExisting character ID owned by the authenticated user; fixed-system validation is required upstream.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already indicate read-only, idempotent, and non-destructive behavior, and the description adds valuable context beyond that: version-specific validation reliability, the guaranteed addition of validation_reliable and validation_note, and the exact success/error return shapes. There is no contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and usage, then covers reliability caveats and return behavior. It is a bit dense, but every sentence earns its place by conveying risks and edge cases that an agent needs before calling.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read-only tool with rich annotations and an output schema, the description is complete. It covers ownership, reliability caveats, success versus failure shapes, and MCP-level argument-schema errors, leaving no critical gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully documents character_id at 100% coverage, so the baseline is 3. The description reinforces that the character must be owned and that validation is fixed-system, but it does not add meaningfully new parameter-level semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Read upstream validation diagnostics for an owned character.' It also distinguishes itself from character_get by explicitly routing field inspection to that sibling, so an agent can tell the tools apart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit guidance: use character_get to inspect fields and do not rely on this tool as a save gate. It also clarifies that repeating the call does not repair or save data, which helps an agent decide when not to invoke it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

chat_readChat ReadA
Read-onlyIdempotent

Read persisted campaign messages with opaque cursor pagination. Use chat_read for narration history; use events_poll for dice results and live events. Read-only for campaign members. Start without a cursor, then pass nextCursor unchanged; stop at null. Older servers support only the latest page and reject cursor history. DICE_ROLL entries are excluded. Repeated reads do not consume messages. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
limitNoPage size, 1..100 messages; defaults to 20.
cursorNoOpaque pagination.nextCursor from the previous response; null starts with the latest page. Do not construct cursors or offsets.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, and the description adds actionable behavioral details: repeated reads do not consume messages, DICE_ROLL entries are excluded, older servers reject cursor history, and failure modes return ok:false. This goes well beyond the annotation hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place: purpose, routing, permissions, pagination procedure, server caveat, exclusions, idempotence, and error contract. The most critical usage guidance is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and rich annotations, the description covers all operational essentials: pagination protocol, server compatibility, exclusions, and error format. Nothing an agent needs to invoke or interpret the tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description enriches the cursor parameter with lifecycle semantics ('pass nextCursor unchanged', 'stop at null', 'Do not construct cursors or offsets') and clarifies the limit's pagination role. Slight deduction because the limit parameter is not discussed beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Read persisted campaign messages') and immediately distinguishes itself from events_poll. It also states exclusions (DICE_ROLL entries), leaving no ambiguity about what the tool returns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes usage: 'Use chat_read for narration history; use events_poll for dice results and live events.' It also provides a clear pagination walkthrough (start without cursor, pass nextCursor unchanged, stop at null) and notes server compatibility caveats.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

chat_sendChat SendA

Post one campaign chat message as narration or player dialogue. Use chat_read to inspect history; use dice_roll for dice, not chat text pretending to be a roll. Authenticated campaign membership is required; type is a message category, not a role grant. On v1.5.0 the server selects the resulting broadcast category from the authenticated role. Upstream campaign chat cooldown may reject messages. Creates a new message on each accepted send; do not retry blindly. Returns sent:true,confirmed:false,status:"pending" inside data: dispatch is not a business ACK. Read events_poll for results/system.error and inspect state before further action; never blindly resend. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
typeNoMessage category: DM (default narration) or PLAYER. This does not change the authenticated role.DM
contentYesNonblank message text, at most 2000 characters; whitespace is preserved when sent.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag non-readonly, non-idempotent, open-world behavior, and the description adds substantial context beyond them: upstream cooldown may reject, each accepted send creates a new message, 'sent:true,confirmed:false' is dispatch and not a business ACK, and events_poll must be read before retrying. This is exactly the caveat detail an agent needs to avoid blind retries.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and alternatives, and every sentence carries operational weight. However it is dense and slightly repetitive around retry/ACK language ('do not retry blindly' and 'never blindly resend'), which costs a point on tightness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite an output schema existing, the description still frames the result contract (sent/confirmed/status on dispatch, {ok:true,data} vs {ok:false,error}, MCP-level schema errors), leaving no ambiguity about what a successful call does or does not guarantee.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3, but the description adds genuinely new semantics: 'type' does not change the authenticated role and, on v1.5.0, the server derives the broadcast category from the authenticated role. That is meaning beyond the schema's field description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states a precise verb and resource ('Post one campaign chat message') and immediately scopes the two modes (narration vs player dialogue). It is trivially distinguishable from siblings like chat_read and dice_roll, which the description names explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It names alternatives and their selecting conditions: chat_read for history, dice_roll for dice rather than chat text posing as a roll. It also states the authentication prerequisite (authenticated campaign membership) and a clear exclusion ('type is a message category, not a role grant').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

dice_rollDice RollA

Roll server-authoritative dice and publish the result to the permitted audience. Use saved_roll_list for stored expressions; saving a macro does not execute it. Authenticated campaign users may roll. Public rolls broadcast to the campaign; v1.5.0 permits DM and PLAYER rolls, not spectators; secret routing and the shared user budget remain server-authoritative. Each send creates a new roll; never retry on missing results. Calls queue with a 2.1-second minimum between actual sends, retaining the older 30/minute policy. Newer servers allow higher rates but cap characterName at 200 and purpose at 300 characters; server errors remain visible through events_poll. The bridge performs no random generation or rules calculations. Returns sent:true,confirmed:false,status:"pending" inside data: dispatch is not a business ACK. Read events_poll for results/system.error and inspect state before further action; never blindly resend. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
purposeNoOptional broadcast label explaining the roll; empty string omits it, without changing dice calculation.
is_secretNoFalse publishes to the campaign; true requests secret delivery to the roller and DMs (wire field secret).
expressionYesServer-parsed dice expression, e.g. 1d20+5, 2d6, or 4d6kh3; invalid syntax is reported asynchronously.
character_nameNoOptional display attribution (wire characterName), not a character ID or permission credential; null omits it.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag non-readOnly, open-world and non-idempotent, but the description adds substantially: a 2.1-second minimum gap with 30/minute, the server-authoritative budget and secret routing, and the crucial disclosure that sent:true/confirmed:false is a dispatch, not a business ACK. It also clarifies that the bridge performs no RNG or rules math and points to events_poll for error visibility.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core routing rule and the send/ACK caveat are front-loaded in the first few sentences, and every clause carries operational value. It is dense and slightly sprawling, with error-shape details tacked on at the end, but there is no obvious filler to cut.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a non-idempotent, open-world mutation tool, the description covers permissions, rate limits, delivery semantics, failure handling, and where to observe results. With an output schema present, it need not explain return values, and it still documents the success/failure envelope shape and MCP-vs-tool error distinction.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the four parameters are already documented, and the description still adds field-level constraints the schema omits: characterName capped at 200 and purpose at 300 characters on newer servers, plus that purpose does not alter dice calculation. It does not restate the expression grammar, which is fine since the schema covers it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states a specific verb+resource ('Roll server-authoritative dice') plus the side effect ('publish the result to the permitted audience'), which no sibling tool offers. It also explicitly distinguishes itself from saved_roll_list, so an agent can route between them without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternative for stored expressions ('use saved_roll_list'), warns that saving a macro is not execution, states who may roll (authenticated campaign users; DM/PLAYER, not spectators), and gives an operational rule ('never retry on missing results'). These are concrete when-to-use/when-not conditions rather than implied guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

document_createDocument CreateA

Create a new txt/md document from inline content through REST. Use document_upload for PDF or larger local files, and document_update to replace existing text. Name and description are trimmed; content preserves whitespace. USER is personal, CAMPAIGN requires its DM, and GLOBAL rights are enforced upstream. Each accepted call creates a separate asset. Content is capped at 900 KiB UTF-8; upstream JSON limits also apply. Upload/create share a default 30 requests/minute/user limit. Creation does not separately link a personal asset; use document_share for that. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
nameYesAsset title, trimmed to 1..200 characters.
scopeNoVisibility/ownership scope: USER (default personal), CAMPAIGN, or GLOBAL; upstream enforces creation rights. CAMPAIGN uses campaign_id.USER
formatYesText representation: txt or md; PDFs require document_upload.
contentYesComplete text, including empty text, at most 900 KiB UTF-8; rejects C0/DEL controls except TAB/LF/FF/CR.
campaign_idNoExplicit campaign ID; null uses the configured campaign when scope=CAMPAIGN, otherwise omits the field. If supplied, it is forwarded for any scope.
descriptionNoOptional metadata, trimmed to at most 1000 characters; null omits it.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=false and destructiveHint=false, but the description adds substantial behavioral context beyond them: whitespace preservation for content, trimming of name/description, scope-based permission enforcement (USER personal, CAMPAIGN requires DM, GLOBAL upstream), a 900 KiB UTF-8 cap, a shared rate limit of 30 requests/minute/user, and the return envelope shape. It also notes that each accepted call creates a separate asset. No annotation contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than average, but every sentence carries operational value, including routing, limits, permissions, and response format. It is front-loaded with purpose and alternatives before diving into behavioral details. It could be slightly tightened, but it remains well-structured and free of filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite the tool's six parameters and rich schema, the description leaves no essential gap: it covers when to use it, alternatives, permissions by scope, size limits, rate limits, return behavior, and a pointer to document_share for linking. The presence of an output schema and detailed input schema further reduces the burden, and the description is more than sufficient for an agent to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all six parameters. The description still adds semantic value by clarifying that 'Name and description are trimmed; content preserves whitespace' and that scope rights are enforced upstream. These nuances are not fully captured in the schema property descriptions, so the description meaningfully supplements the structured input definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Create a new txt/md document from inline content through REST.' It explicitly distinguishes itself from siblings by naming document_upload (PDF/larger local files) and document_update (replace existing text). An agent can immediately identify what this tool does and how it differs from alternative document tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit routing guidance: 'Use document_upload for PDF or larger local files, and document_update to replace existing text.' It also clarifies when document_share is needed ('Creation does not separately link a personal asset; use document_share for that'). This leaves no ambiguity about when to choose this tool over its siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

document_deleteDocument DeleteA
DestructiveIdempotent

Delete a document asset and all of its share links. Use document_unshare to remove only one campaign link and document_read to inspect content first. Upstream enforces uploader/DM/admin permissions according to scope. Deletion is destructive; local downloaded copies remain. Repeating leaves the asset absent but can return a not-found error. This tool does not offer an undo operation. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
document_idYesDocument asset ID to remove globally, including all campaign sharing links; not a single link ID.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, but the description adds substantial context beyond them: local downloaded copies survive deletion, repeating the call is idempotent in effect yet may return a not-found error (clarifying the idempotentHint), there is no undo, and the return shape distinguishes success, tool-body failures, and MCP schema errors. This meaningfully enriches what the annotations alone convey and does not contradict them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but not bloated; each of its seven sentences earns its place (purpose, sibling routing, permissions, destructiveness, idempotency caveat, undo absence, return contract). The core purpose is front-loaded before caveats. It is slightly long, but for a destructive, irreversible operation the thoroughness is justified.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive tool with one parameter, the description is complete: it covers the action, cascade effect on share links, permission context, error/return contract, and irreversibility. The output schema exists and the description still explains the {ok:true,data} vs {ok:false,error} contract, which is more than sufficient for an agent to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already explains that document_id is a 'Document asset ID to remove globally, including all campaign sharing links; not a single link ID.' The description reinforces this via the document_unshare contrast but adds no new parameter-level detail beyond the schema. Baseline 3 is appropriate since the schema carries the full burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Delete a document asset and all of its share links.' It explicitly differentiates itself from document_unshare ('remove only one campaign link') and document_read ('inspect content first'), making the tool's scope unmistakable without needing to inspect siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit routing guidance: use document_unshare when only one campaign link must be removed, and use document_read to inspect content before deleting. It also states that permission enforcement is handled upstream. An agent knows exactly when to pick this tool over its siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

document_listDocument ListA
Read-onlyIdempotent

List document assets with scope, search, and page filters. Use campaign_document_list to discover personal documents shared into this campaign; use document_read for content. Read-only; upstream filters by access. USER restricts to personal assets (including an explicit current-user filter for admins); null scope leaves filtering to upstream. Repeated listing does not consume or modify assets. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
pageNoOne-based page number, integer >=1; defaults to the first page.
limitNoAssets per page, integer 1..100; defaults to 50.
scopeNoOptional USER/CAMPAIGN/GLOBAL filter; null leaves scope unspecified. USER means current-user personal assets.
searchNoOptional search text passed upstream; null omits the filter, empty text is sent explicitly.
campaign_idNoExplicit campaign ID; null uses the configured campaign when scope=CAMPAIGN, otherwise omits the field. If supplied, it is forwarded for any scope.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint. The description adds valuable context beyond those: upstream filters by access, USER scope uses an explicit current-user filter for admins, repeated listing does not consume or modify assets, and success/failure return shapes are specified. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and filters, immediately followed by sibling routing, then behavioral notes and return/error semantics. Every sentence adds distinct value; there is no filler or repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter read-only list tool with an output schema, the description is complete: it covers scope semantics, access filtering, idempotence, success shape, tool-body failure shape, and MCP-level argument errors. Nothing critical is missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaningful param nuance beyond the schema, particularly that USER restricts to personal assets with an explicit current-user filter for admins and that null scope leaves filtering to upstream. This clarifies behavior that raw schema descriptions only hint at.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with the specific verb 'List' and resource 'document assets', then names the exact filters (scope, search, page). It also explicitly distinguishes itself from campaign_document_list and document_read, so an agent can tell sibling tools apart immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear routing guidance: use campaign_document_list to discover personal documents shared into the campaign, and use document_read for content. It also explains read-only access and upstream filtering, which helps the agent decide when this tool is appropriate versus alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

document_readDocument ReadA
Read-onlyIdempotent

Read an accessible document as text or a local binary download. Use document_list/campaign_document_list to discover IDs; use document_update to replace txt/md content. Upstream checks asset visibility, including shared access. Does not modify upstream data, but binary reads atomically replace downloads/.pdf (or .bin) locally; readOnlyHint refers to the upstream resource. Text returns mime_type/etag/content. Binary returns mime_type/etag/file_path/file_size, never inline bytes. Pass etag unchanged for a conditional read: 304 returns not_modified=true without content, so retain your cached copy. Repeated reads may refresh the local file. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
etagNoPrevious response ETag, passed unchanged as If-None-Match; null requests content without a cache condition.
document_idYesDocument asset ID; only ASCII letters, digits, underscores, and hyphens are accepted because it also names a local file.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations carry readOnlyHint/idempotentHint, but the description adds crucial nuance: binary reads 'atomically replace downloads/<id>.pdf locally' while 'readOnlyHint refers to the upstream resource.' It also discloses upstream visibility checks, conditional-read semantics, and the {ok:false,error} failure envelope — all context the annotations alone do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose, then usage, behavior, return modes, and error format in a logical order; every sentence carries information. Slightly longer than strictly necessary since the output schema already documents return fields, but the density is justified by the tool's two modes and local side effects.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema covers return values and annotations cover safety hints, the description still supplies everything an agent needs: discovery flow, local file side-effect disclosure, conditional caching semantics, and the distinction between tool-body failures and MCP argument-schema errors. Nothing needed for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds genuine value by explaining the etag's behavioral consequence — '304 returns not_modified=true without content, so retain your cached copy' — which goes beyond the schema's request-side description of If-None-Match. It reinforces the mode-dependent return fields but leans partly on the output schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: 'Read an accessible document as text or a local binary download.' It also distinguishes itself from siblings by naming document_list/campaign_document_list for ID discovery and document_update for content replacement, so an agent can route correctly without opening other schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'Use document_list/campaign_document_list to discover IDs; use document_update to replace txt/md content.' It also explains when to use the etag parameter (conditional read with 304 handling) and how to interpret the not_modified response, leaving no ambiguity about invocation flow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

document_shareDocument ShareA

Link a shareable document asset into the configured campaign (DM only). Use campaign_document_list to inspect existing links, or document_upload to create an asset first. Upstream validates asset ownership, UUID, and sharing rights. Sharing broadens access without copying the asset. Duplicate-link behavior is upstream-controlled; do not assume retries are idempotent. Use document_unshare to revoke this link, not document_delete, which removes the asset everywhere. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
document_idYesShareable DOCUMENT asset UUID, not a local filename; must satisfy upstream ownership/scope checks.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as non-readonly, non-idempotent, and non-destructive, but the description goes further: it explains that sharing broadens access without copying, duplicate-link behavior is upstream-controlled, and retries cannot be assumed idempotent. It also documents success/error return shapes and MCP error behavior, adding real behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is moderately sized but front-loaded with the core purpose and then covers usage, behavioral caveats, and return formats in a logical order. Every sentence earns its place, though the return-format and MCP-error sentences add density.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter write operation with an output schema and rich annotations, the description covers the essential context: who may use it, what side effects occur, what makes it non-idempotent, how to undo it, and what response shape to expect. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the parameter description already explains that document_id must be a shareable DOCUMENT asset UUID, not a filename, and must satisfy ownership checks. The tool description adds no additional parameter semantics, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific action ('link a shareable document asset into the configured campaign'), scopes it to DM only, and contrasts it with siblings like document_unshare and document_upload. This makes the tool’s role immediately distinguishable from other document and campaign tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when/how guidance: use campaign_document_list to inspect existing links, document_upload to create an asset first, document_unshare to revoke, and explicitly warns against document_delete for this purpose. The DM-only restriction further clarifies appropriate invocation context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

document_unshareDocument UnshareA
DestructiveIdempotent

Remove one document share link from the configured campaign (DM only). Inspect campaign_document_list first: shared=false denotes a native document with no separate link to revoke. Use document_delete only to delete the asset everywhere. This leaves the asset, other links, local downloads, and GLOBAL/native read access intact. Repeating removes no additional link but may return a not-found error. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
document_idYesDocument asset ID with an explicit share link in this campaign; native documents cannot be unshared this way.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite annotations already marking destructive and idempotent hints, the description adds meaningful specifics: what remains intact (asset, other links, local downloads, global access), that repeats may error, and the success/failure return shape. It clarifies the idempotency nuance rather than contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but each sentence earns its place: purpose, prerequisites, alternatives, side-effect boundaries, idempotency behavior, and error modes. The most critical scoping information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-param mutating tool, this description is exceptionally complete. It covers permission context, preconditions, alternative tool routing, side effects, repeat-call behavior, and return/error semantics without requiring the agent to infer anything important.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already fully documents document_id with a clear description, so the baseline is satisfied. The description adds extra value by explaining how to recognize invalid targets via shared=false in campaign_document_list, which helps the agent pick the correct ID.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Remove one document share link from the configured campaign (DM only).' It clearly differentiates from sibling document_delete by explaining that unshare only revokes one link while deletion removes the asset everywhere.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use guidance: DM only, inspect campaign_document_list first, and avoid unsharing documents where shared=false. It also names document_delete as the correct alternative for full asset deletion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

document_updateDocument UpdateA
Destructive

Replace an entire txt/md document's content with upstream-enforced edit rights. Use document_read first to avoid losing text; use document_create for a new asset or document_upload for PDF. This is replacement, not merge-patching, and cannot edit PDF content. Consult campaign_document_list's canEdit when supplied; rights depend on asset scope and current membership, not uploader identity alone. Empty content clears the text. Repeated writes can update metadata or notifications; no full-operation idempotency is promised. Returns upstream REST data. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
contentYesComplete text, including empty text, at most 900 KiB UTF-8; rejects C0/DEL controls except TAB/LF/FF/CR.
document_idYesExisting editable text document asset ID, not a share-link ID.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already mark this as destructive, non-idempotent, and open-world, and the description adds substantial context beyond them: upstream-enforced edit rights, rights depending on asset scope and membership rather than uploader identity, empty content clearing text, metadata/notification side effects, and no promised full-operation idempotency. It also describes success, tool-body failure, and MCP argument-error response shapes. Nothing contradicts the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The definition is front-loaded with the core action and alternatives, and most sentences carry useful constraints or failure behavior. It is slightly dense and has minor redundancy around returning upstream REST data versus the explicit {ok:true,data} response shape, but it is not padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the destructive non-idempotent mutation, two required parameters, output schema, and permission complexity, the description covers the critical context an agent needs: replacement semantics, edit-rights dependency, alternatives, side effects, and error behavior. The output schema carries return-value detail, so the description's return notes are supplementary rather than missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaningful semantics beyond the schema: content replacement is wholesale rather than merge-patching, empty content clears the text, and PDF content cannot be edited. The document_id meaning is already well covered by the schema, so this is not a full 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: replace an entire txt/md document's content. It explicitly distinguishes this from merge-patching, PDF editing, reading, creating, and uploading, so the agent can identify the correct operation without opening sibling schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use guidance: call document_read first to avoid losing text, use document_create for a new asset, use document_upload for PDF, and consult campaign_document_list's canEdit when available. The exclusions and alternatives are unusually clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

document_uploadDocument UploadA

Upload an existing local PDF/txt/md file as a document asset using multipart REST. Use document_create for inline text, or document_share to link an existing asset. Reads the MCP server/container filesystem; client-local paths must be mounted. Creates an asset on each accepted call, so retries may duplicate it. Scope controls access: CAMPAIGN requires that campaign's DM; other scope rights are upstream-enforced. The server checks signatures and its size cap (default 50 MiB), with a shared upload/create limit of 30/minute/user by default. A 400 is preserved without fallback upload. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
nameNoOptional asset display name; null omits it so upstream uses its upload default.
tagsNoOptional tag strings joined by commas for multipart upload; null omits tags, while [] sends an empty field.
scopeNoVisibility/ownership scope: USER (default personal), CAMPAIGN, or GLOBAL; upstream enforces creation rights. CAMPAIGN uses campaign_id.USER
file_pathYesExisting .pdf/.txt/.md path on the MCP server filesystem; ~ is expanded. Container users must mount the file.
campaign_idNoExplicit campaign ID; null uses the configured campaign when scope=CAMPAIGN, otherwise omits the field. If supplied, it is forwarded for any scope.
descriptionNoOptional asset metadata text; null omits it. Upstream validates upload metadata.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only mark side effects and idempotency; the description adds major operational detail: retries duplicate assets, CAMPAIGN scope requires the DM, signature/size-cap checks, default 30/min rate limit, 400 preservation, and exact success/failure response shapes. This is far beyond annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Though long, every sentence carries a distinct operational fact: purpose, alternatives, filesystem constraint, idempotency warning, access control, limits, error behavior, and return format. It is front-loaded with purpose and routing and contains no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating, non-idempotent upload tool with 6 parameters, this description covers file source prerequisites, permissions, rate limits, duplication risk, return values, and error classification. Output schema exists and is further supplemented by explicit response documentation, so nothing an agent needs to invoke correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with rich parameter descriptions, so the baseline is 3. The description adds extra meaning for scope (CAMPAIGN requires that campaign's DM) and file_path (size cap and signature checks), justifying a small bump above baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence specifies the exact operation: uploading an existing local PDF/txt/md file as a document asset via multipart REST. It also differentiates from siblings by naming document_create for inline text and document_share for linking existing assets, so an agent can select the right tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit routing guidance: use document_create for inline text, document_share for linking existing assets, and this tool when uploading a file. It also states the filesystem prerequisite ('client-local paths must be mounted'), which is a clear when-not condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

events_pollEvents PollA
Read-onlyIdempotent

Read buffered campaign events and asynchronous write errors without consuming them. Use after WS writes; use chat_read for persisted chat history. May connect WS lazily, but does not change game state. Returns earliest seq > since first; advance using next_seq (latest_seq is its alias), not high_water_seq. Check gap for eviction from the 500-event buffer, cursor_reset after process restart, and has_more for pagination. Inspect system.error and relevant state to assess pending writes; broadcasts are not correlated ACKs. Buffered events remain available on connection failure, marked stale; this is not durable dice history. v1.5.0 role/map/token notifications are also forwarded; drag frames remain observations, not proof of persisted state. Repeated reads can include newly arriving events. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
limitNoMaximum events per page, 1..500; defaults to 100. Continue with next_seq when has_more is true.
sinceNoLast next_seq received, integer >=0; 0 starts at the oldest retained event. A cursor beyond this process resets to 0.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Although annotations already declare readOnly/idempotent/non-destructive, the description adds substantive behavior beyond them: lazy WS connection, no game-state mutation, stale marking on connection failure, 500-event eviction buffer, cursor_reset after restart, has_more pagination, and the warning that broadcasts are not correlated ACKs. This is unusually rich disclosure for a read tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first clause and every sentence carries operative information, but the passage is long and some material (the ok/data envelope) duplicates the output schema. Dense rather than padded, but denser than strictly needed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a stateful polling tool with an output schema already present, the description still covers the non-obvious failure modes an agent must handle: eviction gaps, cursor resets, pagination, stale-on-failure, and MCP-level vs tool-body error shapes. Nothing needed to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds value beyond it: it explains the since/next_seq relationship ('Returns earliest seq > since first') and the resume protocol ('advance using next_seq'). It leaves the limit semantics entirely to the schema, keeping it just short of a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read buffered campaign events and asynchronous write errors') with the crucial scope qualifier 'without consuming them'. It explicitly distinguishes itself from the sibling chat_read, so an agent can route without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('Use after WS writes') and names the alternative plus its selecting condition ('use chat_read for persisted chat history'). It further excludes a wrong use case ('this is not durable dice history'), which is the strongest form of when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

initiative_manageInitiative ManageA
Destructive

Modify campaign combatants, initiative values, order, or combat lifecycle. Use initiative_read for current state and events_poll for results/errors. Structural actions are DM-only; v1.4.0 also permits a controlling player to roll for an already added token before combat, subject to upstream checks. Older permission behavior is unverified. Actions may remove entries, clear state, reroll, or advance turns; the combined tool is not idempotent. add needs token_id/map_id; remove needs token_id; set needs token_id/map_id/value; reorder needs ordered_token_ids; start/next/end need only action. roll needs token_id and map_id and is gated to DND_5E/PATHFINDER_2E/SHADOWRUN_6E. The server derives system rolls; expression is a DM fallback, not a guaranteed override. CoC7e uses DEX ordering: use add/start or set. The dice_roll 2.1-second queue does not wrap initiative_manage; do not assume it throttles initiative rolls. On v1.5.0 caller-supplied characterName is ignored for initiative.roll; retain it for legacy behavior. Returns sent:true,confirmed:false,status:"pending" inside data: dispatch is not a business ACK. Read events_poll for results/system.error and inspect state before further action; never blindly resend. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
valueNoManual initiative number required for set; null means unspecified. Other actions ignore it.
actionYesOne of add, remove, roll, set, reorder, start, next, end; case-insensitive. Determines required companion parameters.
map_idNoMap containing the token; required for add/roll/set, otherwise unused (empty default).
token_idNoToken to add/remove/roll/set; required for those actions. Empty default is appropriate for reorder/start/next/end.
expressionNoOptional roll fallback for a DM when system derivation has no value; empty uses the server default. Ignored outside roll.
character_nameNoOptional display label passed only for roll; empty omits it and does not affect permissions.
ordered_token_idsNoNonempty ordered list of combatant token IDs for reorder; overrides value ordering. Null is appropriate for other actions.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this non-read-only, destructive, and non-idempotent, but the description adds substantial operational context: DM-only structural actions, v1.4.0 player-roll behavior, unverified legacy permissions, non-idempotent effects, and dispatch-pending semantics that are not a business ACK. It also explains the dice_roll queue exception and requires events_poll inspection before resending.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded, then details are grouped by usage, permissions, action parameters, and return behavior. It is dense and largely earns its length for a complex multi-action tool, though the return-value explanation partially overlaps the output schema and some version caveats could be tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an eight-action, permission-sensitive combat tool with seven parameters, the description covers purpose, alternatives, action-parameter requirements, gating rules, version caveats, dispatch semantics, and error handling. An output schema exists for return shape, and the description still adds the important ACK/pending interpretation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage the baseline would be 3, but the description goes far beyond the schema by mapping required companion parameters per action, gating roll to specific systems, clarifying expression as a fallback rather than an override, and noting version-specific character_name behavior and CoC7e DEX ordering.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb and resource set: modify campaign combatants, initiative values, order, or combat lifecycle. It also names initiative_read and events_poll as alternatives, so an agent can distinguish it from sibling read/poll tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly routes state reading to initiative_read and result/error checking to events_poll, and warns against blindly resending. It also gives permission context, but does not fully spell out when to choose between individual actions for a given player intent beyond the action-parameter mapping.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

initiative_readInitiative ReadA
Read-onlyIdempotent

Read initiative state without changing turn order or advancing combat. Use initiative_manage to modify combat and events_poll for broadcast history. Campaign members may read. By default, request a new WS state and wait up to two seconds; timeout returns state=null/stale=true, not proof that combat is inactive. refresh=false reads the current connection's cache and marks it stale. Repeated requests do not change initiative; WS authentication is still required. State is recipient-filtered and only current-generation data is treated as fresh. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
refreshNoTrue requests and waits for fresh state; false uses cached state, which may be absent or stale.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing timeout semantics (up to two seconds, timeout returns state=null/stale=true and is not proof combat is inactive), cache staleness under refresh=false, idempotence rationale, WS authentication requirement, recipient filtering, and freshness generation rules. This is exactly the kind of behavioral context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and alternative routing, then behavior and return contract. Dense but every sentence carries operational information; the only mild cost is readability from packing many clauses together.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers routing, permissions, timeout semantics, caching, idempotence, and the success/failure return envelopes even though an output schema exists. Nothing an agent needs to call this correctly appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so the schema already documents the single 'refresh' parameter, but the description adds real meaning: the two-second wait, the null/stale timeout result, and the stale-marking cache path. That is more than restating the schema, though not exhaustive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read initiative state') plus the key negative scope ('without changing turn order or advancing combat'), which immediately separates it from initiative_manage. An agent can identify this tool's role without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternatives and when to use them: initiative_manage for modifying combat, events_poll for broadcast history. Also states the access precondition ('Campaign members may read') and the refresh=true/false selection rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

map_createMap CreateA

Create a campaign map using existing image assets (DM only). Use map_list to inspect existing maps and map_switch to activate one; creation does not switch the current map. This creates a map with empty tokens and annotations, not an uploaded image. Upstream checks image access and normalizes asset URLs. Newer servers require MAP image assets, cap width/height at 500 squares, and default grid sizes outside 10..500 to 50. These limits are server-enforced. Each accepted call creates another map; do not blindly retry an uncertain result. CozyVTT supplies fogEnabled, globalIllumination, and explorationEnabled defaults (false); this tool intentionally has no inputs for them. Returns upstream {map} in data without a broadcast receipt. REST validation and permission errors retain upstream diagnostics. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
nameYesNonblank display name for the new map; upstream trims it.
widthYesMap width as a positive integer, in grid units.
heightYesMap height as a positive integer, in grid units.
grid_sizeNoPositive integer pixels per grid square; defaults to 50.
image_urlYesExisting map image asset ID or URL; upstream checks asset access. No file upload.
spirit_layer_urlNoOptional existing spirit-layer image asset ID or URL; null omits it.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and idempotentHint=false, and the description reinforces rather than repeats them by explaining the consequence: every accepted call produces a new map, so retries duplicate state. It also discloses the empty-token/empty-annotation initial state, upstream asset-access checks, server-enforced clamping of width/height and grid defaults, fixed false defaults for fog/illumination/exploration with no inputs to change them, and the difference between REST permission errors and tool-body failures.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and sibling routing are front-loaded, and every sentence carries operational content. It is dense to the point of being a wall of text, however, and the return-value/error sentences could be tightened given an output schema exists.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a six-parameter non-idempotent mutation with an output schema, it covers everything an agent needs: assets must pre-exist (no upload), DM-only authorization, clamping behavior, non-idempotency, and the split between upstream diagnostics and {ok:false} tool-body errors.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning the schema cannot express: dimensions are capped at 500 squares and grid sizes outside 10..500 are coerced to 50, both server-enforced. It also explains that fogEnabled/globalIllumination/explorationEnabled are deliberately absent as inputs, pre-empting a hunt for missing parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource plus a scope qualifier: "Create a campaign map using existing image assets (DM only)." It immediately distinguishes itself from map_list and map_switch, and the phrase "not an uploaded image" rules out a plausible misreading of image_url.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: use map_list to inspect, map_switch to activate, and notes that creation does not switch the current map. It also gives a genuine when-not-to-call rule: "Each accepted call creates another map; do not blindly retry an uncertain result," which directly explains the non-idempotent annotation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

map_deleteMap DeleteA
DestructiveIdempotent

Delete a campaign map and its stored tokens and map state (DM only). Use map_list to inspect maps first; use map_switch to select another current map before deletion. Upstream rejects deletion of the current map with HTTP 400. Use token_delete to remove only one token instead of the entire map. Deletion is destructive and has no undo tool. Repeating leaves the map absent but may return a not-found error. Returns upstream {message} in data without a broadcast receipt; REST permission and resource errors retain upstream diagnostics. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
map_idYesMap ID in the configured campaign to delete; must not be the current map.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the annotations: it discloses that deletion is destructive with no undo, that repeating the call may return a not-found error, that the current map cannot be deleted, and that success returns {ok:true,data} while failures return {ok:false,error}. It also explains the upstream response shape and error handling, which is valuable context not present in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well-organized: it front-loads the core action and constraints, then covers alternatives, error behavior, and return format. Every sentence adds information, though the length is slightly high for a single-parameter tool. Still, the density is justified by the destructive nature and error semantics.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive single-parameter tool, the description covers all essential context: prerequisites (map_list, map_switch), the current-map restriction, idempotency behavior, return shapes, and error handling. The output schema exists, so return values need not be detailed further. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents map_id with 100% coverage, so the baseline is 3. The description adds the critical constraint that map_id must not be the current map, which is not in the schema description. This extra semantic guidance justifies a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('delete') and resource ('campaign map'), and explicitly distinguishes itself from token_delete and map_switch. It also names the sibling map_list for inspection, making the tool's purpose and scope unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance: inspect with map_list first, use map_switch to select another current map before deletion, and use token_delete for single-token removal. It also warns that upstream rejects deletion of the current map with HTTP 400, which is a clear exclusion condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

map_listMap ListA
Read-onlyIdempotent

List maps accessible in the configured campaign to choose a map ID and inspect dimensions. Use map_switch to activate one; listing does not switch maps or place tokens. Read-only for campaign members; non-DMs may see only the current map. v1.5.0 map setting flags pass through unchanged. Repeated calls leave game state unchanged. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive/openWorld, so the bar is lower, yet the description adds real value: permission nuance ('Read-only for campaign members; non-DMs may see only the current map') and the explicit non-effects (no switching, no token placement). 'Repeated calls leave game state unchanged' merely restates idempotentHint, which costs it a point.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then alternative routing, then permissions, then failure modes — a sensible ordering with no padding. Slight redundancy remains: idempotency is restated despite idempotentHint, and the return-shape sentence is partly redundant with the output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read tool with a full annotation set and an output schema, the description supplies everything an agent still needs: scope, the sibling it is not, caller-dependent visibility, and the distinction between tool-body failures and MCP argument errors.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there are no parameter semantics to explain and the description neither omits nor misstates anything. Baseline 4 applies; nothing in the schema needs compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('List maps accessible in the configured campaign') plus the agent-facing goal ('choose a map ID and inspect dimensions'), which distinguishes it from the related write tool map_switch. An agent can route correctly without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternative and the condition that selects it: 'Use map_switch to activate one; listing does not switch maps or place tokens.' It also contextualizes why to call it (to obtain a map ID). It stops short of spelling out a when-not-to-use case, but the alternative routing is unusually clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

map_switchMap SwitchA
Destructive

Set the current campaign map through REST, then notify via WS map.change (DM only). Use map_list to choose an existing map; token_move changes a token, not the active map. REST persistence and WS dispatch are separate: persisted=true does not prove clients received the change. A WS failure returns ok=false with data.persisted=true; do not replay or roll back the saved change. Broadcast receipt remains sent=true, confirmed=false,status="pending"; inspect events_poll for results/errors, not an ACK. Repeating may repeat notifications even when the current map is already correct. v1.5.0 retains the REST-first current-map rule. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
map_idYesExisting map ID in the configured campaign, obtained from map_list; becomes the active map for the table.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructive=true, idempotentHint=false, and openWorldHint=true, but the description goes well beyond them: it discloses that REST persistence and WS dispatch are separate, that persisted=true does not prove clients received the change, that a WS failure yields ok=false with data.persisted=true, and that the agent must not replay or roll back. It also explains the broadcast receipt semantics (sent=true, confirmed=false, status='pending') and directs the agent to events_poll rather than expecting an ACK. This is unusually rich operational context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded and almost every sentence carries operational weight, but the prose is dense and run-on in places, and the version note ('v1.5.0 retains the REST-first current-map rule') is borderline filler for a one-parameter tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the description does not need to explain return values, yet it usefully clarifies the ok=true/ok=false envelope and the distinction between tool-body failures and MCP argument-schema errors. Combined with the failure-handling guidance, it is effectively complete, with only minor redundancy against the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and there is only one parameter, so the schema already documents that map_id is an existing map ID from map_list. The description adds no syntax or format detail beyond that, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource: 'Set the current campaign map through REST, then notify via WS map.change.' It explicitly distinguishes itself from siblings, noting map_list is for choosing an existing map and token_move changes a token rather than the active map. An agent can select this tool without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Alternatives are named with the condition that selects them: use map_list to pick an existing map, and token_move is explicitly not for the active map. The 'DM only' constraint and the warning that repeating may re-notify even when the map is already correct give clear when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saved_roll_createSaved Roll CreateA

Save a private dice-expression macro for the current user and campaign. Use dice_roll to execute an expression; use saved_roll_update to edit an existing macro without creating another. Members manage only their own macros. The server parses expressions and limits each user to 50 per campaign. Creation is serialized only within this process; each accepted call may create another macro. No dice are rolled and no campaign-visible message is sent by this tool. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
nameYesMacro display label, trimmed to 1..60 characters.
expressionYesSaved dice expression, trimmed to 1..200 characters; upstream parses it without rolling.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the annotations by disclosing that no dice are rolled, no campaign-visible message is sent, the server enforces a 50-per-campaign limit, and creation is not globally serialized. These are important side-effect and concurrency traits not captured by readOnlyHint, idempotentHint, or destructiveHint alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than minimal, but each sentence contributes useful context such as alternatives, side-effect behavior, limits, and return shape. It is front-loaded with the core purpose, though the concurrency and MCP-error details could be trimmed without losing essential guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with output schema, the description is complete: it states ownership, limits, side effects, return conventions, and error behavior. An agent has enough information to decide when to call it and what to expect.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already documents both parameters with trimming constraints. The description reinforces that the expression is parsed without rolling, but it does not add meaning beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Save a private dice-expression macro for the current user and campaign.' It also explicitly distinguishes itself from dice_roll and saved_roll_update, making the tool's purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly tells the agent when to use this tool versus alternatives: use dice_roll to execute, use saved_roll_update to edit, and this tool to create. It also clarifies that members manage only their own macros, providing scoping guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saved_roll_deleteSaved Roll DeleteA
DestructiveIdempotent

Delete your Saved Roll from the configured campaign. Use saved_roll_list to identify it or saved_roll_update to change it without deletion. Any member may delete their own macro; cross-user/cross-campaign access returns 404. Destructive to the macro only, not roll history. Repeating leaves it absent but may return a not-found error; it does not roll dice. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
macro_idYesSaved Roll ID owned by the authenticated user in the configured campaign; other users/campaigns are inaccessible.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal destructive and idempotent behavior, and the description adds substantial context: deletion is limited to the macro only, roll history is unaffected, repeated invocation may yield a not-found error, and no dice are rolled. No contradiction with the annotations exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and every sentence adds value: action first, then alternatives, access constraints, destructive scope, idempotency behavior, and error/response format. No filler or redundant restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter deletion tool with an output schema and rich annotations, the description is fully adequate. It covers prerequisites, access boundaries, side effects, retry behavior, and return shapes, leaving no operational ambiguity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the macro_id parameter is already documented as owned by the authenticated user in the configured campaign. The description reinforces the ownership constraint but adds little beyond the schema, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the specific action ('Delete'), resource ('your Saved Roll'), and scope ('configured campaign'). It is clearly distinguished from the sibling update/list operations by naming the deletion action and contrasting it with saved_roll_update.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to saved_roll_list for identification and saved_roll_update for alteration without deletion. It also clarifies ownership constraints, cross-user/cross-campaign 404 behavior, and repeated-deletion outcomes, giving clear when-to-use and retry guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saved_roll_listSaved Roll ListA
Read-onlyIdempotent

List complete Saved Roll macros owned by the current user in this campaign. Use dice_roll with a returned expression to execute it, or saved_roll_update to edit. Read-only for campaign members; no individual get is needed and no dice are rolled. Repeating the list does not consume macros. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false, and the description adds context that no dice are rolled, macros are not consumed, and no individual get is needed. It also discloses success and error return shapes. The description does not contradict annotations and adds meaningful behavioral detail beyond the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is tightly written, with every sentence contributing: scope, usage pointers, read-only behavior, non-consumption, and return format. It is front-loaded with the core purpose and keeps alternatives and error handling to a short tail. No filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read-only listing tool with a rich annotation set and output schema, the description is nearly complete. It covers purpose, follow-up actions, side-effect-free behavior, and error envelope. It does not enumerate exact response fields, but the presence of an output schema lessens that need; a short note on pagination or ordering would push it to a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the schema carries no parameter burden. The description adds useful return and usage semantics: it explains what the list contains, what it does not do, and how the response is structured. This compensates adequately for the absence of parameter-level documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'List complete Saved Roll macros owned by the current user in this campaign.' It clearly distinguishes from sibling tools like saved_roll_create, saved_roll_update, and saved_roll_delete, and even directs users to dice_roll and saved_roll_update for follow-up actions. This is unambiguous and contextually grounded.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly explains when to use this tool: to list saved rolls, without needing an individual get, and without rolling dice. It also mentions that repeating the list does not consume macros and that it is read-only for campaign members. This provides clear usage context and effective routing relative to dice_roll and saved_roll_update.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saved_roll_updateSaved Roll UpdateA
Destructive

Change the name or expression of your Saved Roll in this campaign. Use saved_roll_list to find its ID; use dice_roll to execute it. Supply at least one field; null leaves that field unchanged. Upstream validates expressions and enforces per-user/per-campaign ownership. Replacing values does not roll dice; repeated writes may change update metadata, so full-operation idempotency is not guaranteed. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
nameNoReplacement display label, trimmed to 1..60 characters; null preserves it. At least one of name/expression is required.
macro_idYesExisting Saved Roll ID owned by the current user in this campaign.
expressionNoReplacement expression, trimmed to 1..200 characters and parsed upstream; null preserves it. At least one field is required.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations, it discloses that replacing values does not roll dice, that repeated writes may change update metadata and thus full idempotency is not guaranteed, and that upstream validates expressions and enforces ownership. It also explains the success/error return envelope, which is valuable context not present in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well-organized: action first, then sibling routing, then update semantics, then behavioral caveats, then return format. Every sentence earns its place and no unnecessary filler is present.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a partial-update mutation tool, this is complete: what it updates, how to find the target ID, what happens with nulls and multiple writes, ownership validation, and both success and failure response shapes. The presence of an output schema does not create a gap because the description covers the relevant behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents name, macro_id, and expression meanings plus null-count semantics. The description adds the useful pointer to use saved_roll_list to find macro_id, but otherwise largely restates what the schema already covers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Change') and names the exact resource and fields ('name or expression of your Saved Roll in this campaign'). It also distinguishes itself from related siblings by pointing to saved_roll_list for ID lookup and dice_roll for execution.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly tells the agent when to use this tool ('Change the name or expression') and names alternatives with their conditions: use saved_roll_list to find the ID and dice_roll to execute. It also clarifies the partial-update contract: supply at least one field, null leaves it unchanged.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

session_listSession ListA
Read-onlyIdempotent

List this campaign's latest 50 sessions in descending sessionNumber order, including active sessions. Use session_manage for lifecycle changes and session_notes_update for recaps. Read-only for members; notes are shared with all members, and repeated reads do not end or resume sessions. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only/idempotent/non-destructive, and the description adds concrete non-obvious behavior: notes are shared with all members and repeated reads do not end or resume sessions. It also discloses the success/error return envelope, going beyond the annotation hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence carries distinct information: scope, sibling routing, safe-read behavior, and failure semantics. There is no filler, and the most important functional scope is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With zero parameters and strong annotations plus an output schema, the description covers all remaining decision-relevant details: result ordering/count, active-session inclusion, shared notes, read-only guarantees, and MCP error behavior. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the schema needs no help; the description's mention of the campaign scope is context rather than parameter documentation. Baseline 4 applies because there is no parameter burden to compensate for.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource pair and exact scope: 'List this campaign's latest 50 sessions in descending sessionNumber order, including active sessions.' This leaves no ambiguity about what the tool returns and contrasts with sibling session tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly routes lifecycle changes to session_manage and recaps to session_notes_update, telling an agent when not to call this tool. It also clarifies that reads are safe and repeated reads have no lifecycle side effects, which is strong when-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

session_manageSession ManageA
Destructive

Start, pause, or end a campaign session through REST (DM only). Use session_list to inspect history and session_notes_update to edit or clear a recap without another lifecycle transition. start creates a session; pause/end resolve campaign.activeSession.id and fail if none exists. Lifecycle changes are not guaranteed idempotent: do not repeat start/end to repair notes. notes and save_state apply only to end; other actions reject nondefault values. End notes are campaign-wide, and empty text does not clear an existing recap. save_state requests the upstream end-of-session snapshot; it is not a bridge-side backup. Returns upstream REST data; it does not wait for a WS business ACK. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
notesNoShared recap for end, at most 2000 characters; null omits it. Empty end text does not clear old notes; use session_notes_update.
actionYesLifecycle transition: start, pause, or end, case-insensitive. Pause/end target the currently active session.
save_stateNoTrue (default) requests saving state on end; false skips that snapshot. Must remain true for start/pause.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already say destructiveHint=true and idempotentHint=false, but the description goes further: it explains non-idempotency in practical terms, discloses that notes and save_state apply only to end, and clarifies that save_state is not a bridge-side backup. It also warns that empty end text does not clear an existing recap and that the tool does not wait for a WS business ACK. These are meaningful behavioral nuances beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place: purpose, sibling routing, lifecycle rules, notes/save_state constraints, and return format. It is front-loaded with the core action and ends with structured return behavior, with no fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a non-idempotent, destructive, state-changing tool with conditional parameters, the description covers what is needed: when each action applies, what fails, how notes and save_state behave differently per action, return success/error shapes, and the DM-only restriction. The presence of an output schema means detailed return fields are not required, and the description still summarizes the success/error envelope.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, which establishes a baseline of 3. The description adds extra semantics beyond the schema: notes are 'campaign-wide', nondefault notes/save_state values are rejected for start/pause, and save_state requests an 'upstream' snapshot rather than a local backup. These details enhance understanding of all three parameters, so a score above baseline is warranted.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource pair ('Start, pause, or end a campaign session') and immediately scopes the tool to 'REST (DM only)', which clearly distinguishes it from read-only or notes-related tools. It also explicitly names the two most relevant siblings (session_list and session_notes_update), so an agent can differentiate without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly instructs when to use alternatives: 'Use session_list to inspect history and session_notes_update to edit or clear a recap without another lifecycle transition.' It also explains that pause/end fail if no active session exists, and warns against repeating start/end to repair notes because changes are not idempotent. This is concrete, actionable usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

session_notes_updateSession Notes UpdateA
Destructive

Replace a session's shared recap without another lifecycle transition (DM only). Use session_list to find the ID; use session_manage to start/pause/end instead. All campaign members can read notes. Empty text after upstream trimming clears the recap, unlike empty notes on session_manage end. Does not end the session or broadcast a recap event. Repeated writes may alter metadata, so full-operation idempotency is not guaranteed. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
notesYesComplete replacement recap, at most 2000 characters before trimming; empty or whitespace-only text clears it upstream.
session_idYesExisting session ID in the configured campaign, obtained with session_list; need not be the active session.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal destructive and non-idempotent behavior, and the description adds meaningful details: repeated writes may alter metadata, empty text clears the recap, the tool does not end the session or broadcast a recap event, and it explains the distinction from session_manage. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence is informative and earns its place. The description front-loads the core purpose, then gives usage routing, behavioral caveats, and return/error semantics in a compact but complete block.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's destructive and non-idempotent nature, the description is remarkably complete: it covers lifecycle impact, permissions, ID discovery, clearing behavior, idempotency caveat, return shape on success, tool-body failures, and schema-error handling. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds a useful edge-case nuance by explaining that empty text clears the recap 'unlike empty notes on session_manage end,' and it reinforces the complete-replacement semantics. This goes slightly beyond the schema, but most parameter meaning is already present there.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Replace a session's shared recap.' It also distinguishes itself from the lifecycle tool by saying 'without another lifecycle transition' and later 'Does not end the session or broadcast a recap event.' This clearly differentiates it from session_manage.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit direction: use session_list to find the ID, and use session_manage to start/pause/end instead. It also notes the DM-only restriction and clarifies that all campaign members can read notes, which helps an agent decide whether this tool is appropriate for the situation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

token_addToken AddA

Create a manually configured token on a campaign map (DM only). Use token_place_creature for a library template's name/image, token_move for an existing token, and character_create when a new sheet is needed. This creates only a token; character_id optionally links an existing sheet. Position uses map units; upstream checks map bounds and layer. Width/height are integer sizes in 1..10. Newer servers require whole-square coordinates and clamp the token footprint; use returned coordinates and preserve server refusals instead of rounding input. visible and controlled_by govern display/control subject to server permissions. When controlled_by is omitted, v1.5.0 may autoassign the bound character owner; null means omit the wire field, not send null. Image access and campaign assignment remain upstream checks. REST returns persisted=true,broadcast_confirmed=false; inspect events_poll or the VTT for visibility, since persistence does not confirm a broadcast. Every accepted call creates another token, so repeated calls are not idempotent. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
xYesHorizontal position in map units; upstream requires 0 <= x < map width.
yYesVertical position in map units; upstream requires 0 <= y < map height.
nameYesDisplay label for the new token; upstream requires nonempty text.
layerNoRendering layer: token (default) or spirit; upstream validates it and applies visibility rules.token
widthNoHorizontal token size in map units, integer 1..10; defaults to 1.
heightNoVertical token size in map units, integer 1..10; defaults to 1.
map_idYesDestination map ID in this campaign; discover it and its dimensions with map_list.
visibleNoTrue requests a visible token; false requests a hidden token. Layer and role may further restrict visibility.
image_urlYesToken artwork URL passed upstream; empty text is accepted as a placeholder by v1.4.0, with older behavior unverified.
character_idNoExisting sheet ID to link; empty string creates a token without a character link.
controlled_byNoUser ID allowed to control the token, subject to upstream checks; null omits explicit assignment.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes far beyond annotations: explains non-idempotency ('every accepted call creates another token'), coordinate clamping and whole-square requirements on newer servers, the controlled_by autoassign/null-vs-omit distinction, REST persisted=true but broadcast_confirmed=false, and the recommendation to inspect events_poll or the VTT. Also describes upstream permission/bounds/image checks and the ok/error return shape. This is exactly the behavior an agent cannot infer from annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but well structured, with purpose and alternatives first, then behavioral caveats, then return semantics. It is longer than typical but nearly every sentence carries operational value for an 11-parameter, version-sensitive mutation tool. Minor redundancy around persistence/broadcast could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, yet the description still adds the important success/error distinction (tool-body {ok:false,error} versus MCP argument-schema errors) and the broadcast caveat. Combined with DM-only scope, upstream checks, and idempotency, an agent has what it needs to call this correctly and interpret ambiguous results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3; the description adds value by clarifying map-unit coordinates, integer 1..10 width/height, the controlled_by null-versus-omitted wire semantics, and what character_id linking does. It doesn't re-document every parameter, but the added semantics are meaningful beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb, resource, scope, and audience: 'Create a manually configured token on a campaign map (DM only).' It immediately names the sibling tools it is not (token_place_creature, token_move, character_create), so an agent can select it without opening other schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit routing: use token_place_creature for library templates, token_move for existing tokens, character_create when a new sheet is needed, and this tool only for a manually configured token. That covers when to use and when not to use in a single front-loaded sentence.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

token_deleteToken DeleteA
DestructiveIdempotent

Delete one token from a campaign map (DM only). Use token_move to reposition a token instead. Use token_hp_update for a signed sheet HP adjustment through WS: that tool takes a character ID, whereas this tool takes a map token ID. Deletion removes the placed token, not its linked character sheet or HP. v1.5.0 also removes its combatants and repairs initiative order; do not send a second initiative write. It is destructive and has no undo tool. Repeating leaves the token absent but may return a not-found error. Returns upstream {message} in data without a broadcast receipt; REST permission and resource errors retain upstream diagnostics. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
map_idYesMap ID containing the token in the configured campaign.
token_idYesMap token ID to remove, not a character sheet ID.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint and idempotentHint, and the description adds substantial context beyond that: what destruction entails (removes the placed token, not the linked sheet/HP; removes combatants and repairs initiative order), no undo tool, and repeat-call behavior (token absent but may return not-found). All of this is consistent with the annotations rather than contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the alternative tools, then back-loaded with behavioral and return details. It is dense but mostly earns its place; a couple of clauses (restating destructiveness, error paragraph) slightly overlap with what annotations and the output schema already carry.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Very complete: it covers the mutation's side effects, idempotent-effect behavior, the {ok/data/error} return contract, and where diagnostics surface, while an output schema exists to carry structured returns. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both params are fully documented there, including the token-vs-character-ID distinction. The description reinforces that same distinction but adds no new syntax or format detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource and scope ('Delete one token from a campaign map (DM only)'), and explicitly names the sibling alternatives (token_move, token_hp_update). An agent can distinguish this from token_move/token_add without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: use token_move to reposition, token_hp_update for HP edits, and clarifies token_delete takes a map token ID rather than a character ID. It even warns not to send a second initiative write, which is actionable when-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

token_hp_updateToken Hp UpdateA
Destructive

Apply a signed HP delta to a character sheet through WS, not to a token ID. Use character_get to inspect HP or character_update for an absolute sheet patch. Upstream requires character ownership or DM authority and campaign assignment; its system-specific HP rules determine the result. Positive delta heals, negative delta damages. v1.5.0 permits the owner or DM, never a spectator. Repeating applies the delta again and is not idempotent. Returns sent:true,confirmed:false,status:"pending" inside data: dispatch is not a business ACK. Read events_poll for results/system.error and inspect state before further action; never blindly resend. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
deltaYesSigned integer HP adjustment: positive heals, negative damages, zero requests no numerical change. Upstream applies system limits.
character_idYesCampaign-assigned character ID whose sheet HP is changed; do not pass a map token ID.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (destructive, non-idempotent, openWorld), and the description goes well beyond them: it discloses the ownership/DM authorization requirement, the spectator exclusion, that repetition re-applies the delta, and the critical async distinction that a 'sent:true,confirmed:false,status:pending' dispatch is not a business ACK. That pending-vs-confirmed semantics is exactly the kind of behavioral context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and the sibling routing are front-loaded, and every section carries real operational weight (auth, idempotency, async ACK, error modes). It is somewhat dense and repeats return-shape information ('sent:true,confirmed:false' then '{ok:true,data}') that an output schema already covers, which costs a point but does not obscure the essential guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, non-idempotent, async, authorization-gated mutation, the description supplies everything needed: the target entity, the auth requirement, idempotency warning, the pending-vs-confirmed dispatch model, follow-up via events_poll, and the success/failure envelope shapes. Nothing an agent needs to invoke it safely is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters in detail (signed delta semantics, campaign-assigned character ID vs map token ID). The description restates 'positive heals, negative damages' and the token-vs-character distinction without adding syntax or format detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb+resource ('Apply a signed HP delta to a character sheet') and immediately corrects the misleading name by stating it operates on a character sheet, 'not to a token ID.' It explicitly routes to siblings (character_get for inspection, character_update for an absolute patch), so an agent can distinguish it without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It names the alternatives and the conditions that select them ('use character_get to inspect HP or character_update for an absolute sheet patch'), and adds an operational rule for the async flow ('Read events_poll for results/system.error ... never blindly resend'). When-to-use, when-not-to-use, and post-call behavior are all explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

token_moveToken MoveA
Destructive

Set an existing token's absolute position through REST. Use token_add to create a token or map_switch to change the active map. The bridge rejects SPECTATOR/unknown roles; upstream requires DM or the controlling player. The same coordinates produce the same position, but repeated writes may produce notifications. Returns persisted=true,broadcast_confirmed=false; REST does not itself emit map.changed. On both REST and WS token.move, PLAYER must use the current campaign map; DM may use any map of this campaign. Upstream applies control, plane, and session-state restrictions; returned token fields may be null. Newer servers require whole-square coordinates and may clamp the footprint at map edges. Read the returned position rather than assuming the requested one. Inspect events_poll or the VTT before assuming others saw the move; this result is not a correlated broadcast ACK. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
xYesAbsolute horizontal position in map units; upstream requires 0 <= x < map width.
yYesAbsolute vertical position in map units; upstream requires 0 <= y < map height.
map_idYesMap ID containing the existing token. On both REST and WS token.move, PLAYER must use the current campaign map; DM may use any map of this campaign.
token_idYesExisting token ID on that map; this is not a character or creature ID.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations present, the description still adds substantial non-structured context: bridge role rejection, upstream control/plane/session restrictions, null token fields, whole-square coordinate enforcement, footprint clamping at map edges, and the crucial caveat that the write is not a correlated broadcast ACK (broadcast_confirmed=false, no map.changed emitted by REST). It also explains why repeated identical writes are not a no-op (notifications), which reconciles with idempotentHint=false rather than contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core operation, and nearly every sentence adds an operational constraint or failure mode. It is dense and somewhat run-on, with the error-contract sentence trailing at the end where it is least visible, but no sentence is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with real upstream permission, coordinate, and broadcast semantics, the description covers preconditions, edge-case behavior, and the success/failure envelope. It goes beyond what the output schema alone conveys by warning against assuming the move was observed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema carries the per-parameter burden and 3 would be the baseline. The description still adds meaning beyond the schema: whole-square coordinate requirements on newer servers, clamping of the token footprint at map edges, and the instruction to read the returned position rather than trust the requested one. Some sentences duplicate schema text verbatim (the PLAYER/DM map line on map_id).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: "Set an existing token's absolute position through REST." It immediately distinguishes itself from token_add (creation) and map_switch (active map), so an agent can route without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the sibling alternatives explicitly (token_add for creating, map_switch for changing the active map) and states the role conditions under which this tool applies (DM may use any campaign map, PLAYER only the current campaign map). It also points to events_poll/VTT as the verification path. It stops short of explicitly stating exclusion cases for the move itself, so a 4 rather than 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

token_place_creatureToken Place CreatureA

Create a visible 1x1 token from a library template's name and image (DM only). Use creature_search to obtain a template ID; use token_add for custom size, layer, controller, visibility, or a character link. This reads the template and copies only name/image into a token: it does not create a sheet or copy creature stats. Fails before creation if no usable image exists. Position must be within the map. Each accepted call creates another token. Returns upstream REST data without a broadcast receipt; the template read is DM-only and upstream validates image access. Use events_poll or the VTT to inspect subsequent visibility. Returns {ok:true,data} on success; tool-body failures return {ok:false,error} with optional diagnostic data. Argument-schema errors are MCP errors.

NameRequiredDescriptionDefault
xYesHorizontal position in map units; upstream requires 0 <= x < map width.
yYesVertical position in map units; upstream requires 0 <= y < map height.
map_idYesDestination map ID in this campaign; discover dimensions through map_list.
creature_idYesLibrary template ID from creature_search; the template must have a usable imageUrl, tokenImageUrl, or image.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=true), and the description goes well beyond them: DM-only read, failure before creation when no usable image exists, map-bound position constraint, per-call token creation, no broadcast receipt, upstream image-access validation, and a pointer to events_poll for visibility. It also discloses return shapes and the tool-body vs MCP error distinction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose and routing guidance before the behavioral detail, and most sentences carry distinct information (failure mode, DM-only, repeat-creation, error shapes). It is somewhat dense and there is minor redundancy re-stating the return shape despite an output schema, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-required-param mutation with full schema coverage, annotations, and an output schema, the description covers every decision-relevant gap: prerequisites, DM-only scope, failure conditions, non-idempotency, and how to observe results. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all four parameters including the image-source requirement and the x/y bounds. The description's 'Position must be within the map' and image references restate rather than extend the schema, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Create a visible 1x1 token from a library template') and immediately scopes it (DM only). It explicitly contrasts itself with the sibling token_add, so an agent can differentiate the two without reading either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'use creature_search to obtain a template ID' for the prerequisite, and 'use token_add for custom size, layer, controller, visibility, or a character link' for the alternative. This is a textbook when/when-not/alternative breakdown.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.5.0
    • Changedtoken_move1 field changed
      • changedInput schema / properties / map_id / description
        Previous value: -"Map ID containing the existing token, not necessarily the active map."New value: +"Map ID containing the existing token. On both REST and WS token.move, PLAYER must use the current campaign map; DM may use any map of this campaign."
  2. 4 tool updatesv0.4.0
    • Addedcharacter_delete
    • Addedmap_create
    • Addedmap_delete
    • Addedtoken_delete
  3. 38 tool updatesv0.3.0
    • Addedcampaign_document_list
    • Addedcampaign_get
    • Removedcampaign_status
    • Addedcampaign_transfer_dm
    • Changedcharacter_create3 fields changed
      • addedInput schema / properties / data / description
        Added value: +"Optional initial sheet-field object for the campaign system, not a nested request patch; null omits it and lets upstream choose defaults."
      • addedInput schema / properties / name / description
        Added value: +"New sheet display name, 1..200 characters; passed without trimming."
      • addedInput schema / properties / token_image_url / description
        Added value: +"Optional artwork URL for the sheet; empty string omits it. This does not create a map token."
    • Changedcharacter_get1 field changed
      • addedInput schema / properties / character_id / description
        Added value: +"Existing character ID, normally discovered with character_list; the sheet may use its own gameSystem."
    • Addedcharacter_hitdice_spend
    • Changedcharacter_update2 fields changed
      • addedInput schema / properties / character_id / description
        Added value: +"Existing sheet ID to modify; upstream enforces owner or campaign DM access."
      • addedInput schema / properties / data / description
        Added value: +"Nonempty request patch containing only name, data, tokenImageUrl. Sheet changes go inside data as an object; arrays replace, null is explicit."
    • Changedcharacter_validate1 field changed
      • addedInput schema / properties / character_id / description
        Added value: +"Existing character ID owned by the authenticated user; fixed-system validation is required upstream."
    • Changedchat_read3 fields changed
      • addedInput schema / properties / cursor
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Opaque pagination.nextCursor from the previous response; null starts with the latest page. Do not construct cursors or offsets."
        +}
      • addedInput schema / properties / limit / description
        Added value: +"Page size, 1..100 messages; defaults to 20."
      • removedInput schema / properties / offset
        Removed value: -{
        -  "default": 0,
        -  "type": "integer"
        -}
    • Changedchat_send2 fields changed
      • addedInput schema / properties / content / description
        Added value: +"Nonblank message text, at most 2000 characters; whitespace is preserved when sent."
      • addedInput schema / properties / type / description
        Added value: +"Message category: DM (default narration) or PLAYER. This does not change the authenticated role."
    • Changedcreature_search5 fields changed
      • addedInput schema / properties / cr / description
        Added value: +"Challenge-rating filter passed as text, for example 1/2 or 3; empty omits it. Applicability is upstream-defined."
      • addedInput schema / properties / limit / description
        Added value: +"Requested page size, normally 1..100; defaults to 20. Values above 100 are capped; other validation is upstream."
      • addedInput schema / properties / offset / description
        Added value: +"Number of search results to skip, normally >=0; defaults to 0. Forwarded without local range validation."
      • addedInput schema / properties / search / description
        Added value: +"Name/search filter passed upstream; empty string omits the filter."
      • addedInput schema / properties / source / description
        Added value: +"srd or custom (case-insensitive); empty chooses both for DND_5E and custom for other or flexible campaigns."
    • Changeddice_roll4 fields changed
      • addedInput schema / properties / character_name
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional display attribution (wire characterName), not a character ID or permission credential; null omits it."
        +}
      • addedInput schema / properties / expression / description
        Added value: +"Server-parsed dice expression, e.g. 1d20+5, 2d6, or 4d6kh3; invalid syntax is reported asynchronously."
      • addedInput schema / properties / is_secret / description
        Added value: +"False publishes to the campaign; true requests secret delivery to the roller and DMs (wire field secret)."
      • addedInput schema / properties / purpose / description
        Added value: +"Optional broadcast label explaining the roll; empty string omits it, without changing dice calculation."
    • Addeddocument_create
    • Addeddocument_delete
    • Addeddocument_list
    • Addeddocument_read
    • Addeddocument_share
    • Addeddocument_unshare
    • Addeddocument_update
    • Addeddocument_upload
    • Changedevents_poll2 fields changed
      • addedInput schema / properties / limit / description
        Added value: +"Maximum events per page, 1..500; defaults to 100. Continue with next_seq when has_more is true."
      • addedInput schema / properties / since / description
        Added value: +"Last next_seq received, integer >=0; 0 starts at the oldest retained event. A cursor beyond this process resets to 0."
    • Changedinitiative_manage7 fields changed
      • addedInput schema / properties / action / description
        Added value: +"One of add, remove, roll, set, reorder, start, next, end; case-insensitive. Determines required companion parameters."
      • addedInput schema / properties / character_name / description
        Added value: +"Optional display label passed only for roll; empty omits it and does not affect permissions."
      • addedInput schema / properties / expression / description
        Added value: +"Optional roll fallback for a DM when system derivation has no value; empty uses the server default. Ignored outside roll."
      • addedInput schema / properties / map_id / description
        Added value: +"Map containing the token; required for add/roll/set, otherwise unused (empty default)."
      • addedInput schema / properties / ordered_token_ids / description
        Added value: +"Nonempty ordered list of combatant token IDs for reorder; overrides value ordering. Null is appropriate for other actions."
      • addedInput schema / properties / token_id / description
        Added value: +"Token to add/remove/roll/set; required for those actions. Empty default is appropriate for reorder/start/next/end."
      • addedInput schema / properties / value / description
        Added value: +"Manual initiative number required for set; null means unspecified. Other actions ignore it."
    • Addedinitiative_read
    • Removedinitiative_state
    • Changedmap_switch1 field changed
      • addedInput schema / properties / map_id / description
        Added value: +"Existing map ID in the configured campaign, obtained from map_list; becomes the active map for the table."
    • Addedsaved_roll_create
    • Addedsaved_roll_delete
    • Addedsaved_roll_list
    • Addedsaved_roll_update
    • Addedsession_list
    • Changedsession_manage3 fields changed
      • addedInput schema / properties / action / description
        Added value: +"Lifecycle transition: start, pause, or end, case-insensitive. Pause/end target the currently active session."
      • addedInput schema / properties / notes
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Shared recap for end, at most 2000 characters; null omits it. Empty end text does not clear old notes; use session_notes_update."
        +}
      • addedInput schema / properties / save_state
        Added value: +{
        +  "default": true,
        +  "description": "True (default) requests saving state on end; false skips that snapshot. Must remain true for start/pause.",
        +  "type": "boolean"
        +}
    • Addedsession_notes_update
    • Changedtoken_add13 fields changed
      • addedInput schema / properties / character_id / description
        Added value: +"Existing sheet ID to link; empty string creates a token without a character link."
      • addedInput schema / properties / controlled_by
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "User ID allowed to control the token, subject to upstream checks; null omits explicit assignment."
        +}
      • addedInput schema / properties / height / description
        Added value: +"Vertical token size in map units, integer 1..10; defaults to 1."
      • changedInput schema / properties / height / type
        Previous value: -"number"New value: +"integer"
      • addedInput schema / properties / image_url / description
        Added value: +"Token artwork URL passed upstream; empty text is accepted as a placeholder by v1.4.0, with older behavior unverified."
      • addedInput schema / properties / layer / description
        Added value: +"Rendering layer: token (default) or spirit; upstream validates it and applies visibility rules."
      • addedInput schema / properties / map_id / description
        Added value: +"Destination map ID in this campaign; discover it and its dimensions with map_list."
      • addedInput schema / properties / name / description
        Added value: +"Display label for the new token; upstream requires nonempty text."
      • addedInput schema / properties / visible / description
        Added value: +"True requests a visible token; false requests a hidden token. Layer and role may further restrict visibility."
      • addedInput schema / properties / width / description
        Added value: +"Horizontal token size in map units, integer 1..10; defaults to 1."
      • changedInput schema / properties / width / type
        Previous value: -"number"New value: +"integer"
      • addedInput schema / properties / x / description
        Added value: +"Horizontal position in map units; upstream requires 0 <= x < map width."
      • addedInput schema / properties / y / description
        Added value: +"Vertical position in map units; upstream requires 0 <= y < map height."
    • Removedtoken_hp
    • Addedtoken_hp_update
    • Changedtoken_move4 fields changed
      • addedInput schema / properties / map_id / description
        Added value: +"Map ID containing the existing token, not necessarily the active map."
      • addedInput schema / properties / token_id / description
        Added value: +"Existing token ID on that map; this is not a character or creature ID."
      • addedInput schema / properties / x / description
        Added value: +"Absolute horizontal position in map units; upstream requires 0 <= x < map width."
      • addedInput schema / properties / y / description
        Added value: +"Absolute vertical position in map units; upstream requires 0 <= y < map height."
    • Changedtoken_place_creature4 fields changed
      • addedInput schema / properties / creature_id / description
        Added value: +"Library template ID from creature_search; the template must have a usable imageUrl, tokenImageUrl, or image."
      • addedInput schema / properties / map_id / description
        Added value: +"Destination map ID in this campaign; discover dimensions through map_list."
      • addedInput schema / properties / x / description
        Added value: +"Horizontal position in map units; upstream requires 0 <= x < map width."
      • addedInput schema / properties / y / description
        Added value: +"Vertical position in map units; upstream requires 0 <= y < map height."
  4. 1 tool updatev0.1.1
    • Changeddice_roll1 field changed
      • addedInput schema / properties / purpose
        Added value: +{
        +  "default": "",
        +  "type": "string"
        +}
  5. 20 tool updatesv0.1.0
    • First observedcampaign_status
    • First observedcharacter_create
    • First observedcharacter_get
    • First observedcharacter_list
    • First observedcharacter_update
    • First observedcharacter_validate
    • First observedchat_read
    • First observedchat_send
    • First observedcreature_search
    • First observeddice_roll
    • First observedevents_poll
    • First observedinitiative_manage
    • First observedinitiative_state
    • First observedmap_list
    • First observedmap_switch
    • First observedsession_manage
    • First observedtoken_add
    • First observedtoken_hp
    • First observedtoken_move
    • First observedtoken_place_creature

TDQS

A4.1/5.0

Scored across 41 tools

Disambiguation4/5

Tools target distinct resource+action pairs, and descriptions actively steer callers (e.g. token_add vs token_place_creature, token_hp_update vs character_update, document_list vs campaign_document_list). A few near-neighbors remain (map_list vs campaign_get's current-map, character_hitdice_spend vs character_update), but each is explicitly cross-referenced with 'use X for Y' guidance, so misselection risk is low.

Naming Consistency5/5

All 41 names follow a single snake_case resource_action pattern (map_list, token_move, character_get, saved_roll_create, session_notes_update, campaign_transfer_dm). Multi-word resources like token_hp_update and character_hitdice_spend still read predictably. No camelCase or verb-style mixing.

Tool Count2/5

41 tools is well beyond the 3-15 well-scoped range; even for a broad VTT domain this is heavy and increases selection cost. Many are individually justified (four saved_roll CRUD ops, full document share lifecycle), but the surface could contract via grouped operations (e.g. token modifications, session lifecycle) without losing capability.

Completeness3/5

Strong coverage overall: maps, characters, documents, sessions, initiative, chat, dice, saved rolls, and events all have read/write surfaces. However, notable gaps exist—no token read/list or general token update (only add, place, move, delete), no chat edit/delete, and no fog/annotation tools despite map fog defaults being referenced. These force agents to work around missing operations.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Connects Claude Desktop to Foundry VTT for AI-powered campaign management, enabling natural language interaction with game data including quest creation, character management, compendium searches, and dice rolling. Provides 20 MCP tools for seamless integration between Claude and your tabletop RPG sessions.
    79
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to act as RPG Game Masters by managing campaign state including characters, inventory, quests, and logs through MCP tools. Supports campaign mutations and provides both MCP and HTTP API access to RPG session data.
    2
    -
  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Integrates with FoundryVTT tabletop gaming sessions, allowing AI assistants to query game data, roll dice, generate content (NPCs, loot, encounters), manage combat, and provide tactical suggestions through natural language.
    3 npm
    -