Raw IPC
The Dalamud IPC gates behind the client, for plugins that do not use XivMcpClient.cs.
For plugins that do not use XivMcpClient.cs.
- XIV MCP's gates are named
XivMcp.<Gate>. Yours are named<InternalName>.XivMcp.<Gate>. - XIV MCP's gates reply with
{"ok": true, …}or{"ok": false, "error": "…"}and never throw into your plugin. owneris yourIDalamudPluginInterface.InternalName. Registering from your constructor is fine.
Gates XIV MCP provides
| Gate | Signature | Returns / does |
|---|---|---|
ApiVersion | Func<int> | 2 |
IsReady | Func<bool> | True while loaded |
ListCapabilities | Func<string> | {"capabilities":[{"id","risk","title","description","default"}]} |
RegisterTool | Func<string owner, string definitionJson, string> | {"name","enabled","awaitingConsent","state","capabilities":[{"id","mode"}]} |
UnregisterTool | Func<string owner, string name, string> | {"removed": bool} |
UnregisterAll | Func<string owner, string> | {"removed": count} |
GetStatus | Func<string owner, string> | {"state","canRun","suspendReason","tools":[{"name","mode","own"}],"capabilities":[{"id","mode"}],"dependencies":[…]} |
DeclareDependencies | Func<string owner, string json, string> | Declares the tools your jobs use (see below); returns {"dependencies":[…]} |
CheckPermission | Func<string owner, string capability, string> | {"mode":"allow"|"ask"|"deny","enabled","suspended","state"} |
RequestApproval | Func<string callId, string requestJson, string> | Request {"capability","summary"}; returns {"approvalId","state"} |
GetApproval | Func<string approvalId, string> | {"state":"pending"|"approved"|"denied"} |
CompleteCall | Func<string callId, string resultJson, string> | Finishes a pending call |
FailCall | Func<string callId, string message, string> | Fails a pending call |
ReportProgress | Func<string callId, string text, string> | Adds a job log line |
StartJob | Func<string owner, string jobJson, string> | Job {"name","steps":[{"id","tool","args","note"}]}; returns {"job":{…}} |
GetJob | Func<string id, string> | {"job"} |
ListJobs | Func<string owner, string> | {"jobs"}: the jobs your plugin started |
PauseJob / ResumeJob / CancelJob | Func<string id, string> | Job control |
Ready / Disposing | messages | Register on Ready; stop running calls on Disposing |
state is one of undecided, kept_disabled, enabled, awaiting_consent or suspended.
Tool definition
{
"name": "myplugin_restock",
"description": "Buys what your list is short of from the nearest vendor.",
"inputSchema": { "type": "object", "properties": {} },
"readOnly": false,
"destructive": false,
"capabilities": ["move_character", "game_ui", "spend_gil"]
}capabilities is required unless readOnly. readOnly and destructive cannot both be true, and unknown capability ids are rejected.
Dependencies
The declaration replaces the previous one; {"tools": []} clears it.
{
"tools": [
{ "tool": "navigate_to" },
{
"tool": "otherplugin_announce",
"plugin": "OtherPlugin",
"name": "Other Plugin",
"repo": "https://example.com/repo.json",
"minVersion": "1.2.0"
}
]
}A built-in tool is named alone; naming a plugin for one is refused. Any other tool needs plugin, name, repo (an https:// URL, or "official") and minVersion. At most 64 tools.
Each entry of dependencies in the reply and in GetStatus:
{
"tool": "navigate_to",
"plugin": null,
"state": "ok",
"message": "Ready. Without vnavmesh: XIV MCP puts a flag on …",
"install": [
{
"plugin": "vnavmesh", "name": "vnavmesh",
"repo": "https://puni.sh/api/repository/veyn",
"needed": false, "installed": false, "outdated": false,
"reason": "Walks there for you.",
"without": "XIV MCP puts a flag on your map and waits …"
}
]
}state is one of the dependency states. install lists the plugins to install, enable or update. needed: true is a plugin an integration tool cannot run without (state is then needs_plugin); needed: false is one an XIV MCP core tool can use, with without saying what XIV MCP does instead.
Gates your plugin provides
| Gate | Signature | Does |
|---|---|---|
<InternalName>.XivMcp.Invoke | Func<string callId, string tool, string argsJson, string> | Runs a tool on the framework thread, after the permission checks. Reply with {"result": …}, {"error": "…"} or {"pending": true}; finish a pending call with CompleteCall / FailCall. |
<InternalName>.XivMcp.Cancel | Action<string callId> | Optional: stop a pending call. |
CompleteCall and RequestApproval may be called from inside Invoke, before you reply.
A call that takes a minute
CompleteCall takes the result itself, not wrapped in {"result": …}. The approval request is {"capability": "spend_gil", "summary": "Repair for 3,200 gil"}.
XIV MCP sets no time limit of its own on pending calls. When an AI app calls your tool directly, the app's own time limit applies, often a minute; when it gives up, you get Cancel. Approval windows decline after two minutes, and after a Cancel XIV MCP waits up to two minutes for your CompleteCall or FailCall.