Update CLAUDE.md to reflect MCP server and multi-directory input

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 08:20:55 -05:00
parent 241b246e9d
commit d44fabb4e4

View File

@@ -4,32 +4,45 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Purpose ## Project Purpose
UnrealDocGenerator is a tool for generating documentation from Unreal Engine C++ header files. The `samples/` directory contains representative Unreal Engine headers used as test inputs: UnrealDocGenerator is a tool for generating documentation from Unreal Engine C++ header files and exposing it to Claude via an MCP server for item-granularity lookups.
- `samples/GeomUtils.h` — Small utility header (~6 KB): geometry/math helpers in `UE::AI` namespace
- `samples/AIController.h` — Medium header (~22 KB): `AAIController` class with movement, behavior tree, perception, and blackboard integration
- `samples/GameplayTagsManager.h` — Large/complex header (~43 KB): `UGameplayTagsManager` singleton with tag trees, INI/DataTable loading, and editor support
These samples cover a range of complexity (free functions, large classes, deeply nested types, macros, delegates) suitable for stress-testing a parser or doc generator.
## Current State ## Current State
Implementation complete. Three Python files + a Claude Code skill: Implementation complete. Four Python files + MCP registration:
- `ue_parser.py` — Parses UE headers into dataclasses - `ue_parser.py` — Parses UE headers into dataclasses
- `ue_markdown.py` — Renders parsed data as Markdown (ultra-compact format, documented items only) - `ue_markdown.py` — Renders parsed data as Markdown (ultra-compact format, documented items only)
- `generate.py` — CLI entry point; two-pass pipeline (parse-all → build type index → render-all) - `generate.py` — CLI entry point; two-pass pipeline (parse-all → build type index → render-all)
- `.claude/skills/ue-api/SKILL.md` — Claude Code skill; queries docs via `$UE_DOCS_PATH`, falls back to `$UE_ENGINE_ROOT` source headers - `ue_mcp_server.py` — MCP server exposing 5 tools for item-granularity doc lookups
- `.mcp.json` — Registers the MCP server with Claude Code (stdio transport)
## Usage ## Usage
```bash ```bash
python generate.py samples/ docs/ # process directory → docs/ python generate.py <input> [input2 ...] <output_dir>
python generate.py samples/AIController.h docs/ # single file
python generate.py Runtime/Engine/ Runtime/AIModule/ docs/ # multiple directories
python generate.py Runtime/Engine/Classes/GameFramework/Actor.h docs/ # single file
``` ```
Output: one `.md` per `.h` + `docs/type-index.txt` (compact `TypeName: path/to/File.md` lookup). Output: one `.md` per `.h` + `docs/type-index.txt` (compact `TypeName: path/to/File.md` lookup).
Agent lookup pattern: `grep "^AController:" docs/type-index.txt` → instant single-line result. The last argument is always the output directory. All preceding arguments are inputs (files or directories, processed recursively).
## MCP Server
`ue_mcp_server.py` exposes 5 tools Claude can call directly:
| Tool | Purpose |
|---|---|
| `search_types(pattern)` | Regex search over `type-index.txt` — locate a type before fetching details |
| `get_class_overview(class_name)` | Compact view: description + inherits + property/function name lists |
| `get_member(class_name, member_name)` | Full doc for one function or property (all overloads) |
| `get_file(relative_path)` | Full `.md` file — use when you need delegates, enums, or multiple classes |
| `search_source(pattern, path_hint)` | Grep UE source `.h` files via `$UE_ENGINE_ROOT` |
Requires `pip install mcp`. Reads `$UE_DOCS_PATH`; `search_source` also requires `$UE_ENGINE_ROOT`.
Typical query flow: `search_types``get_class_overview``get_member` (~3 calls, ~15 lines vs ~100 lines for a full file read).
## Architecture Notes ## Architecture Notes
@@ -37,14 +50,14 @@ Agent lookup pattern: `grep "^AController:" docs/type-index.txt` → instant sin
- `find_matching_close()` extracts balanced `{}`/`()` while skipping `//`, `/* */`, and string literals. - `find_matching_close()` extracts balanced `{}`/`()` while skipping `//`, `/* */`, and string literals.
- Only items with actual C++ doc comments (`/** */`) are included in output (`_has_doc()` filter). - Only items with actual C++ doc comments (`/** */`) are included in output (`_has_doc()` filter).
- Two-pass pipeline in `generate.py`: Pass 1 parses all files, Pass 2 renders with cross-reference links. - Two-pass pipeline in `generate.py`: Pass 1 parses all files, Pass 2 renders with cross-reference links.
- Multi-input: each `(header, base)` pair tracks its own base dir for correct relative output paths.
- Inline cross-references: base class names linked to their `.md` when in corpus (`_make_type_link()`). - Inline cross-references: base class names linked to their `.md` when in corpus (`_make_type_link()`).
- No "See also" section — inline links in `*Inherits*:` lines cover cross-file navigation.
- Deprecated functions excluded from output (`not f.is_deprecated` in visibility filter). - Deprecated functions excluded from output (`not f.is_deprecated` in visibility filter).
- Enums with no value descriptions use compact inline format (`Values: A, B, C`) instead of a table. - Enums with no value descriptions use compact inline format (`Values: A, B, C`) instead of a table.
- Placeholder descriptions (`------//`) filtered by `_PLACEHOLDER_RE` in `_fn_body()`. - Placeholder descriptions (`------//`) filtered by `_PLACEHOLDER_RE` in `_fn_body()`.
## Critical Gotchas ## Critical Gotchas
- **Never** use `\s` inside a `[...]` character class with `*?` on C++ source — causes catastrophic regex backtracking (hangs on `AIController.h`). Use line-based scanning instead. - **Never** use `\s` inside a `[...]` character class with `*?` on C++ source — causes catastrophic regex backtracking. Use line-based scanning instead.
- Identifier regex must be `r'\w+'`, **not** `r'[\w:~]+'` — the latter consumes `public:` as one token, breaking access specifier detection (all members become `private`). - Identifier regex must be `r'\w+'`, **not** `r'[\w:~]+'` — the latter consumes `public:` as one token, breaking access specifier detection (all members become `private`).
- Module name casing: use `_caps_to_camel()` (not `.title()`) — `AIMODULE.title()``Aimodule` instead of `AIModule`. - Module name casing: use `_caps_to_camel()` (not `.title()`) — `AIMODULE.title()``Aimodule` instead of `AIModule`.