About Dayz Agentic Modding MCP
Dayz Agentic Modding MCP is an MCP server in the Agents category: mCP server for agentic DayZ modding: build, test stand, structured verdict instead of logs, a bridge into the running game, client eyes and hands, an API knowledge index scoped to one server's mod set, and a Blender-to-mod asset pipeline.
Install
git clone https://github.com/covalschi/dayz-agentic-modding-mcpThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Tools (64)
asset_build(mod, source, deploy)binarize a mod's models from their MLOD sources, judge what came out, and only then put it in the mod; returns a job id
Parameters not published.
asset_check(mod, model)judge the models and textures a mod already ships. Builds nothing, needs no DayZ Tools, answers in milliseconds
Parameters not published.
asset_convert(source, output)convert one texture between `.png` and `.paa`, and judge the result
Parameters not published.
asset_export(blend, mod, source, name)export a model out of a `.blend` into `build.project_root`, headless; returns a job id. The **optional** first step — see below
Parameters not published.
bridge_build()pack the bridge mod, whose sources ship with this server (`bridge/`), not with your project; returns a job id. Built **unsigned** — see below
Parameters not published.
bridge_clear(force, probe_window)discard the command stuck in the mailbox, naming what it threw away. Refuses while the bridge looks alive unless `force=True`
Parameters not published.
bridge_status(window)is the bridge inside the running game still ticking: reports the tick number and whether it advanced over `window` seconds. Succeeds only for a tick that actually moved, or for a stand that restarted mid-sample
Parameters not published.
client_chat(text, color)put a line in chat — delivered **server-side by the bridge**, so no keyboard, no window, no focus
Parameters not published.
client_compile_check(extra_mods, wait_seconds)run the diagnostic client and read its logs
Parameters not published.
client_look(x, y, seconds)turn the camera with the right stick. No focus needed
Parameters not published.
Show all 64 tools
client_move(x, y, seconds)walk the character with the left stick. Analog, and the only tract that moves the character at all. No focus needed
Parameters not published.
client_press(button, seconds)one gamepad button, from a closed table of fourteen names. No focus needed
Parameters not published.
client_shot(path)capture the client's window to a PNG, with `lit_fraction` — the number that tells a real frame from an all-black one. No focus needed
Parameters not published.
client_start(timeout, extra_args, window, language)start the game client and connect it to the stand; returns a job id. Always windowed (`window` overrides the machine's own configured size for one launch). `language`, when given, is validated against the engine's own columns and rewritten as `language="<Name>";` into the client's own DayZ.cfg before launch — every other byte untouched — since the engine reads it once, at its own startup, and has no such launch argument. Finishes when the bridge reports `players >= 1` — a count, not a timer
Parameters not published.
client_status()pid, window geometry, whether the window is minimized or in front, the background setting, the player count, and whether a virtual controller is attached
Parameters not published.
client_stop()stop the client this session started, and unplug the virtual controller
Parameters not published.
client_trigger(which, value, seconds)pull an **analog** trigger — `"left"` or `"right"`, travel in `[0, 1]`. This is how the weapon fires: DayZ binds FIRE to the right trigger and RAISE/AIM to the left, and neither is a button. No focus needed
Parameters not published.
client_type(text, submit)type into a client-side input field with real keystrokes. **The only tool here that takes the foreground**, and it says so in its answer
Parameters not published.
client_verdict(since)judge the live client by its own `.RPT` — an errors-and-crashes verdict; see below
Parameters not published.
job_artifacts(job_id)retrieve outputs from a completed job
Parameters not published.
job_status(job_id)status of a long-running job
Parameters not published.
job_wait(job_id, timeout)wait for a job to finish
Parameters not published.
knowledge_build(layer, full, only)build or refresh a layer of the API index; returns a job id. `only=[path]` re-reads exactly the files you name
Parameters not published.
knowledge_callers(name, kind, owner, layer)who **calls** this method or builds this class — every call site, with the class and method that made it
Parameters not published.
knowledge_find(name, kind, owner, layer, prefix, limit)find a class, method, constant, enum or config class by name
Parameters not published.
knowledge_overrides(name, owner, layer)who overrides this class or method
Parameters not published.
knowledge_show(name, ..., body)one declaration in full: signature, members, inheritance chain, and the source itself — read straight out of an archive if that is where it lives
Parameters not published.
knowledge_status()what each layer holds, how old it is, and whether it still matches what is on disk
Parameters not published.
layout_build(mod)generate every `.layout` a project describes under `ui/<Mod>/*.json` from the project's tokens file (`ui/tokens.json` unless `build.tokens` says otherwise) — one JSON per page, containers and tokens instead of coordinates (`color`/`font`/`space`/`size` are the fixed groups; `device` and any further top-level group a project names are read the same way — `$group.name` resolves to a number or a `[w, h]` pair; any other top-level key must likewise be an object, and a string value there is a note, same as `note` itself), list rows as their own files. The page root places itself like any other node: `anchor: "center"` centres the whole page in its host, `at` offsets it; a frame/panel root's `at_frac` offsets it as a fraction of the host instead, at an exact size, and does not mix with `at`, `anchor` or `size: "screen"`. Writes only what changed (LF), refuses the first bad description with file, node and reason. `mod_lint` refuses a generated file that is behind its description (`layout-stale`). The same build without the server: `python -m dayz_mcp.layoutgen <root> [mod]`
Parameters not published.
log_tail(source, pattern, n)last lines, optionally filtered; same two sources
Parameters not published.
log_verdict(source, since)pass/fail with reasons: counters, forbidden strings, warning budget. `source` is `"server"` (the newest log in the stand) or `"client"` (the log the latest `client_compile_check` produced). `since` (an epoch timestamp, e.g. the `since` `server_start` returns) refuses a log written before the run being judged, so a stale log from an earlier boot cannot be mistaken for this one's result
Parameters not published.
mod_build()pack and sign every declared mod; returns a job id. Refuses a second build of the same project while one is still running
Parameters not published.
mod_lint(mod, strict)judge the Enforce Script without packing or booting anything. `mod_build` runs it first and refuses on what it refuses; .layout files: quotes inside text, unquoted keys, unknown classes, ItemPreview priority (refuse), bare edit boxes, unclipped scrolls, duplicate names (warn); a generated `.layout` is rebuilt from its description under `ui/` and compared: behind it refuses (`layout-stale`), generated but described by nothing warns (`layout-orphan`), a description that does not build refuses or a note it raises warns (`layout-desc`)
Parameters not published.
project_open(path)read the profile, discover the game and tools, report what is missing
Parameters not published.
project_status()current project, running server, recent jobs
Parameters not published.
server_signatures(value)read — or deliberately change — the stand's `verifySignatures`. With no argument it only reports. It edits **only** the config the profile names as this stand's, refuses one that resolves outside `machine.stand_root`, refuses while a server is running against it, keeps the file's comments and line endings, and reads the value back out of the file afterwards
Parameters not published.
server_start(timeout)start the test server, finish when it is ready. **Refuses if the mission the config names is not under `mpmissions` beside the executable being launched** (`machine.server` when one is declared, the game install otherwise) — the engine looks for missions beside the executable being run, not beside the `-config`. Returns the `pid` straight away — the process is spawned before the call returns, so the very next tool already sees a running server. Refuses if the game port is already held by someone else, and refuses on the spot if the image cannot be launched. Readiness comes from `expect.ready_line` when declared, otherwise from **two** engine signals together — the port bound AND the mission module compiled. The port binds about 17 s before the scripts do, and a boot called ready in between is listening with no mission: it answers queries and refuses every player. The job summary names which
Parameters not published.
server_status(pulse_seconds)pid, whether the process is alive, whether the log is growing (sampled `pulse_seconds` apart), and how long it has been stalled
Parameters not published.
server_stop(pid)stop the server this session started (optional pid for orphaned servers)
Parameters not published.
ui_click(path, expect_name, expect_class, via)press a widget. `via="script"` goes through the open menu's handler with no focus; `via="cursor"` puts the real mouse on its rectangle **and then asks the client what that did**: `under_cursor` and `hit` (the engine's own hit test), `menu_before`/`menu_after`, `windows_before`/`windows_after`, and `changed`. The path-resolving probe's own "nothing was pressed" is kept as `resolve_detail` and no longer speaks for the click — it was written before the mouse moved
Parameters not published.
ui_cursor()what the real mouse is over right now, from the engine's `GetWidgetUnderCursor`: the widget with its screen path, the open menu class, and how many top-level widgets the workspace holds
Parameters not published.
ui_find(name, class_name, text, root, offset)the same walk, filtered in the client so the whole tree never has to travel — and filtered **during** the walk, before the 300-node ceiling, so a name is found wherever it is rather than only in the first page. `total` is what was walked, `matched` what passed the filter, and `limit`/`offset` page over the matches
Parameters not published.
ui_gallery(index, sizes, langs, strict)every entry of the project's preview index (`preview/index.json` by default) through `ui_preview`, into one `index.html` with every screenshot and its issue counts — the look before a push. Each entry is an object with `name`, `layout`, `fixture` and `host` keys (as `ui_load` takes them) or `live: true` in place of `layout`, with an optional `root` for a live entry that is not the open menu. A failed entry is recorded with its error rather than aborting the run, and counted in `failed`. `sizes`, a list of `[width, height]` pairs, restarts the client at each in turn before that round's entries run (the owner's 3840x1600, the players' 1920x1080); without it the client is used as it is. `langs`, a list of engine language names (validated the same way `client_start`'s own `language` is), restarts the client into each in turn the same way — typically English and the mod's own language — so a layout that only overflows in translation is caught here; rounds are the product of `sizes` and `langs`, each entry's `"language"` key names its round's language (`""` when none), and `strict=True` names failing entries as `name@size@language` once `langs` was given (`name@size` otherwise). Every restarted round is one whose size or language actually changed
Parameters not published.
ui_load(layout, fixture, host, depth, limit, offset)show a layout file in the client under a host of the bridge's own size, and list what the engine made of it. `fixture` fills it first — add rows, set text, show/hide, colour — from a dict, JSON text, or a project-relative `.json` path. The preview stays up for `client_shot` until `ui_unload` or the next `ui_load`; the HUD is hidden meanwhile
Parameters not published.
ui_menu()what the client's interface is doing: open menu class, cursor, dialog. Free — republished every tick
Parameters not published.
ui_preview(layout, fixture, host, live, name, root)a layout as the engine draws it, in one folder: a screenshot, every widget's rectangle, and the rectangle checks, with an HTML report over all three. `live=False` loads `layout` (`fixture`, `host` as in `ui_load`) and shoots the preview host; `live=True` shoots a root that is already on screen instead — the real thing with real data. `root` picks it: empty for the open scripted menu, `"workspace"` for every top-level widget at once, or a **window's name**, which is the only way to reach a panel a mod created under the workspace root rather than as a menu, with every `.layout` the project declares handed to the checks as its sources (`notes` says how many), so a self-sized label is not read as `text_overflow` just because nothing was loaded to compare it against. A drawn node is matched to its source by walking the source tree in the engine's own ascending-`priority` order (stable for ties), not declaration order, so a sibling reordered by `priority` still finds the right node. Pages past the 300-node ceiling on its own
Parameters not published.
ui_text(path, text, expect_name)write into an edit box, and read the value back out of the widget
Parameters not published.
ui_tree(root, depth, limit, offset)the client's **widget tree**: path, class, name, visibility, screen rectangle, depth, text and text size (engine pixels, TextWidget family only). A page, and it says so. `root` is `"menu"` (the default), `"screen"` or `"workspace"` (the same widget under the name that says what it is — the parent of every top-level window, menus and non-menus alike), `"preview"`, **or the name of a widget**, which the client resolves against the whole workspace: a window a mod hangs off the workspace root is not a menu and has no reserved word of its own
Parameters not published.
ui_unload()remove the preview `ui_load` put up, and give the HUD back
Parameters not published.
world_action(action_class, target_class, subject, radius, pos)run a mod's own action through the engine's gate — see below
Parameters not published.
world_attach(class_name, host, slot)attach an item the player **already has** to another of their items. `host` is `"hands"`, `"player"` (the character's own worn slots) or a config class looked up on the player; `slot` names the CfgSlots slot when there is more than one that fits. The mod reads the item's own inventory location back afterwards — the engine call's bool is about the call, not about where the item ended up — **a tick later**, because the move lands after the frame that asked for it, and names the slot the item actually landed in
Parameters not published.
world_delete(class_name, radius, pos)delete objects of one class nearby. Requires the class; never deletes a real player
Parameters not published.
world_detach(slot, host, to)take the attachment out of one slot and put it in the player's `inventory` (default), `hands`, or on the `ground`. The slot is required: a device can have several. In game this is a drag inside the inventory screen, which is not something a tool can ask for. Checks the slot is empty **a tick later**, for the same reason as `world_attach`. `to="hands"` while the hands hold something else is refused by name — the engine's own answer there is a bare false
Parameters not published.
world_entities(class_name, radius, pos, limit)**which** objects are nearby, not how many: class, position, distance and health for each. A page, and it says so — the true total comes back beside the list
Parameters not published.
world_exec(verb, args)the escape hatch: an arbitrary verb through the same transport, marked non-standard in every answer
Parameters not published.
world_move(class_name, to)move an item the player already has between `hands`, `inventory` (default) and `ground` — the drag inside the inventory screen a headless stand cannot make. `class_name` is `"hands"` for whatever is held, or a config class looked up on the player. **Carry it, do not hold it** is where every test of a worn or pocketed device starts, and `world_spawn` cannot get there. An ask that is already true comes back done, not failed; asking for the hands while they hold something else is refused by name
Parameters not published.
world_power(on, target, energy)switch a device on or off wherever it is on the player — worn, in a pocket, in hands — through its energy manager. `energy` optionally fills its own store first. The answer reads both facts back: **switched on and working are different**, and a device switched on with a flat battery has the first without the second
Parameters not published.
world_ready(timeout)wait until the bridge inside the game is actually claiming commands. Call it once after the boot job finishes, before the first world command — see "server ready is not bridge ready" below
Parameters not published.
world_set(what, value, target)set `health` (player or held item) or `quantity` (held item)
Parameters not published.
world_spawn(class_name, where, pos, quantity, slot)create an item on the ground (with no lifetime, so it cannot vanish mid-check), in the player's hands, in their inventory, or attached to the item they are holding (`where="attachment"`, optional `slot` naming the CfgSlots slot)
Parameters not published.
world_state(class_name, radius, pos)snapshot of the world from the bridge's once-a-second publish: players, position, health, hands. Free with no arguments; with `class_name` it also counts objects of that class nearby (one command round trip)
Parameters not published.
world_teleport(pos)move the player to `"x y z"` — the same format `world_state` reports, so a read position can be handed straight back
Parameters not published.
world_time_set(hour, minute, day, month, year)move the world clock. Every field left at -1 keeps its current value, read back from the engine first, because the engine sets a date as five numbers at once
Parameters not published.
world_weather_set(what, value, seconds, duration)move overcast, rain, fog, snowfall or wind. A **nudge, not a lock**: the engine keeps simulating weather afterwards, and both the tool and the mod say so
Parameters not published.
Ask AI
Ask AI about Dayz Agentic Modding MCP
Powered by Claude · Grounded in docs
Security checks
6 checks have not been run yet.