Merge of the two project copies into one self-contained plugin (the superset: variable_op + variables.py, full pcg_op runtime/declarative/preset ops, the CreateWidgetFloatAnimation widget tool, and full Voxel graph authoring). Made fully project- and machine-agnostic — no hardcoded paths: - New src/projectPaths.js auto-detects the host .uproject (walk-up), project name, Editor build target, log file, and engine install (EngineAssociation via launcher manifest/registry, else installed-engine scan). All overridable via UE_* env vars. - Rewired buildOrchestrator/insights/launcher/insightsExporter/server.js and the Python workers (cpp_scaffold, live_coding, apply_graph, console) off the old C:/Github/ihy, IHY*, E:/UE_Versions and UE_5.7 literals onto the resolver. - Voxel made optional: Build.cs auto-detects the Voxel plugin (env UE_MCP_WITH_VOXEL override) and the C++ compiles to stubs under WITH_MCP_VOXEL, so the module builds in projects without Voxel; .uplugin marks Voxel optional. - De-branded the agent-gateway and docs; scrubbed a leaked API key; excluded node_modules/Binaries/Intermediate/__pycache__/secrets from the repo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
In-engine agent gateway
A local HTTP/SSE server that runs a Claude agent (via the Claude Agent SDK)
wired to this project's ue-blueprint MCP server, and serves a chat
UI for the Unreal WebBrowser widget. Talk to the agent from inside the
editor while it edits Blueprints, spawns nodes, builds C++, screenshots UMG, etc.
WBP_AgentChat (WebBrowser) ──HTTP/SSE──▶ server.mjs (this)
public/ chat UI ├─ @anthropic-ai/claude-agent-sdk (the agent)
stream text + tool cards ├─ spawns ../src/server.js (ue-blueprint MCP)
clickable /Game asset chips └─ /api/focus → UE Remote Control (sync Content Browser)
One-time setup
-
Install deps (already done once):
cd Plugins/UEBlueprintMCP/agent-gateway npm install -
Give the agent credentials. The gateway spawns its own agent process, so it needs auth that does not depend on your interactive Claude Code session. Pick one:
-
Subscription (recommended) — generate a long-lived token:
claude setup-tokenCopy the printed token into
agent-gateway/auth.env(gitignored):CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-... -
API key (pay-as-you-go) — in
auth.env:ANTHROPIC_API_KEY=sk-ant-api03-...
GET /api/healthreturns"hasAuth": falseuntil one is present, and the chat header shows a "no token" state. -
-
Enable UE plugins: Web Browser (for the widget) and Remote Control API (for live tool access —
WebControl.StartServer, default port 30010).
Run
npm start # → http://127.0.0.1:8765
or double-click start-gateway.bat.
Open http://127.0.0.1:8765 in any browser to test the UI without UE.
Inside Unreal
Open /Game/UI/Agent/WBP_AgentChat, add it to the viewport (or dock it in an
Editor Utility Widget). It hosts a full-bleed WebBrowser pointed at the gateway
URL. See ../UI_WORKFLOW.md note: this screen is a deliberate exception to the
UMG-token rule — all visuals live in public/styles.css (the :root block),
not in DA_UITheme, because the surface is HTML inside a browser.
Config (env vars)
| var | default | meaning |
|---|---|---|
MCP_AGENT_PORT |
8765 |
gateway port |
MCP_AGENT_HOST |
127.0.0.1 |
bind host |
MCP_AGENT_MODEL |
claude-opus-4-8 |
agent model |
UE_PROJECT_DIR |
repo root (auto) | project cwd handed to the agent |
UE_REMOTE_CONTROL_URL |
http://127.0.0.1:30010 |
UE Remote Control (asset focus) |
Endpoints
GET /— chat UI (static frompublic/)GET /api/health—{ ok, model, projectDir, mcp, hasAuth }POST /api/chat—{ message, sessionId? }→ SSE stream of:init·text·thinking·tool_start·tool_end·error·done.done.sessionIdis replayed by the client to continue the conversation.POST /api/focus—{ path: "/Game/..." }→ focuses the asset in UE's Content Browser (used by clickable asset chips).
Notes
- The agent runs with
permissionMode: bypassPermissions(no interactive terminal exists behind a web UI) and inherits the projectCLAUDE.mdviasettingSources: ["project"], so it follows the same conventions Claude Code does — including the MCP-first and UI vision-loop rules. - Conversation state is per
sessionId(SDKresume); the browser keeps it in memory for the page session.