mcp server
DalamudAgentBridge
Authenticated local bridge and MCP tooling for safe agent-assisted Dalamud plugin development.
Set up
Runs on your computer. Pick your agent and operating system.
This project does not publish an install method we can turn into a config. Follow the README instead.
README
synced Oct 26, 2026Dalamud Agent Bridge
Local control and inspection utility for bridge-enabled Dalamud plugins, with HTTP, command-line, and MCP surfaces designed for development agents.
The utility discovers named-pipe bridge advertisements under the current user's XIVLauncher plugin-config directory, then exposes a loopback-only dashboard and HTTP API. Access tokens never leave the machine and are never returned by its API.
Contents
- Prerequisites
- Install
- Run
- Safety boundary
- Situation and navigation
- Specialist cockpit
- Screenshot privacy
- Frame-validated control
- Plugin lifecycle
- Connect an agent
- Releases
- Protocol convention
- Contributing
Prerequisites
- Windows 10 version 1809 or newer.
- The .NET 8 SDK for the utility, CLI, and MCP server.
- The .NET 10 SDK is additionally required for connector development.
- A development Dalamud installation and sibling checkout of Franthropy are needed only when building the in-game connector from source.
Connector development expects this layout:
FFXIV-Development/
DalamudAgentBridge/
Franthropy/
Set FranthropyDalamudProject at build time if the repositories live elsewhere.
Connector builds require that checkout to be clean and exactly at the revision
recorded in Franthropy.commit; this makes the bundled patch-sensitive adapter
reproducible instead of silently consuming whichever sibling revision happens
to be present. GitHub CI verifies the same receipt against a checkout of that
commit.
The utility, CLI, MCP server, and their tests consume the published
Franthropy.AgentBridge package and build from a standalone DAB checkout.
Install
Add the FranFkntastic custom repository URL under Dalamud Settings → Experimental → Custom Plugin Repositories:
https://raw.githubusercontent.com/FranFkntastic/DalamudPlugins/main/pluginmaster.json
Install Dalamud Agent Bridge from the Plugin Installer, then use /dab or
the plugin's configuration button to inspect the connector and configure
optional screenshot handoff. Screenshot access remains disabled until enabled
there; agent navigation and specialist automation are separate permissions and
also default to disabled.
Download the matching Windows utility or MCP bundle from GitHub Releases. The in-game connector discovers the local utility through its authenticated current-user bridge; no port, token, or consumer-plugin configuration is required.
Run
Penumbra crash logging
The connector snapshot includes penumbraCrashReporter: availability, the saved
enabled setting, actual running state, Penumbra version/instance, game and reporter
process IDs, and the output log path. Unsupported or unloaded Penumbra reports
unavailable with unknown state, not a misleading disabled value.
The connector window exposes the reviewed action
penumbra.crash-reporter.enabled. It uses Penumbra's own persistent setting and
verifies the resulting reporter state; it does not reload Penumbra, change mods,
or require general plugin-window input permission. Reviews are rejected if the
Penumbra instance or setting changes before invocation. The adapter is compatible
with Penumbra's 1.7.0.12 service layout and fails closed on unsupported layouts.
.\Run-Bridge.ps1
Open http://127.0.0.1:45831.
Use -NoBuild after the first run when no source files have changed.
Each named utility instance builds into its own output directory, so a running primary bridge cannot lock another instance's deployment. For an additional XIVLauncher profile:
.\Run-Bridge.ps1 -InstanceName secondary -Port 45832 -PluginConfigRoot "C:\path\to\profile\pluginConfigs"
Pass -BuildPluginRepository when developing the connector to also create a
private, loopback-only Dalamud repository at
http://127.0.0.1:45831/repository/repo.json. Add that URL under Dalamud
Settings → Experimental → Custom Plugin Repositories. The repository contains
your locally built plugin package and does not require a GitHub token.
Safety boundary
- Binds to
127.0.0.1only. - Requires a per-run, HTTP-only local dashboard session for every bridge API and image request.
- Reads DPAPI-protected bridge access tokens locally; never returns them to clients.
- Enforces its own command allowlist in addition to each plugin's allowlist.
- Exposes pre-player title, lobby, character-list, queue, and error text with
RenderedAddonprovenance;begin-logindelegates low-level lobby mechanics to Lifestream and never receives account credentials. - Game agents, client state, packets, and plugin IPC may supply capability and diagnostics, but rendered identity/confirmation plus the final plugin snapshot remain required at consequential boundaries. A disagreement must fail closed instead of silently choosing one source.
- Plugin lifecycle actions address an exact installed-plugin internal name, refuse to manage the bridge itself, and verify the resulting Dalamud state before returning.
- Local-build replacement validates the source manifest and optional DLL hash, backs up the installed files, and rolls back if replacement or reload fails.
- Unsupported plugins expose only read-only inventory and reversible window presentation. Mutating actions remain limited to explicitly declared, frame-reviewed semantic controls.
The in-game connector also supports get-login-ui and begin-login on its authenticated named pipe. Use tools/Invoke-InGameBridge.ps1; a login target is written as Character Name@Home World, and success means only that Lifestream accepted the work. The caller must still prove the rendered character selection and the eventual logged-in character/world/build.
send-chat accepts one slash command and never accepts plain chat text. DAB gives
registered Dalamud plugin commands first refusal, then forwards an unhandled slash
command to the game's native command shell; its receipt identifies the plugin or
native route. get-chat-log can then confirm local command output such as /echo
without screen automation. Before native fallback, DAB switches ambient chat to the
user-reserved Cross-world Linkshell 2 sink. Explicit chat commands and every alias
derived from all four localized current TextCommand sheets are rejected, as are
every command referenced by the current Emote data; local-only /echo remains
available.
Situation and navigation
bridge_situation gives an agent one bounded, timestamped view of the current
character: territory and map, world and map coordinates, resources and casting,
active condition flags, target and focus target, party, the nearest 48 objects
within 100 yalms, visible decision-oriented game UI, the newest 20 chat lines,
and DAB-owned navigation progress. It uses public Dalamud observations and
rendered addon text; raw addresses and arbitrary reflected game memory are not
part of the schema.
bridge_navigate accepts an exact current territory ID and finite world-space
X/Y/Z coordinates, then delegates pathing to vnavmesh. DAB owns at most one
request at a time, records its starting and best distance, deadline and last
progress time, refuses unsafe client states or territory changes, and exposes
status and guarded cancellation through bridge_navigation and
bridge_navigation_cancel. The permission can only be enabled by the user in
the in-game /dab window; an agent cannot turn it on through a reviewed action.
Specialist cockpit
bridge_specialists discovers DAB's reviewed adapters for installed
Questionable, AutoDuty, Henchman, and Lifestream versions. It reports each
plugin's availability, compatibility and busy state together with typed
capabilities, argument constraints, risk labels, and the current DAB-owned
operation. Discovery and observation are read-only even when specialist
automation is disabled.
bridge_specialist_start accepts only a capability ID returned by that catalog
and parameters declared by its schema. DAB does not expose arbitrary IPC names,
reflection-based invocation, slash-command fallback, or plugin configuration
mutation through this surface. The initial reviewed capabilities are one
explicit Questionable quest, an explicit AutoDuty territory path, Henchman's
published On A Boat and On Your Mark tasks, and typed Lifestream aethernet or
world travel.
Specialist automation has its own default-off permission in /dab. Every
accepted request receives an operation ID, deadline, latest plugin observation,
and terminal state. bridge_specialist_cancel can guard cancellation with that
ID. Navigation and specialist operations share one DAB gameplay-control lease,
so two agent-issued controllers are refused rather than allowed to fight;
specialist work started outside DAB is reported as externally busy and is never
stolen. Individual plugins still execute according to their existing user
configuration and may perform consequential gameplay such as duties, quests,
teleports, or world travel.
Screenshot privacy
bridge_capture_clip reuses the screenshot permission and encrypted handoff to
sample 2-12 ordered full-viewport frames over at most 60 seconds. Every frame is
paired with the contemporaneous situation snapshot, which lets an agent
correlate visible geometry or loading failures with position, conditions, and
vnavmesh progress. The result is a bounded diagnostic clip, not an indefinite
stream or desktop capture.
Screenshot capture is disabled by default and must be explicitly enabled from
the connector's in-game /dab window. Plugin-surface capture requires a
short-lived presentation transaction and captures only the presented plugin
window—not the full desktop.
The plugin encodes the crop in memory, protects the short handoff with Windows DPAPI for the current user, and never writes plaintext PNGs or sidecar metadata. The utility verifies the handoff, immediately deletes it, then stores both the image and its review metadata as separate DPAPI-encrypted files under the current user's local application-data directory. By default a review capture expires after 30 minutes; the authenticated local dashboard decrypts it only in memory for browser delivery. It can be cleared immediately from the dashboard. Browser delivery uses no-store headers and a Blob URL that is revoked when replaced or closed.
This reduces accidental persistence and unauthorised local web access; it does not protect against a compromised Windows user account, a malicious local process, browser extensions with local access, or downstream systems that may retain pixels after display.
Frame-validated control
Plugins may expose their own rendered ImGui controls through the shared AgentBridgeUiReviewRegistry. Each control has a stable ID, visible bounds, value and enabled state, and is actionable only through its named semantic action. The utility must supply the current review-frame ID; the registry rejects stale, disabled, missing, or replayed controls. This is deliberately not arbitrary coordinate clicking or keyboard injection.
For visual testing of unsupported third-party plugins, the user can separately enable bounded surface input in /dab. bridge_surface_interact_capture then presents one discovered IWindow under a runtime-bound lease, maps normalized pointer coordinates only into that window, delivers a short move/click/scroll/drag/text/navigation-key sequence through ImGui's own input queue, captures the settled window, and restores its prior state. It never emits Win32 input, activates the desktop, or targets native FFXIV UI; stale leases, runtime changes, competing sequences, invalid coordinates, and oversized input are refused.
Agents that already know a stable control ID should use GET /api/bridges/{bridgeId}/controls/{controlId}. It returns only that control with the current reviewed frame ID and expiry, so the same small response supports guarded invocation and status polling without serializing the plugin's complete control surface.
POST /api/bridges/{bridgeId}/control-presentations opens an advertised surface and returns up to sixteen requested controls from one current frame. POST /api/bridges/{bridgeId}/control-actions presents one control and invokes that exact reviewed frame in one request; it retains the same enabled-state, expiry, and replay checks as the two-request path.
Plugin lifecycle
The standalone connector manages installed plugins without automating the Plugin Installer window:
GET /api/bridges/{bridgeId}/pluginsPOST /api/bridges/{bridgeId}/plugins/{internalName}/enablePOST /api/bridges/{bridgeId}/plugins/{internalName}/disablePOST /api/bridges/{bridgeId}/plugins/{internalName}/local-build
The local-build request accepts sourceDirectory, optional expectedCurrentVersion and expectedMainDllSha256 guards, enableAfterReplacement, and preserveInstalledManifest (default true). Preserving the installed manifest keeps a hotfix build attached to the package version Dalamud already resolved. It replaces an already installed plugin only; installing a previously unknown repository plugin remains outside this control surface.
Dev-plugin bootstrap is a separate, narrower surface: POST /api/bridges/{bridgeId}/plugins/{internalName}/install-dev (or install-dev-plugin on the named pipe) registers a plugin that already exists on disk under the target profile's own devPlugins directory. The caller supplies an internal name only; the bridge resolves the assembly beneath that root, verifies the manifest matches the requested name, registers Dalamud's supported watched-location entry, scans, loads, and verifies the resulting state. Arbitrary paths and repository installs remain outside this surface.
For repeated development, tools\Test-Bridge.ps1 reuses a successful test result only while the source and test-assembly hashes remain unchanged. tools\Restart-BridgeUtility.ps1 builds through a staging directory, safely restarts a named loopback utility, verifies its DLL hash and listening port, and keeps the complete build and runtime logs under ignored artifacts storage.
Connect an agent
The dab-mcp executable exposes DAB's bridge, manifest, snapshot, log,
capture, deployment, and reviewed-action tools over MCP stdio. Follow the
MCP setup guide for copy-paste Codex CLI and
config.toml registration, verification, and approval defaults.
Releases
Tagged releases provide Windows x64 utility and MCP bundles. Building the
in-game connector still requires a local Dalamud development installation;
maintainers can produce the complete release with
tools/Build-Release.ps1. See docs/releases.md for the
artifact contract and release procedure.
Protocol convention
Bridge-enabled plugins publish agent-bridge/discovery-<pid>.json beneath their plugin config directory and store AgentBridgeAccessToken in the adjacent plugin configuration JSON. Each named-pipe request and response is one JSON line.
Contributing
Pull requests are welcome. Start with CONTRIBUTING.md, target
main, and keep live-client testing separate from
source-only verification. Security-sensitive reports belong in GitHub's private
vulnerability reporting flow described in SECURITY.md.
DAB is licensed under the GNU General Public License v3.0.