@orinnadiak/mcp-rpg-tools
v0.1.0-beta.1
Published
MCP server exposing tabletop RPG rules lookup tools. Pathfinder 2e via Archives of Nethys.
Readme
mcp-rpg-tools
An MCP server that gives an AI assistant tabletop RPG rules lookup. It ships with Pathfinder 2e, backed by Archives of Nethys. The provider guide covers Pathfinder setup, available tools, Remaster handling, operational considerations, and content attribution.
Tools are generated from the selected game system's categories rather than a lowest common denominator.
Requirements
Node 22.19.0 or newer; supported Node lines are 22 (22.19.0+) and 24. Node 24 is recommended for new installations. Node 20 is no longer supported. Pathfinder 2e requires a network connection — see its operational notes.
Install and configure your MCP client
The selected public npm package is @orinnadiak/mcp-rpg-tools.
The current code is beta, not a production release. The following pinned
configurations target the planned first beta, 0.1.0-beta.1.
This beta is not published yet; the former 0.1.0 npm package was manually removed.
These examples are not yet verified against npm.
Consumers will not need to clone this repository or install a TypeScript compiler.
Linux
{
"mcpServers": {
"rpg-tools": {
"command": "npx",
"args": ["--yes", "@orinnadiak/[email protected]"]
}
}
}Windows
For clients that cannot launch npm's .cmd shim directly, use a command shell:
{
"mcpServers": {
"rpg-tools": {
"command": "cmd",
"args": ["/d", "/s", "/c", "npx --yes @orinnadiak/[email protected]"]
}
}
}Alternatively, after publication:
npm install --global @orinnadiak/[email protected]
mcp-rpg-toolsThe global npm executable directory must be on PATH. Windows clients unable to
launch mcp-rpg-tools.cmd directly likewise need cmd with
["/d", "/s", "/c", "mcp-rpg-tools"].
To upgrade, replace the explicit version and restart the MCP server. Global users
reinstall the desired exact version.
After beta publication, @orinnadiak/mcp-rpg-tools@beta opts into the moving beta
channel. Exact-version configurations above remain the primary examples.
Unqualified installs do not select beta; no stable latest release is available.
Release verification, ownership, and automation
The repository remains private; publishing makes the shipped JavaScript public.
Releases are automated via GitHub Actions when an annotated semantic-version tag
(e.g. v0.1.0-beta.1) is pushed to main. See the Release Runbook
for step-by-step guidance on version bumps, tagging, npm Trusted Publishing (OIDC),
dist-tags, recovery from partial completion, and private repository limitations.
CI covers the installed-tarball suite on Linux x64 and Windows with Node 22.19.0
(the exact supported minimum) and 24, using npm 11.16.0 on both runtimes. It checks direct Node
execution and npm's installed-bin resolution with a deterministic toy lookup outside
the checkout. The declared Node floor is >=22.19.0, matching MCP Inspector's
development-tool requirement.
You can check release packaging and generate metadata locally without publishing:
npm run release:check # dry-run: packs, writes metadata, runs test:package, queries npmThis dry run writes artifacts and checks npm publication status, but does not run
typechecking, linting, or unit/integration tests. Run npm run typecheck,
npm run lint, and npm test separately for full verification. Ancestry failures
and published checksum mismatches are warnings in dry-run mode, not failed gates.
Tag selection remains validated in dry-run mode: an explicit --tag takes
precedence, and GitHub tag runs use the actual tag. Branch/PR dry runs and local
runs without a tag use v plus the package version. A manual release workflow run
on a branch with dry_run=true can check packaging; real GitHub publishing
requires a tag ref or an explicit matching --tag.
Environment variables
| Variable | Default | Effect |
|---|---|---|
| GAME_SYSTEM | pf2e | Which system to load. pf2e or toy. An unrecognised value exits non-zero and lists the valid ones. |
For provider-specific settings, see the Pathfinder 2e guide.
Changing GAME_SYSTEM requires restarting the server. The tool list is fixed
at startup and the server tells clients so, rather than advertising updates it will
never send.
Tools
Two per category — search returns compact summaries, details returns one full entry. The selected system supplies its categories and tool-name prefix; see the Pathfinder 2e tool list for the default provider. Search never returns full rules text: the assistant fetches details only for entries it needs.
Search results may include nextCursor. Pass it as cursor on the same search
tool with identical query, filters, and limit to retrieve the next page:
{"query":"fire","limit":2}
{"query":"fire","limit":2,"cursor":"<nextCursor from the previous result>"}Omitted nextCursor means finished; a short or empty page alone does not. Search
defaults to 10 results (50 for blank-query small closed sets), with a maximum of
50. Details lookup still uses an entry's id, not its page cursor.
Cursors are opaque, reusable, and local to one running server. A traversal expires
after 15 minutes; bounded storage may evict it earlier, and restarting invalidates
all cursors. Invalid, expired, or mismatched cursors produce explicit errors:
restart without cursor. Pagination is not a point-in-time snapshot: edits
within the same index can change rankings between pages. MCP tools/list is unchanged.
Tool names are prefixed with the system even though only one ships today. Running a second system alongside this one would otherwise collide, and renaming tools later breaks every saved client config.
Operational notes
Content caches are in memory only, for the lifetime of the process. Restarting re-fetches everything. Content has no TTL, so a long-running process can serve stale cached content. Continuation handles have a separate expiry as described above.
Failures are explicit. A backend error surfaces as a tool error carrying the
upstream status code. "The service is rate limiting us", "the service is down", and
"that entry does not exist" are different answers and are reported differently.
An empty terminal page means no further matches, never something went wrong;
an empty page with nextCursor means traversal can continue past skipped records.
The Pathfinder provider's Archives of Nethys request policy is described in its provider guide.
Attribution and licensing
Project software is licensed under the MIT License, copyright 2026 mcp-rpg-tools contributors. This does not license retrieved rules text; see the Pathfinder content notices.
Development
Source builds remain a development alternative: clone the repository with access, use Node 22.19.0+ (Node 24 recommended) and the pinned npm 11.16.0, then run:
npm install --global [email protected]
npm ci
npm run buildPoint a development MCP client at node with the absolute path to
dist/index.js as its argument; use the same environment settings above.
npm run typecheck # src/ AND test/ -- see below
npm run lint # includes the import-zone and stdout rules
npm test # unit + integration, network mechanically disabled
npm run test:live # opt-in; hits the real API to detect upstream drift
npm run test:package # opt-in; packs, installs, and launches outside the checkout
npm run test:mutation # breaks each invariant, checks a test notices
npm run release:check # dry-run; packaging/metadata checks, writes artifacts and queries npmtypecheck runs two configs. The base one excludes test/, and vitest transpiles
without typechecking, so for a while nothing in the repo ever typechecked a test
file — which let a broken helper sit there unreported. tsconfig.test.json covers
both. Two traps are noted in that file: extends inherits exclude, which beats
include (the first version resolved zero files and reported success), and the
base rootDir: src rejects test files outright.
The startup tool-list size guard uses a narrowly typed view of the SDK's private request-handler map. SDK upgrades must preserve that boundary; the integration suite exercises rejection of an oversized tool list.
test:mutation is the one worth running before you trust a green suite. A
passing test proves nothing about whether it would fail. Every test this repo's
issue #1 was about passed while the thing it named was broken, and a full-suite
green was exactly the evidence that concealed it. The matrix breaks each invariant
in turn and reports anything no test noticed.
npm test runs with undici's net connect disabled, so any request that is not
explicitly stubbed throws. A test cannot pass because a live service happened to be
up.
Layout
src/provider/types.ts the backend-neutral contract — has zero imports, by rule
src/provider/pf2e/ Archives of Nethys implementation
src/provider/toy/ ~80-line in-memory provider
src/tools/ schema generation, registration, descriptions, results
src/http.ts the single outbound path: identity, throttle, timeout
src/cache.ts bounded LRU primitive
src/constants.ts every tunable number, defined onceThe toy provider is not a stub. With one real backend shipping, it is what proves
the shared contract stayed backend-neutral: if types.ts ever acquires an
Elasticsearch-shaped concept, the toy provider becomes impossible to write and the
build fails. It validates structure, not schema diversity — that needs a second
real backend.
Before calling a change done, run through docs/acceptance-scenarios.md. Automated tests prove the data layer is correct; they cannot tell you whether an assistant picks the right tool.
