Build on Storywright with MCP
We don’t publish a REST API for third parties — our REST surface is internal and unversioned, and freezing it as a public contract isn’t something we can honestly promise yet. What we do ship, and what this page documents, is a real, public Model Context Protocol server: 66 tools over a signed-in user’s own campaign data, authenticated with OAuth 2.1.
The server
One remote MCP server, reachable over Streamable HTTP:
https://mcp.storywright.io/mcp
Point any MCP-capable client at that URL — Claude, ChatGPT, or anything else speaking the protocol — and it discovers everything else on this page automatically: the OAuth configuration, Dynamic Client Registration, and the tool/resource/prompt catalog. No API key to request, no manual credential setup.
What the tools let you do
The server exposes a signed-in user’s own worlds, sessions, player journals, quests, lore (“Drafting Table”), characters, and the Campaign Weave graph — read and write, scoped to whatever that user could already do in the app. It is a thin adapter over the same internal REST API the product itself uses; permissions are always enforced by the Storywright backend, never by this process.
| Surface | Count | What it covers |
|---|---|---|
| Read tools | 32 | Worlds, sessions, characters, journals, quests, lore, the Weave graph, campaign overviews, and GM-only Discord recap delivery status. |
| Write tools | 28 | Journal entries, quests, objectives, lore, annotations, sessions, AI session recaps and briefings, and deliberate GM-only Discord recap retry. |
| Delete tools | 6 | Permanent removal — quests, objectives, lore items, threads, characters, journal entries. There is deliberately no session-delete tool. |
| Total tools | 66 | Read + write + delete. |
| Resources | 5 | Attachable reading material rendered as prose, not JSON — so a user can hand a client their campaign to read. |
| Prompts | 6 | Ready-made slash commands: starting a new campaign, session prep, recap, loose threads, catching a player up, importing a module. |
Discord delivery tools are available when recovery is enabled for the world. A retry uses the same delivery rules as the app and may require the GM to acknowledge that Discord could already have a copy.
This page documents the MCP tool surface only — it does not enumerate individual REST endpoints. That is a deliberate boundary, not an omission: the internal REST API is unversioned, and we are not ready to freeze it as a public contract. The MCP surface above is what we’re actually offering third parties today.
Every tool, before you connect
The counts above are a summary. The full list — every tool, prompt, and resource with its description and argument schema — is published as JSON at https://mcp.storywright.io/tools.json.
No authentication required. Reading what the server can do should not itself need a token — you can’t evaluate a surface you have to sign in to see. It is generated from the running server on each request, not maintained by hand, so it is always the build that answers it: add a tool and it appears there in the same deploy. It also carries this server’s live rate limit and the OAuth documents a client needs.
Authentication
Every client authenticates as a real Storywright user, with that user’s explicit consent — there are no API keys. The server runs as an OAuth 2.1 Resource Server: PKCE (S256) is required on the authorization code grant, and a client can self-register with Dynamic Client Registration (RFC 7591) instead of asking us for credentials by hand.
| Property | Value |
|---|---|
| Grant type | Authorization Code + PKCE (S256 required); refresh_token for staying connected. |
| Client registration | Open Dynamic Client Registration (RFC 7591) at POST https://storywright.io/api/oauth/register/ — public clients only (token_endpoint_auth_method: none), rate-limited. |
| Consent | A human consent screen on Storywright; the user grants only the scopes they choose. |
| Tokens | Short-lived bearer access tokens, sent as Authorization: Bearer <token>. |
Scopes
| Scope | Grants |
|---|---|
campaigns:read | Read the user's worlds, sessions, journals, quests, and lore. |
campaigns:write | Create and update journals, quests, lore, and recaps. |
Discovery documents
All public, CORS-open JSON — a spec-compliant client walks these automatically:
- Authorization server metadata (RFC 8414) —
https://storywright.io/.well-known/oauth-authorization-server - Protected resource metadata (RFC 9728) —
https://storywright.io/.well-known/oauth-protected-resource - API catalog (RFC 9727) —
https://storywright.io/.well-known/api-catalog - MCP server card —
https://storywright.io/.well-known/mcp.json
Use Storywright in Claude
A GM’s connection can do nearly everything that GM can already do in Storywright — read every session, quest, and Drafting Table entry, and write journal entries, quests, objectives, and lore. Still deliberately excluded, even for a GM: world deletion, ownership transfer, member removal, billing, account deletion, webhook config, and invite regeneration. A player’s connection is scoped the same way the app already scopes a player: published and public content, plus that player’s own private content — their own journal entries, their own character’s notes. GM notes, another player’s private content, and unrevealed entries stay hidden, and a GM-only action — publishing a session briefing, touching GM notes — is refused for a player’s assistant exactly as it would be in the app itself. Connecting an assistant never widens anyone’s view of a world.
Free plan: 1 world, unlimited sessions, 4 players, 75 world items, 10 AI actions a month — the same caps you’d hit in the app itself, whether you connect an assistant or not. See Pricing for GM Pro.
Add it in Claude
In Claude: Settings → Connectors → Add custom connector, then paste the server address from “The server” above (https://mcp.storywright.io/mcp). Claude sends you to Storywright’s own sign-in, then a consent screen that lists exactly what you’re granting. Approve once and the connection is live. For the full three-step walkthrough, including ChatGPT and other clients, see Connect an assistant.
Three things to try
The connector ships ready-made prompts that appear as slash commands in Claude’s prompt menu. Three, worked end to end:
- /prep-my-next-session
- Ask: “/prep-my-next-session” (a GM, before the table sits down). Reads: the world’s continuity checks, unresolved objectives, the latest session, player goals, and the entities named in it — nothing is written. The GM sees: a scannable prep packet — where the story left off, open threads ranked by urgency, who is likely to appear, and three prep questions to decide before play.
- /catch-me-up
- Ask: “/catch-me-up” (a player who missed a session or two). Reads: only published briefings, recaps, and journals — the same content that player already sees in the app. Nothing in the campaign changes, though reading a published briefing records a read receipt the GM can see. The player sees: what they missed in order, their own character’s situation grounded in their journal, the party’s current aim, and one question their character owes the table next session.
- /start-new-campaign
- Ask: “/start-new-campaign” (a GM with no world yet and nothing prepared). Reads: the four available genre templates and offers a choice. Writes: a new world seeded from the chosen template — a handful of entities, plus a quest linked to them and an opening beat for the three genre templates (Blank + Tips seeds one example entity only, and no quest). No session is ever auto-created; whatever the GM plays is genuinely their own. The GM sees: the new campaign and its genre, the seeded entities (including any NPCs), and the opening quest if the template seeded one.
What Claude can do without asking
The read/write/delete split above is the approval model: a read tool never changes campaign content, though reading a published session briefing does record a read receipt the GM can see — the same as opening it in the app. A write tool creates or updates a record under your name, and a delete tool removes one permanently. Every tool also carries machine-readable annotations (readOnlyHint, destructiveHint, idempotentHint) that a host like Claude reads to decide whether to ask before running it — the exact, current annotation for any one tool is in the tool manifest, not restated here, because a per-tool promise written into this page is a claim about a build and the manifest is the value actually in force.
Revoking access
Changing (or setting) your Storywright account password immediately revokes every connected assistant’s access — every access token, refresh token, and grant, for every connected client at once, not one connection at a time. That’s the fastest way to cut a connection off from your side. Short of that, an access token expires on its own within about an hour, and an idle connection’s refresh token lapses on its own after thirty days of inactivity. Removing the connector inside Claude’s own settings stops that assistant from using it, but isn’t guaranteed to notify Storywright — some assistants revoke the token when you remove them, others don’t, so the token can stay valid on our side until it expires on its own. If you want a connection cut off immediately and would rather not change your password, write to [email protected] and we’ll revoke it from our side. Or manage every connected assistant directly from Connected apps in your account settings. See Trust for more on what a connected assistant can and cannot do.
If something’s not working
- Stuck in a sign-in loop, or the connector shows connected but can’t answer anything about your worlds. The connector was added but never finished authorizing. Remove it in Claude and add it again — that reconnect is the fix for most stuck states, including a client that connected before a new prompt or scope existed and needs to reconnect to see it.
- A write tool call is refused with an explicit error naming the missing scope. Never a silent no-op — if you’re on a read-only connection and want write access, remove the connector in Claude and add it again.
- Requests start failing with a rate-limit error. Storywright’s MCP server returns a
429with aRetry-Afterheader when a client is over its window — Claude should back off and retry on its own; the number in force is published in the manifest, not here. - Anything else: write to [email protected] and describe what you asked for and what happened instead.
What we don’t promise yet
This surface is offered as-is, with no versioning guarantee yet — a tool’s name, arguments, or behavior can change, and we make no uptime commitment. Expect the tool list to grow. If a tool’s behavior needs to change in a breaking way, we’ll say so in mcp/README.md and on this page, not silently — and the tool manifest is generated from the running server, so it always describes what is actually deployed.
Rate limits. Requests to /mcp are limited per client over a fixed window; over the limit you get a 429 with a Retry-After header and a JSON body with error_kind: rate_limited andretry_after seconds. Honour the header rather than retrying immediately. The numbers in force are published in the manifest’s rateLimit block — read there rather than here, because a limit written into a page is a claim about a build, and that one is the value the limiter is actually counting with.
Bring your own assistant.
Free to start, free for your players, forever. Connect an assistant once you have a world to point it at.