Skip to main content
Glama
README.md
# Lanhu MCP 0.2

[简体中文](README.zh-CN.md)

Lanhu MCP is a local, Unity-only MCP server that converts a Lanhu design page into a validated Packet v1, a Unity Plan v1, and an experimental staged UGUI Prefab YAML snapshot.

> [!IMPORTANT]
> The current renderer writes Unity YAML directly; it does not run the Unity Editor. Static verification is required but does not prove that the project compiles, imports without Missing Scripts, or visually matches Lanhu. Complete the [Unity acceptance checks](#unity-acceptance-checks) before treating generated output as production-ready.

## What it supports

- Unity 2022.3 LTS and Unity 6 LTS.
- UGUI hierarchy and presentation components: `GameObject`, `RectTransform`, `CanvasRenderer`, `Image`, `Text`, masks, layout groups, `LayoutElement`, `Outline`, `Shadow`, and `CanvasGroup`.
- Conservative best-effort inference for `Button`, `Slider`, `Toggle`, `ToggleGroup`, `InputField`, `Dropdown`, `ScrollRect`, and `Scrollbar`.
- Downloaded sprites, deterministic `.meta` files, a Prefab Source Map, and an ownership manifest.

Semantic inference is not business-logic restoration. Review inferred component bindings in Unity. No C# Unity Editor importer is shipped in 0.2; the current Direct YAML path is best suited to inspectable snapshots, diffs, and pre-generation.

## Requirements

- Python 3.10 or newer.
- A Lanhu session Cookie for private projects; some DDS sources may require a separate DDS Cookie.
- A Unity project whose root contains both `Assets/` and `ProjectSettings/`.
- Unity's built-in UGUI package; editable text uses `UnityEngine.UI.Text` and the built-in Arial font by default.

## Install and run

From a source checkout:

```bash
python3 -m venv .venv
.venv/bin/pip install -e .
cp .env.example .env
.venv/bin/lanhu-mcp
```

HTTP mode is loopback-only and listens at `http://127.0.0.1:8126/mcp` by default. This server has no remote authentication and must not be exposed to the internet.

For a stdio MCP client, point the client at the absolute path to `run-stdio.sh`. A typical MCP client entry is:

```json
{
  "mcpServers": {
    "lanhu": {
      "command": "/absolute/path/to/lanhu-mcp/run-stdio.sh"
    }
  }
}
```

Client configuration keys vary by MCP host. The equivalent command is:

```bash
MCP_TRANSPORT=stdio /absolute/path/to/lanhu-mcp/.venv/bin/python -m lanhu_mcp
```

## Configuration

Copy `.env.example` to `.env`. For an authorized Lanhu browser session, set the complete request `Cookie` header value; do not commit or share it. `DDS_COOKIE` is separate and never inherits `LANHU_COOKIE`.

| Variable | Default | Purpose |
|---|---|---|
| `LANHU_COOKIE` | empty | Cookie sent only to the configured Lanhu host and subdomains. |
| `DDS_COOKIE` | empty | Optional Cookie sent only to the configured DDS host and subdomains. |
| `DATA_DIR` | `./data` | Managed Packet and downloaded-asset cache. |
| `HTTP_TIMEOUT` | `30` | Positive request timeout in seconds. |
| `SERVER_HOST` | `127.0.0.1` | HTTP bind host; only loopback addresses are accepted. |
| `SERVER_PORT` | `8126` | HTTP port. |
| `MCP_TRANSPORT` | `http` | `http` or `stdio`. |
| `MAX_NODES_PER_RESPONSE` | `200` | Maximum node count for a full response. |
| `MAX_ASSET_BYTES` | `52428800` | Maximum bytes per downloaded asset. |
| `MAX_PACKET_ASSET_BYTES` | `524288000` | Maximum aggregate downloaded bytes per Packet. |
| `ASSET_DOWNLOAD_CONCURRENCY` | `4` | Download workers, from 1 to 16. |
| `HTTP_RETRIES` | `3` | Retry count, from 0 to 3. |
| `UNITY_TEXT_FONT_GUID` | empty | Optional default UGUI `Font` GUID from an imported `.ttf/.otf`. |
| `UNITY_TEXT_FONT_MAP_JSON` | empty | Optional inline source-font-name to UGUI `Font` GUID map. |
| `UNITY_TEXT_FONT_MAP_PATH` | empty | Optional path to a UTF-8 UGUI font map JSON file. |

`LANHU_BASE_URL` and `DDS_BASE_URL` are advanced HTTPS-only endpoint overrides. Process environment variables take precedence over `.env`; restart the MCP process after changing configuration.

The server intentionally clears `DATA_DIR/packets` and `DATA_DIR/assets` on startup. A `packet_id` and its downloaded files are therefore valid only for the current server process; call `lanhu_prepare_design` again after a restart.

## Prepare Unity text

Editable `UnityEngine.UI.Text` output is enabled by default. During generation, Lanhu MCP scans the target project's `Assets/` tree for `.ttf/.otf` files and matches normalized source names in this order: `family + style/weight`, then `family`. The matched font's `.meta` GUID is written internally as `m_Font` with fileID `12800000`; users do not need to configure GUIDs for normal name-based matching.

Explicit `text_font_map_json` or `UNITY_TEXT_FONT_MAP_*` values override automatic matches, and `text_font_guid`/`UNITY_TEXT_FONT_GUID` supplies a default. These GUIDs must reference imported `.ttf/.otf` files, not TMP `.asset` files. Ambiguous or unmatched names produce warnings; unmatched text falls back to built-in Arial. Set `use_text_components=false` only when intentionally choosing visual-only rasterized text output.

## Quick start workflow

The examples below show MCP tool payloads, not shell commands.

### 1. List designs

```json
{
  "url": "https://lanhuapp.com/web/#/item/project/product?..."
}
```

Call `lanhu_list_designs`, then select a design by exact name, unique partial name, zero-based list index, or the `image_id` already present in the URL.

### 2. Prepare and download

Call `lanhu_prepare_design`:

```json
{
  "url": "https://lanhuapp.com/web/#/item/project/product?...",
  "design": "Home",
  "force_refresh": false
}
```

Keep the returned `packet_id`. This step fetches sources, normalizes nodes, downloads assets into the managed cache, validates the Packet, and records partial download failures as warnings.

### 3. Inspect readiness

Call `lanhu_inspect_design` before writing Unity files:

```json
{
  "packet_id": "0123456789abcdef0123",
  "view": "summary"
}
```

Review `unity_readiness.status`, `blockers`, `review_items`, missing assets, and missing font mappings. Use `view="unity_plan"` to inspect the exact creation/component plan, `view="assets"` for download state, and `view="slices"` for Sprite candidates.

### 4. Generate the Prefab snapshot

```json
{
  "packet_id": "0123456789abcdef0123",
  "unity_project_path": "/absolute/path/to/UnityProject",
  "overwrite": false,
  "prefab_visual_mode": "layered",
  "use_text_components": true,
  "component_policy": "conservative"
}
```

The Unity project path must be the project root, not its `Assets/` directory.

### 5. Verify generated files

Generation runs a staged static verification automatically. It also returns `prefab_asset_path` and `source_map_asset_path`, which can be checked again with `lanhu_verify_unity_prefab`:

```json
{
  "unity_project_path": "/absolute/path/to/UnityProject",
  "prefab_asset_path": "Assets/LanhuMCP/Home/Prefabs/01234567_ViewRoot.prefab",
  "source_map_asset_path": "Assets/LanhuMCP/Home/Prefabs/01234567_ViewRoot.design-to-unity.json"
}
```

`pass_with_warnings` requires review; it is not the same as production acceptance.

## Tool reference

### `lanhu_list_designs`

| Parameter | Required | Default | Description |
|---|---:|---|---|
| `url` | Yes | — | Lanhu project URL containing `pid`/`project_id`. |

### `lanhu_prepare_design`

| Parameter | Required | Default | Description |
|---|---:|---|---|
| `url` | Yes | — | Lanhu project URL. |
| `design` | No | `null` | Name, unique partial name, list index, or URL `image_id`. |
| `force_refresh` | No | `false` | Bypass an intact same-version cache in the current process. |

### `lanhu_inspect_design`

| Parameter | Required | Default | Description |
|---|---:|---|---|
| `packet_id` | Yes | — | ID returned by prepare. |
| `view` | No | `summary` | `summary`, `full`, `tree`, `nodes`, `assets`, `slices`, `unity_profile`, or `unity_plan`. |
| `node_ids` | For `nodes` | `null` | One node ID or a list of IDs. |
| `max_depth` | No | `3` | Tree depth, clamped to 0–20. |
| `include_style` | No | `true` | Include style/text fields in tree output. |
| `include_reference` | No | `false` | Include the whole-design reference in slices/plan output. |
| `component_policy` | No | `conservative` | `conservative` or `structure_only` for the Unity Plan. |

### `lanhu_generate_unity_prefab`

| Parameter | Required | Default | Description |
|---|---:|---|---|
| `packet_id` | Yes | — | Prepared Packet ID. |
| `unity_project_path` | Yes | — | Unity root containing `Assets/` and `ProjectSettings/`. |
| `asset_root` | No | `Assets/LanhuMCP` | Generated directory below `Assets/`. |
| `prefab_name` | No | `<packet-prefix>_ViewRoot` | Optional generated Prefab name. |
| `overwrite` | No | `false` | Replace only paths owned by the same Packet manifest. |
| `include_reference` | No | `false` | Copy/include the whole-design reference asset. |
| `use_text_components` | No | `true` | Generate editable `UnityEngine.UI.Text`; `false` explicitly chooses rasterized text. |
| `component_policy` | No | `conservative` | `conservative` or `structure_only`. |
| `prefab_visual_mode` | No | `layered` | `layered` or `flattened_reference_overlay`. |
| `text_font_guid` | No | empty | Optional default UGUI Font GUID from an imported `.ttf/.otf`. |
| `text_font_map_json` | No | configured/empty | Optional source-font-name to UGUI Font GUID mapping; overrides automatic name matches. |

### `lanhu_verify_unity_prefab`

| Parameter | Required | Default | Description |
|---|---:|---|---|
| `unity_project_path` | Yes | — | Unity project root. |
| `prefab_asset_path` | Yes | — | Prefab path beginning with `Assets/`. |
| `source_map_asset_path` | No | adjacent derived name | Source Map path beginning with `Assets/`. |

Every tool response includes `api_version: "0.2"` and an envelope `status`. Expected failures use `{code, message, details, retryable}`. A successful envelope may still contain a domain `result_status`, readiness blockers, generation warnings, or verification status `pass_with_warnings`; inspect those fields before continuing.

## Rendering and overwrite policies

### Visual modes

- `layered` is the default editable output. Recognized and downloaded source assets are copied into `Sprites/` and bound to layer `Image` components.
- `flattened_reference_overlay` uses the whole-design reference image as the visible baseline. It deliberately suppresses normal source-layer visuals while retaining hierarchy, metadata, and transparent interaction overlays. It requires a usable `design.reference_asset_ref`; if that reference download is missing or failed, do not use this mode.

`include_reference=true` copies the whole-design reference; it does not control whether normal slices are downloaded or imported.

### Component policies

- `conservative` emits inferred interactive components only when confidence is at least `0.8`, no semantic review is required, and all required serialized references are available.
- `structure_only` emits hierarchy and presentation components without inferred interaction.

### Overwrite safety and limitation

Output is built in staging, statically verified, and transactionally committed. `overwrite=false` rejects collisions. `overwrite=true` can replace only files listed in the same Packet's ownership manifest; failures restore replaced files, and historical orphans are reported rather than deleted.

> [!WARNING]
> Ownership protection prevents overwriting unrelated files, but it does not merge edits inside an owned generated Prefab. Direct YAML performs a full snapshot regeneration. With `overwrite=true`, scripts, UnityEvents, animations, extra children, and manual field changes added directly to the generated Prefab may be lost. Keep custom behavior outside the generated Prefab or preserve it manually until an Editor-based incremental importer exists.

## Generated output

With the default `asset_root`, output resembles:

```text
Assets/LanhuMCP/<design-name>/
├── Sprites/
│   ├── <generated images>
│   └── <generated image .meta files>
├── Prefabs/
│   ├── <name>.prefab
│   ├── <name>.prefab.meta
│   ├── <name>.design-to-unity.json
│   └── <name>.design-to-unity.json.meta
└── lanhu-mcp-manifest.json
```

- The Source Map records source node IDs, Unity fileIDs, assets, component counts, policies, and expected import gates.
- The ownership manifest records the Packet owner and SHA-256 of every generated file; do not delete it if you intend to use `overwrite=true` later.

## Unity acceptance checks

Static status means:

- `pass`: no static YAML/schema/reference problem was found.
- `pass_with_warnings`: files are structurally usable but listed bindings or resources require review.
- `fail`: regenerate or fix the reported files/references before Unity import.

After a static `pass` or reviewed `pass_with_warnings`:

1. Open/refresh the project in the matching supported Unity Editor.
2. Confirm the project compiles and the Console has no relevant import errors.
3. Open the Prefab and check for Missing Scripts.
4. Confirm generated textures import as Sprites and the Source Map imports as a `TextAsset`.
5. Review UGUI Text font appearance and inferred Slider, Toggle, InputField, Dropdown, ScrollRect, Scrollbar, mask, and layout bindings.
6. Capture a Prefab/GameView screenshot and compare it with the Lanhu reference.

Static verification cannot replace these steps.

## Troubleshooting

| Symptom/code | Meaning and action |
|---|---|
| `output_collision` | A target already exists. Inspect its owner; use `overwrite=true` only when intentionally replacing output owned by the same Packet. |
| `packet_asset_missing` | The prepared Packet points outside or no longer has its managed cached asset. Prepare the design again in the current server process. |
| `missing_asset` / unresolved assets | Inspect `view="assets"`; refresh the Packet and resolve download/export failures before generation. |
| `ugui_text_font_match_ambiguous` | Multiple `.ttf/.otf` files matched the same normalized source name; provide an explicit map or rename the files more precisely. |
| `ugui_text_font_substitution` | No project font matched the source name, so that text uses built-in Arial. |
| Empty/transparent output in `flattened_reference_overlay` | The mode suppresses layer visuals and depends on the reference image. Inspect the reference asset, or regenerate with `layered`. |
| Unsupported Unity version | Use Unity 2022.3 LTS or Unity 6 LTS; other versions are rejected before staging. |
| Static pass but broken Unity output | Static verification does not import or compile Unity. Run the full acceptance checklist above. |

## Data contracts and migration

Version 0.2 intentionally does not load or migrate legacy/unversioned Packets or Source Maps. Canonical JSON Schemas live in `schemas/` and can be regenerated with:

```bash
python -m lanhu_mcp.schema_export schemas
```

See [Security](SECURITY.md), [Architecture](docs/architecture.md), [Data contracts](docs/contracts.md), [0.2 migration](docs/migration.md), [Unity support](docs/unity-support.md), and the [Changelog](CHANGELOG.md).

## Development

```bash
uv sync --extra dev
.venv/bin/ruff check src tests
.venv/bin/mypy src/lanhu_mcp
.venv/bin/pytest
```

## License

MIT

TDQS

A3.7/5.0

Scored across 5 tools

Disambiguation5/5

Each tool maps to a distinct stage in the design-to-prefab pipeline: listing, preparing, inspecting, generating, and verifying. The overlap between list_designs and inspect_design is minimal because one targets project pages and the other targets prepared packets.

Naming Consistency5/5

All tools share the lanhu_ prefix and follow a consistent snake_case verb_noun pattern. The verbs list, prepare, inspect, generate, and verify clearly indicate the action while the nouns identify the target artifact.

Tool Count5/5

Five tools is well-scoped for a focused design-to-Unity-prefab workflow. Each tool has a clear purpose and no redundant operations clutter the surface.

Completeness5/5

The tool set covers the full lifecycle from discovering available designs, preparing and inspecting them, to generating and verifying a Unity prefab. There are no obvious dead ends or missing critical operations for the stated domain.

Maintenance

ActivityStale
ResponsivenessNo issues