foundry-vtt

Connect a Foundry VTT world to Claude, ChatGPT, Codex, Cursor, Gemini or any MCP client.

Community: Submitted by a user or imported; check the owner before granting accessOnlineNo sign-inGlobalFreeRead-only

What it can do

  • Actor Create: Create a new actor from scratch (custom NPCs, characters, creatures). type must be valid for the world's game system — dnd5e: character, npc, vehicle, group; pf2e: character, npc, hazard
  • Actor Create From Compendium: Import an actor (monster, NPC) from a compendium pack into the world. Pass either uuid — the "Compendium.<scope>.<pack>.Actor.<id>" value returned by dnd5e-compendium-fil
  • Actor Delete: Delete an actor from the world. This action cannot be undone!

What data it sees

Do you need an account

No: the server works without sign-in

Connect a Foundry VTT world to Claude, ChatGPT, Codex, Cursor, Gemini or any MCP client. 121 tools: actors and inventory, dice and combat, journals and roll tables, scenes and tokens, compendium search and import; D&D 5e and Pathfinder 2e aware. Sign in with Patreon (OAuth), no API key to paste; free to start, paid tiers unlock journals, scenes, tokens, combat and compendiums.

Setup: install the "Foundry API Bridge" module in Foundry VTT, get a key from the module settings, then add this server to your client and sign in. Code mode for Claude Code and Codex: https://foundry-mcp.com/code

Website: https://foundry-mcp.com Docs: https://github.com/alexivenkov/foundry-api-bridge-module Privacy: https://foundry-mcp.com/privacy

How to connect

How to connect foundry-vtt to Claude

The server address to paste into Claude settings:

https://foundry-vtt--ai-nitromoon.run.tools

  1. Open Claude (claude.ai or the desktop app).
  2. Go to Settings → Connectors.
  3. Click Add custom connector.
  4. Paste the server address copied below into Remote MCP server URL and click Add.
  5. In a chat, click + → Connectors and switch the new connector on.

Custom connectors are available on Free, Pro, Max, Team and Enterprise plans (Free is limited to one). On Team and Enterprise an organization Owner adds the connector first under Organization settings → Connectors.

Authorization

After you click Add, a sign-in window for the service opens. Sign in with your own account and approve access. Claude never sees your password.

How to connect foundry-vtt to ChatGPT

The server address to paste into ChatGPT settings:

https://foundry-vtt--ai-nitromoon.run.tools

  1. Open ChatGPT in a browser (chatgpt.com). A Plus, Pro, Business, Enterprise or Edu plan is required.
  2. Turn on developer mode once: Settings → Apps → Advanced settings → Developer mode.
  3. Open Settings → Connectors and click Create.
  4. Fill in the form: Name (anything), Description (one line about what the service does), MCP server URL (copy it below).
  5. Under Authentication choose OAuth if the service requires sign-in, otherwise None. Click Create.
  6. In a new chat open + → Apps/Connectors and enable the connector.

OpenAI has renamed this section before (Connectors → Apps/Plugins). If the label differs, search settings for "developer mode". On Business/Enterprise workspaces an admin must allow custom connectors first.

Authorization

On first use ChatGPT opens the service's sign-in window. Sign in and approve access.

How to connect foundry-vtt to Cursor

The server address to paste into Cursor settings:

https://foundry-vtt--ai-nitromoon.run.tools

Fastest: click Open in Cursor below and confirm the prompt.

Manually:

  1. In Cursor open Settings → Cursor Settings → MCP and click Add new global MCP server.
  2. Paste the JSON copied below into ~/.cursor/mcp.json (per project: .cursor/mcp.json in the repo root).
  3. Save the file. The server appears in the MCP list; authorize it there if asked.

Authorization

If the service needs sign-in, an authorize button appears next to the server in the MCP list.

Server tool list (60)

Raw names from tools/list. Only developers need these.

