FoundryBLOCK
A Model Context Protocol (MCP) server that integrates with FoundryVTT, allowing AI assistants to interact with your tabletop gaming sessions. Query actors, roll dice, generate content, and manage your game world through natural language.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
[](https://www.npmjs.com/package/foundryvtt-mcp) [](LICENSE)
A Model Context Protocol (MCP) server that integrates with FoundryVTT, allowing AI assistants to interact with your tabletop gaming sessions through natural language.
Features
- Dice Rolling — standard RPG notation with any formula
- Data Querying — search and inspect actors, items, scenes, journals
- Game State — combat tracking, chat messages, user presence
- Content Generation — NPCs, loot tables, rule lookups
- World Search — full-text search across all game entities
- Live Connection — Socket.IO loads complete world state on connect
- MCP Resources —
foundry://URIs for direct data access - Diagnostics — optional server health monitoring (requires REST API module)
Quick Start
Prerequisites
- Node.js 18+ (or Bun)
- FoundryVTT server running with an active world
- MCP-compatible AI client (Claude Desktop, Claude Code, VS Code, etc.)
Recommended: Create a Dedicated API User
It is recommended to create a separate FoundryVTT user account for the MCP server rather than using your own GM or player account. This provides better security and auditability.
In FoundryVTT:
- Go to Configuration → User Management
- Click Create User
- Set a username (e.g.,
mcp-api) and a strong password - Assign the Assistant GM role (needed to read world data and roll dice)
- Use this account's credentials in your MCP configuration
Benefits:
- Chat messages and actions from the MCP server are clearly attributed to a separate user
- You can revoke access by disabling the API user without affecting your own account
- Limits blast radius if credentials are ever exposed
Installation
Run directly without installing — no clone needed:
f1026e365041OBSERVED · 2026-10-08Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add foundryvtt-mcp --env FOUNDRY_API_KEY=${FOUNDRY_API_KEY} --env FOUNDRY_PASSWORD=${FOUNDRY_PASSWORD} -- npx -y [email protected]{
"mcpServers": {
"foundryvtt-mcp": {
"command": "npx",
"args": [
"-y",
"[email protected]"
],
"env": {
"FOUNDRY_API_KEY": "${FOUNDRY_API_KEY}",
"FOUNDRY_PASSWORD": "${FOUNDRY_PASSWORD}"
}
}
}
}Exposed tools (25)
19 read · 4 write · 2 destructive. Blast radius: 2 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.
| Tool | Risk | Description |
|---|---|---|
Users | read | List of users and their online status |
apply_status_effect | destructive | Apply or remove a status condition (e.g. |
delete_actor_item | destructive | Permanently remove an item owned by an actor. Use when: the user explicitly asks to delete or discard a specific owned item, and has given you the itemId - no tool in this server lists owned-item ids, so never guess one. Do not use when: only the item |
diagnose_errors | read | Stub: returns a fixed |
end_combat | read | End the active combat encounter by deleting its Combat document, discarding the initiative order and round count. Use when: the fight is over and the user asks to end the encounter. |
generate_npc | read | Generate a random NPC (name, race, class, HP, ability scores, background) as text. Use when: the user needs a throwaway NPC on the spot. Do not use when: the NPC must exist in FoundryVTT - this creates no documents, and the result still has to be entered into the world by hand. |
get_actor_details | read | Get details for one actor by id: type, level, current/max HP, AC and ability scores; no biography or description text is returned (the description line always reads |
get_chat_messages | read | Get the most recent chat messages from the game log. Use when: you need recent in-game context - what players said, or roll results that already happened. |
get_combat_state | write | Get the active combat encounter: initiative order with each combatant |
get_health_status | read | Get a combined health report: MCP-to-FoundryVTT connection state, world title/system/core version, and the server |
get_journal | read | Get one journal entry by id with the text of its pages. Page bodies are HTML-stripped and each is truncated to its first 500 characters, marked with a trailing |
get_recent_logs | read | Get recent FoundryVTT server log entries, optionally filtered by level or since a timestamp. Use when: investigating an error or recent server behaviour. Do not use when: you have a specific term to look for - use search_logs. Requires the REST API module (FOUNDRY_API_KEY); fails without it. |
get_scene_info | read | Get details of the active scene, or of a specific scene by id: name, scene id, active/navigation flags, pixel dimensions, padding and lighting (global light, darkness); no description text is returned unless a module has set a description flag on the scene (the description line otherwise reads |
get_system_health | read | Get the FoundryVTT server |
get_users | read | List the world |
get_world_summary | read | Get world metadata (title, game system, core version) and per-collection document counts. Use when: orienting yourself in an unfamiliar world, or confirming the game system before system-specific edits. |
lookup_rule | read | Stub: builds a templated placeholder from the query and consults no rules source, so the text it returns carries no rules content. No tool in this server looks rules up. |
next_turn | read | Advance the active combat to the next turn, wrapping to the next round after the last combatant. When skipDefeated is true, defeated combatants are skipped. Use when: the current combatant has finished their turn. Do not use when: only reporting the turn order - use get_combat_state. |
search_actors | read | Search actors (player characters, NPCs) by name, optionally filtered by type. Returns a summary line per match: name, type, level and current/max HP. Use when: checking whether an actor exists, or getting a quick roster with HP. Do not use when: you already have the actorId and want that actor |
search_items | read | Search item documents in the world by name, optionally filtered by type. Returns name, type and rarity per match (rarity shows |
search_journals | read | Search journal entries by name and page content. Use when: looking for notes, lore, or handouts by keyword. Do not use when: you already have the journalId - use get_journal. |
search_logs | read | Search the FoundryVTT server logs for a query string and list the matching entries. Use when: hunting a specific error message, stack trace, or module name. Do not use when: you just want the latest entries - use get_recent_logs. The reported match count is the server\ |
set_initiative | write | Set a combatant |
update_actor_attributes | write | Update fields on an actor\ |
update_actor_item | write | Apply a JSON merge patch to an item |
Trust audit
BLOCKgrade D · trust 63/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | WARN |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (1 observation(s))
- Network
- declared (9 observation(s))
- Shell
- declared (3 observation(s))
- Dependencies
- not all pinned
- Secrets in source
- none-found
Findings (25)
if check 'eval($$$)'; then ((issues+=1)); else echo "None found"; fi
console.log(` API Key: ${API_KEY ? '✅ Configured' : '❌ Not set'}\n`);console.log(` Transport: ${config.foundry.apiKey ? '🌐 REST API' : '🔌 Socket.IO'}`);console.log(` API Key: ${config.foundry.apiKey ? '✅ Configured' : '❌ Not set'}`);console.log(` - Data access: ${config.foundry.apiKey ? '🌐 REST (coverage depends on the target module; Socket.IO is the full-data path)' : '✅ Full worldData'}`);console.log(` - Connection: ${config.foundry.apiKey ? '🌐 REST API' : '🔌 Socket.IO'}`);# FOUNDRY_URL=http://192.168.1.100:30000
'http://127.0.0.1:30000',
console.log(' • http://192.168.1.100:30000 (local network IP)\n');console.log(' • http://192.168.1.100:30000 (network IP)');console.log('🧙♂️ FoundryVTT MCP Setup Wizard\n');apply_status_effect, delete_actor_item
.env.integration.example
.gitleaks.toml
.project-standards.yaml
.release-please-manifest.json
.nojekyll
import type { FoundryClient } from '../../foundry/client.js';vi.mock('../../foundry/client.js');vi.mock('../../utils/logger.js', () => ({vi.mock('../../utils/logger.js', () => ({const { logger } = await import('../../utils/logger.js');FOUNDRY_URL=http://192.168.1.100:30000
@modelcontextprotocol/sdk, ajv, axios, dotenv, socket.io-client, zod, @biomejs/biome, @playwright/test
* **auth:** send the Foundry session as a Cookie header, and load .env before config ([#210](https://github.com/laurigates/foundryvtt-mcp/issues/210)) ([b3fd356](https://github.com/laurigates/foundryv
Gates applied: no_behavioural_pass.
f1026e365041full audit observations/trust-audit/mcp-server/laurigates__foundry-2.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-08 | f1026e365041 | BLOCK | D | 63 | first audit |
Questions
What is the Foundry MCP server?
A Model Context Protocol (MCP) server that integrates with FoundryVTT, allowing AI assistants to interact with your tabletop gaming sessions. Query actors, roll dice, generate content, and manage your game world through natural language.
What tools does Foundry expose?
25 in total: 19 read-only, 4 that write, and 2 that can delete or overwrite (apply_status_effect, delete_actor_item). Every one is listed on this page with its risk.
Is Foundry safe to connect to an agent?
No — not without reading the findings first. The audit graded it D (63/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 2 of its tools can destroy data, so scope the token you give it to what you actually need.
What credentials does Foundry need?
It reads FOUNDRY_API_KEY and FOUNDRY_PASSWORD from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does Foundry run?
It speaks stdio, so it runs as a local process your client starts. It is published on npm as foundryvtt-mcp at 1.5.3.
How current is this page?
The grade is for one exact copy of the source (f1026e365041), read on 2026-10-08. The repository is watched and re-audited when it changes.