Fix search_source: pass env vars via mcp.json interpolation, search Plugins/, cap at 40 total lines
- .mcp.json: pass UE_ENGINE_ROOT and UE_DOCS_PATH via ${VAR} interpolation so the
MCP server subprocess inherits them without hardcoding paths
- search_source: search both Engine/Source/ and Engine/Plugins/ (path_hint applied
under both); switch from -m 40 (per-file cap) to streaming Popen with a true
40-line total cap; fix UE_ENGINE_ROOT to point at Engine/ not the repo root
- Update README and CLAUDE.md to reflect the above
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,11 @@
|
||||
"mcpServers": {
|
||||
"ue-docs": {
|
||||
"command": "python",
|
||||
"args": ["ue_mcp_server.py"]
|
||||
"args": ["ue_mcp_server.py"],
|
||||
"env": {
|
||||
"UE_ENGINE_ROOT": "${UE_ENGINE_ROOT}",
|
||||
"UE_DOCS_PATH": "${UE_DOCS_PATH}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,9 +38,11 @@ The last argument is always the output directory. All preceding arguments are in
|
||||
| `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` |
|
||||
| `search_source(pattern, path_hint)` | Grep UE `.h` files in `Engine/Source/` and `Engine/Plugins/`; `path_hint` applied under both; returns up to 40 lines total |
|
||||
|
||||
Requires `pip install mcp`. Reads `$UE_DOCS_PATH`; `search_source` also requires `$UE_ENGINE_ROOT`.
|
||||
Requires `pip install mcp`. Reads `$UE_DOCS_PATH`; `search_source` also requires `$UE_ENGINE_ROOT` (must point to the `Engine/` directory, e.g. `/path/to/UnrealEngine/Engine`).
|
||||
|
||||
`.mcp.json` passes both vars via `${VAR}` interpolation — no paths hardcoded.
|
||||
|
||||
Typical query flow: `search_types` → `get_class_overview` → `get_member` (~3 calls, ~15 lines vs ~100 lines for a full file read).
|
||||
|
||||
|
||||
@@ -34,10 +34,10 @@ pip install mcp
|
||||
|
||||
```bash
|
||||
export UE_DOCS_PATH=/path/to/your/generated/docs
|
||||
export UE_ENGINE_ROOT=/path/to/UnrealEngine # optional, for search_source
|
||||
export UE_ENGINE_ROOT=/path/to/UnrealEngine/Engine # optional, for search_source
|
||||
```
|
||||
|
||||
The `.mcp.json` at the repo root registers the server automatically when you open the project in Claude Code.
|
||||
The `.mcp.json` at the repo root registers the server automatically when you open the project in Claude Code. It reads `UE_DOCS_PATH` and `UE_ENGINE_ROOT` from your environment via `${VAR}` interpolation — no paths are hardcoded.
|
||||
|
||||
### Available tools
|
||||
|
||||
@@ -47,7 +47,7 @@ The `.mcp.json` at the repo root registers the server automatically when you ope
|
||||
| `get_class_overview(class_name)` | Description + base classes + 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 — for delegates, enums, or multiple classes |
|
||||
| `search_source(pattern, path_hint)` | Grep UE source `.h` files via `$UE_ENGINE_ROOT` |
|
||||
| `search_source(pattern, path_hint)` | Grep UE `.h` files in `Engine/Source/` and `Engine/Plugins/`; returns up to 40 lines |
|
||||
|
||||
### Typical query flow
|
||||
|
||||
|
||||
@@ -207,15 +207,26 @@ def get_file(relative_path: str) -> str:
|
||||
def search_source(pattern: str, path_hint: str = "") -> str:
|
||||
"""Grep UE source .h files for pattern. Requires $UE_ENGINE_ROOT.
|
||||
path_hint: optional subdirectory under Engine/Source/ (e.g. 'Runtime/Engine').
|
||||
Searches both Engine/Source/ and Engine/Plugins/.
|
||||
Returns up to 40 matching lines with file:line context."""
|
||||
root = _engine_root() / "Engine" / "Source"
|
||||
if path_hint:
|
||||
root = root / path_hint
|
||||
result = subprocess.run(
|
||||
["grep", "-rn", "--include=*.h", "-m", "40", pattern, str(root)],
|
||||
capture_output=True, text=True, timeout=15
|
||||
engine = _engine_root()
|
||||
candidates = [engine / "Source", engine / "Plugins"]
|
||||
search_dirs = [d / path_hint if path_hint else d for d in candidates]
|
||||
search_dirs = [d for d in search_dirs if d.exists()]
|
||||
if not search_dirs:
|
||||
return "(no matches)"
|
||||
grep = subprocess.Popen(
|
||||
["grep", "-rn", "--include=*.h", pattern, *map(str, search_dirs)],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True
|
||||
)
|
||||
return result.stdout or "(no matches)"
|
||||
lines = []
|
||||
for line in grep.stdout:
|
||||
lines.append(line)
|
||||
if len(lines) == 40:
|
||||
grep.kill()
|
||||
break
|
||||
grep.wait()
|
||||
return "".join(lines) or "(no matches)"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user