DFHack을 통해 실행 중인 Dwarf Fortress 게임에 AI 클라이언트가 실시간으로 접속하여 요새 상태, 비축물자, 위협 요소 및 유닛 상세 정보를 관찰할 수 있도록 지원합니다.
다른 이름 alexanderolvera/dfhack-mcp, dfhack-mcp
- 스타
- 2
- Tools
- —
- 다운로드, 30일
- —
- 최신 버전
- 1.4.1
- 마지막 커밋
- 2026년 11월 11일
- 라이선스
- ISC
Dwarf Fortress (DFHack) MCP란?
Dwarf Fortress (DFHack)은(는) MCP server입니다. DFHack을 통해 실행 중인 Dwarf Fortress 게임에 AI 클라이언트가 실시간으로 접속하여 요새 상태, 비축물자, 위협 요소 및 유닛 상세 정보를 관찰할 수 있도록 지원합니다.
프로젝트 README에서 생성된 요약
Dwarf Fortress (DFHack) MCP server 정보
이 MCP server는 AI 클라이언트가 Dwarf Fortress 정착지의 상태와 보안을 모니터링할 수 있게 해줍니다. DFHack을 통해 실행 중인 게임에 연결함으로써, AI agent는 인구 행복도, 비축물자 수준, 군사 준비 태세, 활성 위협 등 실시간 데이터를 관찰할 수 있습니다. 이 서버는 사실 기반의 액세스 레이어 역할을 하며, 클라이언트가 자체적인 추론과 전략 수립을 수행할 수 있도록 구조화된 JSON 데이터를 제공합니다.
사용자는 npx를 통해 패키지를 실행하여 Claude Desktop과 같은 표준 stdio 클라이언트로 연결할 수 있습니다. 설정을 위해서는 DFHack과 localhost:5000에서 DFHack Remote RPC가 활성화된 Dwarf Fortress 인스턴스가 실행 중이어야 합니다. 서버는 기본적으로 39개의 센서 및 참조 도구를 갖춘 읽기 전용 상태이지만, 사용자가 명시적으로 액추에이터를 선택하면 AI가 대기열 관리, 노동 할당, 레버 조작 등의 작업을 수행할 수 있습니다. 이러한 구분 덕분에 사용자가 게임 상태 변경 권한을 부여하지 않는 한 AI는 관찰자 역할에 머무릅니다.
활용 사례
- 1요새 안정성 평가AI에게 정착지의 현재 상태를 평가하여 긴급한 문제를 식별하도록 요청합니다.
- 2자원 수준 모니터링agent가 인구를 유지하기 위한 충분한 식량이나 재료가 있는지 확인하게 합니다.
- 3개별 드워프 요구 사항 추적agent를 사용하여 특정 드워프를 찾고 그들의 사회적 관계나 건강 상태를 확인합니다.
프로젝트의 README를 바탕으로 작성되었습니다. 모든 활용 사례는 해당 내용의 인용문과 대조하여 확인합니다.
Dwarf Fortress (DFHack) MCP 설치 방법
형식 확인: 2026년 11월 10일Cursor에 추가Goose에 추가Claude Code에 Dwarf Fortress (DFHack) MCP 설치
$ claude mcp add dfhack-mcp -- npx -y dfhack-mcpCursor에 Dwarf Fortress (DFHack) MCP 설치
~/.cursor/mcp.json
{
"mcpServers": {
"dfhack-mcp": {
"command": "npx",
"args": [
"-y",
"dfhack-mcp"
]
}
}
}VS Code에 Dwarf Fortress (DFHack) MCP 설치
.vscode/mcp.json
{
"servers": {
"dfhack-mcp": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"dfhack-mcp"
]
}
}
}VS Code CLI에 Dwarf Fortress (DFHack) MCP 설치
$ code --add-mcp '{"name":"dfhack-mcp","type":"stdio","command":"npx","args":["-y","dfhack-mcp"]}'Claude Desktop에 Dwarf Fortress (DFHack) MCP 설치
claude_desktop_config.json
{
"mcpServers": {
"dfhack-mcp": {
"command": "npx",
"args": [
"-y",
"dfhack-mcp"
]
}
}
}Codex에 Dwarf Fortress (DFHack) MCP 설치
$ codex mcp add dfhack-mcp -- npx -y dfhack-mcpCodex config.toml에 Dwarf Fortress (DFHack) MCP 설치
~/.codex/config.toml
[mcp_servers.dfhack-mcp] command = "npx" args = ["-y", "dfhack-mcp"]
Gemini CLI에 Dwarf Fortress (DFHack) MCP 설치
$ gemini mcp add -s user dfhack-mcp npx -- -y dfhack-mcpGemini settings.json에 Dwarf Fortress (DFHack) MCP 설치
~/.gemini/settings.json
{
"mcpServers": {
"dfhack-mcp": {
"command": "npx",
"args": [
"-y",
"dfhack-mcp"
]
}
}
}구성
DFHACK_HOSTHost running DFHack's remote RPC server. Defaults to 127.0.0.1.
DFHACK_MCP_ACTUATORSSet to any value to expose the write tools. Unset, the server is read-only.
DFHACK_PORTPort for DFHack's remote RPC server. Defaults to 5000.
| 이름 | 설명 | 유형 |
|---|---|---|
| DFHACK_HOST | Host running DFHack's remote RPC server. Defaults to 127.0.0.1. | |
| DFHACK_MCP_ACTUATORS | Set to any value to expose the write tools. Unset, the server is read-only. | |
| DFHACK_PORT | Port for DFHack's remote RPC server. Defaults to 5000. |
자동 검사
2026년 11월 13일에 실행됨전체 보고서 →자동 검사를 통과했습니다. 이는 보안 감사가 아닙니다. 코드를 직접 읽고 서버에 필요한 최소한의 권한만 부여하십시오. 검사 방식
- 소스 저장소 연결 및 접근 가능alexanderolvera/dfhack-mcp is public and reachablegithub.com/alexanderolvera/dfhack-mcp ↗통과
- 패키지가 이 저장소를 소스로 명시dfhack-mcp names alexanderolvera/dfhack-mcp as sourcenpmjs.com/package/dfhack-mcp ↗통과
- 빌드 출처(Sigstore 증명)Sigstore attestation for dfhack-mcpnpmjs.com/package/dfhack-mcp/v/1.4.1#provenance ↗통과
- 오픈 소스 라이선스 (OSI)ISCspdx.org/licenses/ISC.html ↗통과
- 최근 1년 내 커밋 또는 릴리스Last commit or release 2026-11-11github.com/alexanderolvera/dfhack-mcp ↗통과
- OpenSSF Scorecard검사되지 않음
- 패키지 이름이 인기 패키지와 유사하지 않음No popular package one edit away from dfhack-mcp통과
- 패키지 및 해당 종속성에 중요한 보안 권고 없음113 resolved dependencies checked; no critical advisoryosv.dev ↗통과
- 모델에 대한 숨겨진 지침 없음0 tool descriptions and the README read; no override phrases, credential paths or hidden characters통과
- 파괴적인 도구에 라벨 표시됨검사되지 않음
- 원격 엔드포인트가 MCP 핸드셰이크에 응답검사되지 않음
README
GitHub에서 보기dfhack-mcp
An MCP server that gives an AI client live access to Dwarf Fortress through DFHack. It is an access layer: it reports what is true in the running game and executes exactly what it is asked, and it leaves deciding what matters, and what to do about it, to the client. Point Claude (or any MCP client) at it and ask "how's my fort doing?". The client reads happiness, threats, stocks, jobs, health and defenses straight from the game and does the reasoning itself.
Read-only by default. The 39 sensor and reference tools only observe the game. A handful of actuators that change the fort — queue manager orders, apply quickfort blueprints, assign labor, sound the civilian alert, pull a lever — ship behind an explicit opt-in and stay hidden until you enable them (see Taking action).
Two kinds of tools:
- Sensors answer what is my fort doing right now? —
fort_status,threats,stocks,jobs_and_labor,military,injuries_and_health,defenses, and more. - Reference answers how does Dwarf Fortress work? —
game_datais your world's ground truth (its loaded raws), anddfhack_command_listlists what DFHack itself can do.
It returns facts, not advice: structured JSON in DF's own terms, with no thresholds, triage or strategy text layered on top. Rates, alerts and game knowledge belong to the client. docs/migrating-to-2.0.md lists what moved out of the server in 2.0.
Every tool has a reference page — parameters, return shape, real example output, caveats — in docs/tools.
Quick start
The package is published to npm and ships a prebuilt bundle — there is
nothing to build. Point your MCP client at it with npx:
{
"mcpServers": {
"dfhack": {
"command": "npx",
"args": ["-y", "dfhack-mcp"]
}
}
}
That's it for Claude Desktop / Claude Code / any stdio MCP client. npx -y dfhack-mcp fetches and runs the latest release; its runtime dependencies — the
MCP SDK, zod, and the
dfhack-remote-node RPC
transport — are pulled from npm automatically.
Clients that browse the official MCP Registry
can find this server there as io.github.alexanderolvera/dfhack-mcp; the
listing is generated from server.json and points at the same npm
package, so either route installs the identical build.
Then just have your fort running (next section) and ask your agent something like "check on my fort and flag anything urgent."
Prefer a pinned global install?
npm install -g dfhack-mcp # then set "command": "dfhack-mcp", "args": []
Requirements
- Dwarf Fortress running with DFHack, with a fort loaded. The tools read the live game; if no fort is loaded they say so.
- DFHack Remote RPC on
localhost:5000. This is on by default whenever DF runs with DFHack — no config file to edit. (Theallow_remotesetting only governs connections from other machines and can stayfalse; a local MCP server reaches it either way.) Point elsewhere withDFHACK_HOST/DFHACK_PORT. - Node 20+ to run the published package. (Node 24+ only if you develop from source — see Development.)
What you can ask it
Your agent picks the tools; you just describe what you want. The tools below are what it has to work with.
Sensors — the state of your fort
Each reports on the loaded fort, except game_state(), which works at any screen.
Fog of war is on by default. Undiscovered tiles, the units standing on them and undiscovered caverns never appear. What a player may see past that is the client's call, so every fog-gated tool takes the same optional reveal_hidden: true to bypass it, and every response from one reports fog_of_war: "applied" | "bypassed". The fog-gated tools are defenses, environment, fluids, fort_health, fort_status, geology, historical_figure, livestock_and_pastures, map_overview, military, rooms_and_zones, threats, tile_region and unit_appearance. A bypassed full-map scan (fluids, geology) reads every tile, so it takes longer; raise DFHACK_MCP_TIMEOUT_MS on a large map. See CONTRIBUTING's fog-of-war section.
game_state()— DFHack and DF versions, game mode (title/fortress/adventure/other), whether a world and map are loaded, paused, the raw clock (year,year_tick, formatted date), and the world/fort identity. The one tool that works with no fort loaded; cheap enough to poll.fort_status(reveal_hidden?)— name, date/season, identity (world, save folder, site, civ), population, wealth, happiness breakdown, recent deaths, hostiles on map.stocks(category?)— raw usable counts of food, drink and key materials, a usable count for every DF item type (optionally onecategory), and the population to normalize them by.threats(reveal_hidden?)— dangerous units grouped by type; active vs. contained, great-danger/invader/undead flags, plus each group's decisive traits (trapavoid, flier, fire, webber, building-destroyer, ranged).unmet_needs()— the needs system aggregated: the top unmet needs ranked by how many dwarves are distracted, and how starved each is.jobs_and_labor()— workforce utilization: busy vs. idle adults (children excluded), idle %, and a ranked breakdown of active jobs.military(reveal_hidden?)— squads (each with itssquad_id, the idsquad_orderstargets), enlisted soldiers, filled positions, readiness against hostiles on the map, and per-squad roster equipment gaps (missing uniform pieces), ammo, and active training order.injuries_and_health()— wounded / patients / bedridden / unconscious counts, plus the care needed (diagnosis, surgery, suture, …).defenses(reveal_hidden?)— active hostiles with map positions and distance/direction/z-delta to the fort core and nearest drawbridge, plus a controllable-structure inventory (bridges, levers, floodgates, hatches, cage traps, doors).burrows()— every burrow's size and membership, plus the civilian-alert safety-burrow set (configured/active/linked burrows) — the read half ofcivilian_alert.mechanisms()— every lever's position, state, and linked target(s) (bridge/door/floodgate/hatch/support/weapon-trap); pressure-plate trigger conditions; unlinked levers and bridges.moods()— any active strange mood (fey/secretive/possessed/macabre/fell): the dwarf, driving skill, workshop state, and each demanded material cross-referenced against fort stock — the "demands bones, fort has zero" early warning.mandates_and_justice()— the nobility's overhead: active production mandates and export bans, unmet noble room demands, and justice state (open cases, convictions awaiting punishment, restraint capacity).rooms_and_zones(reveal_hidden?)— the facility inventory, each count paired with its demand-side number: bedrooms, dining halls, the hospital, wells, temples, taverns, libraries, guildhalls, and coffins free vs. dead awaiting burial. The supply-side companion tounmet_needs().trade()— the caravan lifecycle and trade depot: depot existence/completeness and wagon-accessibility, caravans present and their state, broker assignment/presence, and the count and approximate value of goods staged in the depot.environment(reveal_hidden?)— ambient conditions right now: season and weather, surface temperature and whether exposed water is frozen, the embark's biome alignment (evil/good/reanimating), and — for each cavern the fort has already breached — whether it is open or sealed.find_unit(query)— look up citizens by name fragment or profession; a compact dossier per match (profession, age, stress, job, squad, health flags). Chain intocitizenfor depth.citizen(unit_id)— the full character sheet for one dwarf: social graph (spouse/parents/children/friends/grudges, each with aunit_idyou can walk), worshipped deities, notable personality extremes, skills of note, likes/detests, and recent thoughts tied to current stress.unit_appearance(unit_id, reveal_hidden?)— the portrait read for one unit: DF's appearance modifiers (eyes, nose, hair length, build, ...) as raw values with their description band, hair/beard styling, hair/skin/eye colors as DF names them (including age graying), missing parts and scars, and everything worn or wielded with material, quality, wear, dye, and decorations.site_history()— the fort's entry in the world saga: founding, the fort name in Dwarven + English with etymology, prior sieges/battles at the site, and notable figures who died here.historical_figure(hf_id, reveal_hidden?)— one figure's legends entry, dead or alive, fort-dweller or not: name in its native language + English, race/caste, birth and death (cause, site, slayer withhf_id), entity affiliations and positions held, relationships and worshipped deities (each with anhf_idyou can walk), site links, kills, and the saga events that involve them.artifacts_and_engravings()— the fort's masterworks and notable engravings.chronicle()— a scannable recent-events feed for the fort.
Spatial (with fog applied, undiscovered tiles never leak):
-
map_overview(reveal_hidden?)— cheap orientation to run before any per-tile read: map extents, the fort-core coordinate, the surface z-level, the z-levels carrying player activity (digging/construction), and stairways as vertical columns. Fixed-size regardless of fort size. -
tile_region(z?, x0?, y0?, x1?, y1?, reveal_hidden?)— a bounded window of one z-level as an ASCII grid plus a self-describing legend. Undiscovered tiles stay?unlessreveal_hidden. All params optional: none → a 60×40 window on the fort core;zalone → that level's centroid; explicit corners otherwise. Hard-capped at 100×100 (oversized requests are clamped, never errored). Renders the map; never designs it.glyph meaning glyph meaning ?undiscovered (fog of war) +constructed floor #undug stone / wall ~water / brook ,undug soil (sand/clay/loam) %magma .dug floor / walkable ground Wworkshop / furnace Ffortification Sstockpile rramp Mmachine (gear/axle/pump/wheel/windmill) vramp top nfurniture (bed/chair/table/door/etc) <>xup / down / up-down stair (space) open space Ttree -
geology(reveal_hidden?)— a one-call geological survey: surface z-level, the exposed layer stack with material names, the aquifer (light vs. heavy, z-range), discovered caverns, whether the magma sea is reached, and surface water.
Reference — how DF works
game_data reads a loaded world; dfhack_command_list works without one.
game_data(query, kind?)— your world's raws across six kinds (creature,material,plant,reaction,item,building; defaultcreature). Ground truth for procedural creatures (demons, forgotten beasts, titans) that never reach the wiki.queryis a token (DEMON_4,INORGANIC:IRON), a name ("plump helmet"), or — for creatures — a liveunit_id. One strong hit → a full dossier; several → a disambiguation list; none →{"match_count":0,"matches":[]}.dfhack_command_list(filter?)— every command DFHack itself ships (built-ins, plugins, scripts) from DFHack's ownls: name, one-line help, and tags, plus the tag list fromtags.filteris a tag or a name substring. Reports what exists, not what to run; works without a fort.
Taking action (actuators)
By default every tool above only reads the game. The actuators change the
fort, so they ship behind an explicit switch — set DFHACK_MCP_ACTUATORS and they
appear in the tool list; leave it unset and the server is strictly read-only.
{
"mcpServers": {
"dfhack": {
"command": "npx",
"args": ["-y", "dfhack-mcp"],
"env": { "DFHACK_MCP_ACTUATORS": "1" }
}
}
}
Every actuator uses the same preview → confirm → apply → undo safety loop, so a change is never a surprise:
- Preview (dry-run). The agent calls the tool with the operation fully
specified but no confirmation token. It gets back a
previewof exactly what would change — facts, never advice — plus a single-useconfirm_token. Nothing is written. If the operation can't be applied as asked (e.g. a malformed blueprint), the preview reports why and no token is issued. - Apply. The agent calls again with the same arguments plus that token. The
server re-checks that the thing being acted on hasn't changed since the
preview; if it has, the token is void and the agent re-previews. On success it
gets an
undohandle and areadbackfrom the matching sensor confirming the change.
Tokens are single-use and target-scoped: an unrelated change elsewhere in the fort does not void them, but a change to the target does. Each actuator names its own reversal path.
Manager work orders
work_order_list(after_id?)— read-only, always available. The fort's manager orders as facts: id, job type, output item/material, amount total/left, repeat frequency, bound workshop, and per-order validation state. Paged (cap 256) with a cursor.work_order_create(job_type, amount, frequency?, material?, item_type?)— queue a new order; the preview flagswould_duplicateandmanager_present. Reversal:work_order_cancel.work_order_cancel(order_id)— remove one order by id; the undo handle is a recreate spec (with afaithfulflag when a workshop binding or conditions can't be fully restored).
Quickfort blueprints — designate dig/zone from an agent-drafted quickfort CSV. There's no separate read sensor: blueprint_apply without a token is the preview.
blueprint_apply(csv, anchor_x, anchor_y, anchor_z, mode)— designate from a#digor#zoneblueprint; the top-left cell maps to the anchor. The dry-run parses quickfort's own stats and previews tiles affected, footprint, and fog-of-war tiles under it (a fact, never blocked). A malformed blueprint blocks with no token (quickfort would partially apply). v1 scope: dig + zone only —build/placeare rejected. Reversal:blueprint_undo.blueprint_undo(csv, anchor_x, anchor_y, anchor_z, mode)— revert a dig/zone designation via quickfort's native undo (same csv/anchor/mode). The token signs a per-cell digest, so any per-cell drift voids it.
Labor via work details
work_details()— read-only, always available. Every work detail (the game's labor groups): name, mode, the labor tokens it enables, and its assigned citizens (id-sorted, capped at 200 with the fullmember_count).assign_work_detail(unit_id, detail, enabled)— add or remove one citizen to/from one detail. The preview reportscurrently_member,resulting_members_count, andonly_member; an already-satisfied request previews as a no-op. Reversal: the same call withenabledinverted.
Emergency response
burrows()— read-only, always available. Every burrow's size and membership, plus the civilian alert's own state:configured(has the fort ever set one up),active(is it sounding right now), and the linked burrow ids.civilian_alert(burrow, enabled)— add or remove one burrow from the civilian-alert safety set.enabled=truealso sounds the alarm if it wasn't already;enabled=falseonly silences it once the set becomes fully empty. Reversal: the same call withenabledinverted.mechanisms()— read-only, always available. Every lever/pressure-plate's position and linked target(s) (bridge/door/floodgate/hatch/support/weapon-trap), plus unlinked levers and bridges.pull_lever(lever_id, urgent?)— queue a job for a dwarf to pull a named lever (urgentdefaults to do-now priority). This queues the job; the physical toggle happens once a dwarf completes it, not on apply. Reversal: pull the same lever again.squad_orders(squad_id, order, ...)— order a squad tomoveto a tile,killnamed units, orcancelits orders. The highest-stakes actuator here: it sends real dwarves into real combat, and the ones who die stay dead. Orders replace rather than stack (DF treats a squad's order list as its whole standing instruction set), so an apply first clears what the squad was already doing. A kill target on an undiscovered tile is refused — targeting it would act on knowledge the fort doesn't have. Reversal:order="cancel", which releases the squad; it does not walk anyone back or un-fight a fight.
Saving the game
game_save()— checkpoint the fort with a quicksave before a large or risky change, so a bad batch can be rolled back by loading the save. Takes no arguments; the dry-run previews the fort and game date being frozen. Two facts to know: the write is asynchronous (DF commits it over the next few frames — the readback confirms the quicksave dispatched, not that the file landed) and it routes through DF's autosave, so it lands in a rotating "autosave" folder per your DF settings rather than overwriting the loaded save. Irreversible: to roll back, load the appropriate save/autosave in DF. Fortress mode only.
Running DFHack's own commands
dfhack_command_list shows everything DFHack can do. dfhack_command_run(command, args?, confirm_token?)
runs a small, hand-reviewed allowlist of those commands, and only when
DFHACK_MCP_COMMANDS=1 is set. That gate is separate from DFHACK_MCP_ACTUATORS,
and neither one enables the other. Any other command line returns
{"error":"not allowlisted"} and never reaches DFHack.
The allowlist is matched per subcommand:
- Read-only, run directly:
seedwatch [status],instruments [list],prospect [-s <sections>] [-v](revealed map only;all/hellare refused). - Mutating, preview → confirm:
enable seedwatch,disable seedwatch,seedwatch <PLANT_ID|all> <target>,seedwatch clear,instruments order <name> [qty]. DFHack has no dry-run for these, so the preview reports the state the command acts on. The apply result reports the undo: the prior seedwatch targets to restore, or the created manager order ids to cancel withwork_order_cancel.
The full allowlist, with each entry's safety note, is in docs/tools/dfhack_command_run.md.
Configuration
All optional, set in your MCP client's env for the server:
| Variable | Default | Effect |
|---|---|---|
DFHACK_HOST |
127.0.0.1 |
Host where DFHack's Remote RPC is listening. |
DFHACK_PORT |
5000 |
Port for DFHack's Remote RPC. |
DFHACK_MCP_ACTUATORS |
(unset) | Set to 1 to expose the write actuators (off = strictly read-only). |
DFHACK_MCP_COMMANDS |
(unset) | Set to 1 to expose dfhack_command_run, which runs an allowlist of DFHack's own commands (separate from the actuator gate). |
DFHACK_MCP_DEV |
(unset) | Set to 1 to expose run_lua, a raw DFHack Lua escape hatch (reads and writes game state; for tool authors only). |
DFHACK_MCP_QUERY_DIR |
src/dfhack-queries/ (dev) / dist/dfhack-queries/ (bundled) |
Overrides the directory from which the MCP query scripts are loaded. |
DFHACK_MCP_TIMEOUT_MS |
30000 |
Per-call deadline, in milliseconds, for each DFHack RPC call. A call that misses it returns TIMEOUT, resets the connection, and is never retried. |
Errors
Every error payload carries a stable, machine-readable code next to the
human-readable error message, so a client can tell the states apart without
matching message text:
{ "error": "no fort loaded", "code": "NO_FORT" }
code |
Meaning |
|---|---|
NOT_CONNECTED |
DFHack could not be reached, even after one reconnect attempt. |
NO_FORT |
DFHack is reachable, but no fort is loaded. |
NO_GAME |
No world is loaded at all (game_data). |
NOT_FOUND |
The id you passed (a unit, a historical figure) does not exist. |
INVALID_ARGUMENT |
The call was well-formed, but the arguments or the game state reject it (for example, a stale confirm_token, or a command outside the allowlist). |
TIMEOUT |
DFHack accepted the call but did not answer within DFHACK_MCP_TIMEOUT_MS. The call is not retried, so it may have partly run. |
SCRIPT_ERROR |
The query script or DFHack command ran and failed. |
NOT_CONNECTED, TIMEOUT, SCRIPT_ERROR and the actuators' INVALID_ARGUMENT
come back as MCP tool errors (isError: true). The others (the no-fort guard, a
missing id) are ordinary tool output. Arguments that fail a tool's input schema
are rejected by the MCP SDK before the tool runs, as plain text with no code.
Troubleshooting
{"error":"no fort loaded","code":"NO_FORT"}— DFHack is reachable but you're at the title screen or in the menus. Load a fort in Fortress mode."code":"TIMEOUT"— DFHack is reachable but did not answer in time (the game is hung, a modal dialog is open, or a long save is running). The next call reconnects. RaiseDFHACK_MCP_TIMEOUT_MSif your fort is large enough that a normal call takes longer than 30 seconds.- An error about not reaching DFHack — Dwarf Fortress isn't running with
DFHack, or the RPC port differs. Confirm DF is up with DFHack and that
DFHACK_HOST/DFHACK_PORTmatch (defaults127.0.0.1:5000). - The tools don't show up in your client — restart the MCP client so it relaunches the server; a running server won't pick up a config change.
- The write tools are missing — that's the default. Set
DFHACK_MCP_ACTUATORS=1(see Taking action). dfhack_command_runis missing — it has its own gate. SetDFHACK_MCP_COMMANDS=1(see Running DFHack's own commands).- First call after loading a fort errors once, then works — a freshly-started DFHack can reject the very first tool call while it finishes registering the query scripts; retry once.
Dwarf Fortress (DFHack) MCP 질문
Dwarf Fortress (DFHack) MCP를 Claude Code에 추가하려면 어떻게 하나요?
터미널에서 claude mcp add dfhack-mcp -- npx -y dfhack-mcp를 실행합니다. 모든 프로젝트에서 사용할 수 있게 하려면 --scope user를 추가합니다.
Dwarf Fortress (DFHack) MCP를 Cursor에 추가하려면 어떻게 하나요?
~/.cursor/mcp.json를 열고 mcpServers 아래에 서버를 추가합니다. 위 설치 섹션에 표시된 Cursor 구성을 사용합니다.
이 서버를 통해 AI가 제 게임의 내용을 변경할 수 있나요?
기본적으로 서버는 읽기 전용입니다. 노동 할당이나 레버 조작처럼 요새를 변경할 수 있는 액추에이터는 숨겨져 있으며, 사용자가 명시적으로 활성화를 선택해야만 사용할 수 있습니다.
AI가 현재 안개(fog of war)에 가려진 지도 부분을 볼 수 있나요?
발견되지 않은 타일과 유닛은 기본적으로 숨겨지지만, 대부분의 도구에는 안개를 무시하고 숨겨진 정보를 드러내는 선택적 파라미터가 포함되어 있습니다.