Content
FairyGUI-MCP-Headless
Local FairyGUI headless creation MCP for AI Agents. It maps FairyGUI projects into a restricted, strongly-typed DOM intermediate model, allowing Agents to reuse HTML/CSS knowledge of trees, selectors, and styles to complete batch queries, atomic edits, runtime previews, publishing, and validation, but does not claim compatibility with browser DOM or complete CSS.
V1 uses Node.js 24, TypeScript ESM, local stdio, FairyGUI-dom, and Playwright Chromium. Windows is the only officially developed, tested, and screenshot baseline; the source code does not depend on Windows-only packages or platform-specific business logic, and Linux/macOS does not provide active adaptation, CI, or visual baseline.
## Installation
```sh
pnpm add --global @magicskysword/fairygui-mcp-headless
pnpm exec playwright install chromium
```
The browser must be installed explicitly. The service will not silently download Chromium, nor will it fall back to Edge, Tauri, or system WebView. When the browser is missing, `fairygui.render_component` returns `BROWSER_NOT_INSTALLED` and an explicit installation command.
MCP host configuration example:
```json
{
"mcpServers": {
"fairygui": {
"command": "fairygui-mcp-headless"
}
}
}
```
## Seven Tools
| Tool | Purpose |
|---|---|
| `fairygui.project` | `open/list/status/close` multi-project sessions, transaction recovery, and service version information |
| `fairygui.query` | Named batch queries for packages, resources, components, DOM, references, capabilities, and audits |
| `fairygui.apply_dom_patch` | Atomically modify a single component using insert, update, move, remove, and replace operations |
| `fairygui.apply_resource_operations` | Preview or execute creation, import, replacement, renaming, moving, and deletion of resources |
| `fairygui.render_component` | Named batch rendering, returning PNG, status interpretation, diagnostics, version, and fidelity |
| `fairygui.publish` | Use project settings to publish fully or only definitions, optionally for all or specified packages |
| `fairygui.validate` | Execute `quick/roundtrip/publish/full` validation |
All tools return only two types of top-level results:
```ts
{ ok: true, data, warnings? }
{ ok: false, error: {
code, message, path?, actual?, allowed?, suggestedFix?,
transactionId?, logPath?
} }
```
Invalid calls set MCP `isError:true` simultaneously. Validation discovering project issues is still a legitimate execution, resulting in `{ok:true,data:{valid:false,...}}`. Named queries or named rendering items can partially fail, but write batches never partially succeed.
## Agent Recommended Loop
1. Open the project with `fairygui.project` and save `projectId`.
2. Use a single `fairygui.query` summary to locate packages, components, and resources in bulk.
3. Before writing DOM, query the target with full details and read `skills/fairygui-headless/references/dom-authoring.md` within the package.
4. Preview with `dryRun:true` first; merge same intentions into a single DOM or resource write call.
5. After writing successfully, call `fairygui.render_component` in sequence for named batch screenshots.
6. Continue adjusting based on PNG, status information, and diagnostics, and finally call `fairygui.validate`.
7. Call `fairygui.publish` only when the formal product is needed, and then close the project session.
Server instructions and package `skills/fairygui-headless/SKILL.md` contain this set of disciplines.
## Compact Queries, Status, and Validation
`fairygui.query` receives up to 100 named queries. Large results default to `detail:"summary"`, with a default of 50 items per page; only explicit `detail:"full"` returns complete paths, sizes, export information, or strongly-typed DOM for direct patching. Continue pagination by passing opaque `cursor` as is.
DOM queries use `instanceProjection:"none"|"summary"|"full"` to control component instance source projection, defaulting to `"none"`. Results also contain read-only `state- Controller current and total pages;
- Gear type, applicable pages, default values, and current page valid- Effective visibility and hidden reasons in default state; explicitlyunknown` when unable to statically determine.
Named queries partially failing still have top-level `ok:true`, MCP `isError:false`, and return `PARTIAL_QUERY_FAILURE` via `warnings`; each query key retains its own success or error envelope queries can filter by package, component, source kind,, name, and path.
`fairygui.validates `detail` also defaults to `"summary"`, returning check counts, stage metrics and code statistics, and limited diagnostics; only `"full"` returns all IDs and diagnostics.
`fairygui.project` action results contain service package name, version, DOM Schema version, and three fork runtime versions for confirmation.
## DOM and Selector Boundaries
- Common styles use `left/top/width/height/opacity/rotation/scaleX/...`, with JSON numbers not carrying `px`; does not support `calc()`, `vw/vh`, or `x/y/alpha` aliases.
- Selectors only support type, `#id`, `[name="..."]`, compound selectors, descendants, and `>`.
- All write targets must declare `expectedMatches`, failing immediately if the match count does not match.
- New nodes in the same batch are referenced by `clientRef`; the server generates stable and compatible IDs.
- Component instances are boundary nodes by default; `instanceProjection` only provides read-only source projection.
- Group members are still sibling nodes and reference `groupId`; List/Tree items are not ordinary child nodes.
V1 can write image, text, rich-text, input-text, loader, graph, movie-clip, group, static list, instance, component root basic properties, 25 Relations, component scrolling/overflow, five static List layouts, and horizontal/vertical Group. Tree, virtual List, Controller/Gear-driven layout, Transition, Loader3D, Spine/DragonBones, and custom extensions are reserved as planned or read-only.
### General DOM Patches
`fairygui.apply_dom_patch` only accepts five batch-combinable operations: `insert`, `update`, `move`, `remove`, and `replace`. The public MCP Schema strictly describes the operation skeleton; `node` and `changes` are ordinary JSON objects, secondarily validated by the service's internal complete strong-type contract.
```json
{
"projectId": "p_...",
"packageId": "pkg00001",
"componentId": "cmp01",
"operations": [
{
"op": "insert",
"parentSelector": "component-root",
"expectedMatches": 1,
"clientRef": "title",
"node": {
"type": "text",
"name": "title",
"style": { "left": 20, "top": 12, "width": 200, "height": 36 },
"relations": [],
"content": { "text": "Hello" }
}
},
{
"op": "update",
"targetRef": "title",
"expectedMatches": 1,
"changes": { "style": { "opacity": 0.9 } }
}
]
}
```
`update.changes` uses restricted Merge Patch: fields default to no modification, objects recursively merge, arrays replace entirely, and `null` clears optional fields; required fields cannot be cleared. Cannot modify `id/type/readOnly/capability`, and type changes use `replace`. `selector` and `targetRef` must and can only be given one; `targetRef` can only point to earlier `insert` in the same batch. Internal validation failures return `INVALID_PATCH`, with paths precisely down to under `operations[n]`.
Successful results only contain transactions, operation-by-operation summaries, affected nodes, files, and `clientRefs`, without returning the complete DOM; batch queries are needed to confirm results. Any target or-check failure keeps zero writes.
## Resource Preview, Transactions Import
`fairygui.apply_resource_operations`'s `dryRun` defaults to `false`. High-risk calls should use `dryRun:true` first: the service still executes complete model operations, serialization, and read-back validation from the latest disk, but does not create transactions, write to disk, or consume inbox. Results provide operation-by-operation before/after, `affectedReferences`, file writes/moves/deletions, `wouldConsumeInboxPaths`, and `wouldRemoveDirectories`. Actual execution returns corresponding occurred summaries.
Imported files must be placed in:
```text
<project>/.fairygui-mcp/import-inbox/
```
The tool only accepts normative relative paths under this directory, rejecting absolute paths, `..`, symbolic links, directories, and non-ordinary files. Successful transactions consume source files; failed ones retain them. Conflict strategies are `reject|rename|replace`; deletion strategies are `reject|cascade|force`.
After actual resource moves or deletions, the service only cleans up safe empty directories produced by this operation under the project's `assets`; does not delete `assets` itself, nor follow symbolic links. Cleanup failures only produce warnings, without rolling back already successful transactions.
The disk is always the single source of truth. Reads, rendering, and writes refresh external modifications before; there are no drafts, Undo/Redo, revisions, ifMatch, file locks, history, or Git operations. Writes of the same project are serialized in submission order, while queries and rendering can be parallel.
Writes only serialize affected `package.xml`, component XML, and resource files completely. Multi-file transactions use temporary files, journals, before, staged, diagnostics, rollbacks, and startup recovery in the same directory; logs are located in the system temporary directory by default, retained for 7 days, and capped at 1 GiB per project.
## Named Batch Runtime Preview
`fairygui.render_component` only has a named batch form, with a maximum of 20 items; a single component also uses a named key. It never publishes the source project; instead, it temporarily exports all components in an independent memory model, compiles `.fui` and atlases, without publishing in FairyGUI Editor, nor changing project publish settings or disk files.
```json
{
"projectId": "p_...",
"imageResult": "both",
"stateDetail": "full",
"renders": {
"default": {
"packageId": "pkg00001",
"componentId": "cmp01"
},
"page_one": {
"packageId": "pkg00001",
"componentId": "cmp01",
"width": 800,
"height": 600,
"scale": 2,
"state": {
"controllers": [{
"selector": "component-root",
"expectedMatches": 1,
"controller": "start",
"page": { "index": 1 }
}],
"lists": [{
"selector": "list[name=\"items\"]",
"expectedMatches": 1,
"selectedIndices": [1,]
}],
": [{
": "tree[name\"]",
"": 1,
"expansions": [{ [0, 2], "expanded": true }],
"selectedPath0, 2,]
}],
s": [{
"selector": "instance[name\"]",
"expectedMatches": 1,
": { "y": 320 }
}]
}
}
}
```
`imageResult` is"|"file"|`, defaulting"`; `stateDetail` is `"summaryfull"`, defaultsummary"`. Text and structuredContent never contain base64; inline PNGs results via `contentIndex`.
Controller's ` must choose one of `index/id/name`; scroll` must provide at least one axis. Temporary Controller, Tree, and scrolling states only exist in the currentContext. Each resultavailableState`, ``, and Gear hidden summaries, so default blank interfaces can be explained by state information; only `stateDetail:"full"` expands complete Tree paths and other large data.
Single component or state failures retain other results and produce `PARTIAL_RENDER_FAILURE` project session, browser, or shared compilation failures-level failures. Rendering declares:
```json
{
": "fair-dom",
"fidelity": "runtime-preview"
}
```
Preview executes real FairyGUI-dom package loading, component construction, resource parsing, and layout; position, display, image, and color targets are visually close to the Editor; browser font rasterization and other differences may still produce slight pixel jitter, not Unity pixel true values. `scale` controls both PNG device pixel density and `@2x/@3x/@4x` FairyGUI resource levels.
## Formal Publishing
`fairygui.publish` only receives publish scope, publish type, and optional one-time path overrides:
```json
{
"projectId": "p_...",
"packageIds": ["028qk31h"],
"publishType": "full",
"outputPath": "../release/ui"
}
```
Omit `packageIds` to publish all packages; `publishType` defaults to `full`. `definitions` still executes code generation required by description files, external resources, and project only skipping atlas packaging, without judging if can run independently. Omitting `outputPath` reads `settings/Publish.json`; explicit paths only override this runtime output directory, while code output continues using project settings.
Publishing overwrites same-named products but does not clear directories or delete other old files. `validate`'s `publish` mode only validates the publishing link in a temporary directory and forces code generation closure, without producing formal publishing results.
## Local Development and Verification
MCP's `package.json` only writes ordinary SemVer dependencies. The workspace root's `pnpm-workspace.yaml` automatically links OpenFairyGUI and FairyGUI-dom forks during development, without runtime dependencies on sibling directories.
```sh
pnpm install
pnpm test:all
pnpm test:corpus
pnpm benchmark:corpus
pnpm test:pack
```
:pack` packages three forks and MCP, installs four tarballs in a brand-new temporary project outside the workspace, and lists and actually calls all seven tools via the CLI, covering compact/full queries, resource previews, DOM patches, batch rendering, temporary publishing,, and closing sessions. Detailed design is in/architecture.md`](docs/architecture.md); soft performance records are in [`docs/performance-baseline.md`](formance-baseline.md).
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available