actor-createCreate a new actor from scratch (custom NPCs, characters, creatures). type must be valid for the world's game system — dnd5e: character, npc, vehicle, group; pf2e: character, npc, hazard, loot, familiar, party, vehicle, army. To import a monster from a compendium use actor-create-from-compendium. system is deep-merged over the system defaults.
actor-create-from-compendiumImport an actor (monster, NPC) from a compendium pack into the world. Pass either uuid — the "Compendium.<scope>.<pack>.Actor.<id>" value returned by dnd5e-compendium-filter-actors, pf2e-compendium-filter-actors and compendium-search — or packId + actorId from compendium-browse.
actor-deleteDelete an actor from the world. This action cannot be undone!
actor-getGet full actor details: HP, AC, abilities, skills, speed, proficiency, inventory with item IDs. Use actor-list or actor-filter FIRST to find actorId. Item IDs from here are needed for dnd5e-roll-attack, dnd5e-roll-damage, dnd5e-item-use. The statblock layout follows the dnd5e data model; in other systems sections such as skills or currency stay empty — use uuid-resolve with "Actor.<id>" for the raw document.
actor-listList actors in the world (name, type, ID), at most 200 rows. For anything beyond a plain listing — by name, CR, creature type, size, folder, HP, AC — use actor-filter, which also paginates. Actor IDs are needed for rolls, combat, items, and effects.
actor-filterSearch WORLD actors with D&D 5e structured filters (dnd5e worlds only). Returns paginated {id, name} entries; call actor-get for full stats. Filters combine with AND, values inside one array with OR. Use for "undead with CR 1-5", "PCs in the party", "dragons with AC 18+", "NPCs in folder Chapter 7". For every actor unfiltered use actor-list; compendiums are NOT searched (use dnd5e-compendium-filter-actors). CRITICAL DATA FORMATS - CR is a NUMBER from the exact set 0, 0.125, 0.25, 0.5, 1..30 ("1/4" -> 0.25; 0.7 is rejected). - Sizes are SHORT codes: tiny, sm, med, lg, huge, grg ("small" is rejected). - creatureType: the 14 lowercase SRD types only; subtypes ("demon") are rejected, use the base type ("fiend"). - Ranges are {min?, max?}, inclusive; min = max for an exact match. Actors lacking a filtered field are silently excluded (PCs have no CR, vehicles no abilities, root-level actors no folder). - Pagination: limit 1..200 (default 50), offset; the response has total and hasMore. EXAMPLES { "cr": { "min": 0.25, "max": 0.25 }, "type": ["npc"] } { "creatureType": ["undead"], "folder": { "name": "Chapter 3", "recursive": true } }
actor-updateUpdate an actor's name, image, folder, or system data (HP, XP, abilities...). system is DEEP-MERGED into the existing data: pass only the paths you change, e.g. {"attributes": {"hp": {"value": 25}}} sets current HP and leaves everything else intact; arrays are replaced whole. Common dnd5e paths: attributes.hp.value, details.xp.value.
chat-clearDelete ALL chat messages. This action is IRREVERSIBLE. Use ONLY when the user explicitly asks to clear the entire chat log.
chat-deleteDelete a specific chat message by ID. Use to remove erroneous messages or clean up chat. Use chat-list FIRST to find the message ID.
chat-exportExport the full chat log as text or JSON. Use for session summaries, recapping what happened, or saving chat history. Text format: "[Speaker] Content" per line. JSON format: array of message objects with id, timestamp, author, speaker, content, flavor, isRoll.
chat-listRead recent chat messages from Foundry VTT. Use to see what players are discussing, check roll results, or review combat narration. Returns plain text (HTML stripped). Use since param with a message ID to poll for new messages since last check. Filters: authorId, actorId, type (ic/ooc/emote/roll), search text. Messages are returned in chronological order (oldest first).
chat-sendSend a message to the Foundry VTT chat log. Use for narration, NPC dialogue, combat descriptions, and out-of-character communication with the player. Supports HTML formatting. Pass actorId to speak as an NPC (shows their portrait). Use flavor for context subtitles like "Narration", "The Tavern", "Combat". Players watching Foundry only see what is posted here. You can insert document links in content using @UUID[Actor.actorId]{Name}, @UUID[Item.itemId]{Sword}, @UUID[JournalEntry.journalId]{Quest} — Foundry renders them as clickable links.
chat-updateEdit content or flavor of an existing chat message. Use to fix typos in DM narration or update descriptions. Use chat-list FIRST to find the message ID. At least one of content or flavor must be provided.
combat-add-combatantAdd actor to combat. Use actor-list or actor-filter FIRST to find actorId. After adding all combatants, use combat-roll-all-initiative before combat-start.
combat-createCreate new combat encounter. First step in combat workflow. After creating: use combat-add-combatant to add actors, then combat-roll-all-initiative, then combat-start.
combat-deleteDelete combat encounter immediately without confirmation. Use when combat is over or cancelled.
combat-getGet combat state: combatants, round, turn, whose turn it is. Call FIRST to check if combat exists before other combat operations. Returns combatant IDs needed for combat-roll-initiative, combat-set-combatant-defeated, etc. combatId selects a specific encounter; omit it for the active combat.
combat-next-turnAdvance to next combatant's turn. Auto-advances round when all have acted. includeContext (default true) appends the tactical context: current combatant position, nearby enemies with distances and line of sight, ASCII map; set false on routine turns to save context.
combat-previous-turnGo back to previous combatant's turn. Use to undo an accidental combat-next-turn.
combat-remove-combatantRemove combatant from combat. Use combat-get to find combatantId (not same as actorId). Use when creature flees or is removed from encounter.
combat-roll-all-initiativeRoll initiative for all combatants at once. Call AFTER combat-add-combatant, BEFORE combat-start. Use npcsOnly=true to let players roll their own.
combat-roll-initiativeRoll initiative for specific combatants. Use combat-get to find combatantIds. For rolling all at once, use combat-roll-all-initiative instead.
combat-set-combatant-defeatedMark combatant as defeated (shows skull icon, skips their turn). Use when creature reaches 0 HP or is otherwise eliminated.
combat-set-initiativeManually set initiative value. Use for readied actions, special circumstances, or fixing rolls.
combat-set-turnJump directly to a specific combatant's turn in combat. Does NOT cycle through intermediate turns or increment the round. Use this instead of repeated combat-next-turn calls to avoid triggering round-based effects (Rage expiry, concentration checks, condition durations). Get combatant IDs from combat-get. includeContext (default true) appends the tactical context for the new current combatant.
combat-startBegin combat (round 1, turn 0). Call AFTER adding combatants and rolling initiative. Returns the combat state; includeContext (default true) appends the tactical context: current combatant position, nearby enemies with distances and line of sight, ASCII map.
combat-toggle-combatant-visibilitySet or toggle a combatant's visibility to players (hidden enemies, invisible creatures, surprise). Pass hidden to set the state explicitly; omit it to flip the current state.
compendium-browseBrowse the contents of a compendium pack. Lists documents (monsters, items, spells, etc.) in the compendium. Use compendium-list first to find the packId. Use types to select only given subtypes (e.g. ["spell"]), and ids to BATCH-fetch specific documents in one call — e.g. every item a class grants, taken from uuid-resolve output — instead of N compendium-document-get calls. types+ids combine with AND. On bridge module 8.11.0+ the selection happens inside Foundry; on older modules the full pack is fetched and the same selection is applied gateway-side. Paginate with limit (default 50, max 200) and offset. For structured stat filters (CR, level, rarity, traits, price...) prefer dnd5e-compendium-filter-* / pf2e-compendium-filter-* instead.
compendium-document-getGet a compendium document as a readable summary: actors come back as a statblock (HP, AC, abilities, attacks), other types as core fields plus system data. For the complete raw JSON use compendium-document-get-raw, or uuid-resolve when you already hold the document UUID (what the filter tools return). Use compendium-browse to find document IDs.
compendium-document-get-rawGet the complete raw JSON data of a compendium document including all system fields. Use this when you need the full statblock data for calculations or detailed information.
compendium-listList all available compendium packs. Compendiums contain pre-made content like monsters, items, spells, etc. Use this to discover what compendiums are available, then use compendium-browse to see their contents.
compendium-searchSearch for documents across ALL compendiums by name. Useful when you want to find a monster, item, or spell but don't know which compendium it's in. Name matching only — for structured filters (CR, level, rarity, traits, price...) use dnd5e-compendium-filter-* / pf2e-compendium-filter-*; for rules/lore TEXT inside journal packs use compendium-page-search (this tool does not see page content); when you already hold a UUID, use uuid-resolve.
compendium-page-searchFull-text search inside JournalEntry compendium packs — matches page NAMES and page CONTENT. This is the tool for rules/lore text questions: compendium-search only sees document names in pack indexes, so rule pages, spell lists, and class write-ups are invisible to it. Requires bridge module 8.11.0+. WHEN TO USE - "What does the grappled condition say?" → query: "grappled", pageTypes: ["rule"] - Find a class/subclass rules page, a spell list page, or any lore text - Locate which journal a phrase appears in WORKFLOW - Each match carries the PAGE uuid — pass it to uuid-resolve for the full page text. - matchedIn tells what matched; name matches win (content is not scanned then) and their snippet is always null. - Content matches include a ~200-char plain-text snippet around the first hit. SEMANTICS - Query is a case-insensitive substring. - Packs are scanned lazily in order until limit is reached; results are in scan order, unsorted. - Explicit unknown packIds error with "Pack not found: <id>"; non-journal packs with "Compendium pack is not an JournalEntry pack: <id>".
uuid-resolveResolve any ABSOLUTE Foundry UUID to its full document in one call: world documents ("Actor.<id>"), compendium documents ("Compendium.<scope>.<pack>.<DocType>.<id>"), and embedded/nested ones ("Actor.<id>.Item.<id>", journal pages). Returns core fields plus the complete raw document data. Requires bridge module 8.11.0+. UUIDs are NOT guessed — take them from the uuid fields of other tools: compendium-browse, compendium-page-search, the compendium filter tools, or reference fields inside a previously resolved document (e.g. a dnd5e class item's system.advancement[].configuration.items[].uuid). WHEN TO USE - Walk a reference graph one hop per call: class → granted features → their effects; spell-list page → individual spells. - Fetch the full text of a page found via compendium-page-search. - Inspect any document when a UUID is all you have. LIMITS - Relative UUIDs (starting with ".") are not supported. - Both a missing and a malformed UUID return "Document not found for UUID: <uuid>".
dnd5e-compendium-filter-actorsSearch COMPENDIUM packs for actors with D&D 5e structured filters (dnd5e worlds only). Compendium counterpart of actor-filter, which searches world actors; for a plain name lookup use compendium-search. CRITICAL DATA FORMATS - CR is a NUMBER from the exact set 0, 0.125, 0.25, 0.5, 1..30 ("1/4" -> 0.25; 0.3 is rejected). - Sizes are SHORT codes: tiny, sm, med, lg, huge, grg. creatureType: the 14 lowercase SRD types, no subtypes ("demon" -> "fiend"). - level applies only to type "character" (NPCs have CR). World-only filters (folder, hasPlayerOwner, currentHp) do not exist here. SEMANTICS: filters combine with AND, values inside one array with OR. Ranges are {min?, max?}, inclusive (min = max for exact). Documents lacking a filtered field are silently excluded. limit 1..200 (default 50), offset; the response has total and hasMore. Results are {name, uuid} entries: follow up with uuid-resolve, or compendium-browse with ids to batch-load. Requires bridge module 8.11.0+. EXAMPLES { "type": ["npc"], "cr": { "min": 0.25, "max": 0.25 } } { "packIds": ["dnd5e.monsters"], "creatureType": ["dragon"], "size": ["huge", "grg"] }
dnd5e-compendium-filter-itemsSearch COMPENDIUM packs for items with D&D 5e structured filters (dnd5e worlds only): gear, spells, feats, class features and other Item documents. Compendium counterpart of world-item-filter. CRITICAL DATA FORMATS - rarity is camelCase: veryRare (not "very rare"). spellSchool is the full word (evocation, not "evo"). - spellLevel 0..9 (0 = cantrip) only affects type "spell"; other types are silently excluded by it. - price in GP (denominations normalized), weight in lb, decimals allowed. SEMANTICS: filters combine with AND, values inside one array with OR. Ranges are {min?, max?}, inclusive (min = max for exact). Documents lacking a filtered field are silently excluded. limit 1..200 (default 50), offset; the response has total and hasMore. Results are {name, uuid} entries: follow up with uuid-resolve, or compendium-browse with ids to batch-load. Requires bridge module 8.11.0+. EXAMPLES { "type": ["spell"], "spellLevel": { "min": 0, "max": 0 }, "spellSchool": ["evocation", "illusion"] } { "requiresAttunement": true, "price": { "max": 5000 }, "rarity": ["rare", "veryRare"] }
pf2e-compendium-filter-actorsSearch COMPENDIUM packs for actors with Pathfinder 2e structured filters (pf2e worlds only): bestiary browsing by level, traits, rarity, size, HP, AC. CRITICAL DATA FORMATS - level is an INTEGER range; negative bounds are valid ({ "min": -1 }). - traits are ALL-OF (every listed trait must be present), an open set of lowercase slugs ("undead", "kobold"). - rarity: common, uncommon, rare, unique (PF2e ladder). Sizes: tiny, sm, med, lg, huge, grg. SEMANTICS: filters combine with AND, values inside one array with OR. Ranges are {min?, max?}, inclusive (min = max for exact). Documents lacking a filtered field are silently excluded. limit 1..200 (default 50), offset; the response has total and hasMore. Results are {name, uuid} entries: follow up with uuid-resolve, or compendium-browse with ids to batch-load. Requires bridge module 8.11.0+. Results carry level (null when absent), sorted by level then name. EXAMPLES { "type": ["npc"], "traits": ["kobold"], "level": { "min": -1, "max": 1 } } { "rarity": ["unique"], "level": { "min": 15 } }
pf2e-compendium-filter-itemsSearch COMPENDIUM packs for items with Pathfinder 2e structured filters (pf2e worlds only): equipment, spells, feats, ancestries, classes and 20 more Item types. CRITICAL DATA FORMATS - For spells, level is the spell RANK. - traits are ALL-OF (every trait present); traditions are ANY-OF (arcane, divine, occult, primal). Do not confuse the two. - category is the feat category (class, skill, general, ancestry, ...). rarity: common, uncommon, rare, unique. - priceGold is gp with decimals (5 sp -> 0.5), per batch for batched goods like arrows. SEMANTICS: filters combine with AND, values inside one array with OR. Ranges are {min?, max?}, inclusive (min = max for exact). Documents lacking a filtered field are silently excluded. limit 1..200 (default 50), offset; the response has total and hasMore. Results are {name, uuid} entries: follow up with uuid-resolve, or compendium-browse with ids to batch-load. Requires bridge module 8.11.0+. Results carry level (null when absent), sorted by level then name. EXAMPLES { "type": ["spell"], "level": { "min": 3, "max": 3 }, "traditions": ["arcane"] } { "type": ["consumable"], "priceGold": { "max": 5 } }
effect-createAdd a custom active effect to an actor (buff, debuff, custom condition). Each change targets a data path with a mode; values are strings. EXAMPLE changes: [{"key": "system.attributes.ac.bonus", "value": "2", "mode": 2}] adds +2 AC. Paths are dnd5e; other systems differ.
effect-deleteRemove an active effect from an actor. Use effect-list first to find effect IDs.
effect-listGet all active effects on an actor, including conditions, buffs, debuffs, and custom effects. Effects modify actor stats, grant abilities, or apply conditions.
effect-toggle-statusToggle a D&D 5e condition/status on an actor (dnd5e worlds only; in PF2e worlds use pf2e-set-condition / pf2e-remove-condition). Adds or removes conditions like blinded, poisoned, prone. Core D&D 5e status IDs: blinded, charmed, deafened, exhaustion, frightened, grappled, incapacitated, invisible, paralyzed, petrified, poisoned, prone, restrained, stunned, unconscious.
effect-updateUpdate an existing active effect on an actor. Can modify name, icon, disabled state, or changes.
handout-template-getGet the full HTML of a handout template. Use this as a STYLE REFERENCE — do not copy it verbatim. Generate a unique variation with the required content, using inline style="" attributes (Foundry VTT strips <style> tags). Save the result via journal-page-create with type "text".
handout-template-listList available handout templates (wanted posters, letters, scrolls, etc.). Returns template IDs and descriptions. Use handout-template-get to read the full HTML. Then generate a unique variation with your own content and save via journal-page-create.
dnd5e-item-activateActivate an item with full Foundry automation — triggers Midi-QOL and other automation module hooks. Use for combat actions: melee/ranged attacks, spell casting, abilities. Pass targetTokenIds for attacks — Midi-QOL will auto-roll attack, check AC, roll damage, apply HP loss. For AoE spells pass templatePosition. Circle AoE (Fireball): x,y = center of effect (avg target positions). Cone/Line AoE (Cone of Cold, Lightning Bolt): x,y = caster token position, direction = angle toward targets (direction = atan2(targetY - casterY, targetX - casterX) * 180 / PI, add 360 if negative). Pixel coords: pixel = gridCoord * gridSize + gridSize / 2. Unlike dnd5e-item-use, this does NOT suppress hooks or dialogs, so automation modules work fully. Use scene-get to find target token IDs and grid info, item-list to find item IDs. Prefer this over dnd5e-item-use when targets, templates or automation matter.
item-createCreate a new item directly in an actor's inventory (dnd5e data model). Use for custom items, loot, or simple gear; for official SRD content use item-create-from-compendium. For an item that lives in the world Items Directory rather than on an actor use world-item-create.
item-create-from-compendiumAdd an item (weapon, spell, feat, gear) from a compendium pack to an actor's inventory with its full data. Pass either uuid — the "Compendium.<scope>.<pack>.Item.<id>" value returned by dnd5e-compendium-filter-items, pf2e-compendium-filter-items and compendium-search — or packId + itemId from compendium-browse.
item-deleteRemove an item from actor's inventory permanently. Use item-list FIRST to find itemId. Cannot be undone! An item that is already gone counts as deleted (success), so retries are safe.
item-listList an ACTOR's inventory (embedded items: weapons, gear, spells, feats, class features) with descriptions, damage, and range. Not the world Items Directory — use world-item-filter for that. Filter by type, equipped status, or hasActivities (usable abilities). Item IDs from here feed dnd5e-item-use, dnd5e-item-activate, dnd5e-roll-attack.
item-updateUpdate an item in actor's inventory. Use item-list FIRST to find itemId. system is DEEP-MERGED into the existing data: pass only the fields you change, e.g. {"quantity": 3} or {"uses": {"value": 0}}; arrays are replaced whole.
dnd5e-item-useUse an item from an actor's inventory via item.use() with dialogs suppressed: consumables (potions, scrolls), spells, weapons, features. Returns the raw use result as JSON. CHOOSING: this tool for quick, dialog-free usage without targets; dnd5e-item-activate when targets, AoE templates, or automation modules (Midi-QOL) matter.
journal-createCreate a new journal entry, optionally with a first page. content is HTML (see journal-page-create for the HTML rules). folder takes a folder ID; a unique folder NAME is resolved to its ID.
journal-deleteDelete a journal entry and all its pages. This action cannot be undone!
journal-folder-listList journal folders by name with entry and page counts — a quick overview of journal organization. Then use journal-list with a folder name, or omit folder to list all journals. Folder IDs (for journal-create / journal-update / folder-get) come from folder-list with type "JournalEntry".
journal-getGet a journal entry by ID with all its pages as plain text (default) or as raw JSON with HTML and page metadata (formatAsText=false). Use journal-list or journal-search to find journal IDs; for one page of a long journal use journal-page-get.
journal-listList journal entries with IDs, grouped by folder. Omit folder to list ALL journals. Returns IDs needed for journal-get. Use journal-search if you know the name.
journal-page-createAdd a page to an existing journal entry. Text pages take HTML content: style with inline style="" attributes (Foundry strips <style> and <script>), link documents with @UUID[Actor.<id>]{Label}. handout-template-list offers ready-made layouts.
journal-page-deleteDelete a specific page from a journal. This action cannot be undone!
journal-page-getGet a specific page from a journal. Useful when you only need one page from a multi-page journal. Returns plain text content by default.