bunny
Provides an always-on MCP proxy in front of the ModelContextProtocol plugin embedded in Unreal Engine 5.8. Exposes Unreal's tool catalog (as ue_* tools) at all times, forwarding calls to the live editor when it is running and returning actionable errors when it is not. Includes proxy-local tools to check UE status, launch the editor, wait for MCP readiness, build the project with Build.bat, kill the editor, refresh the cached tool catalog, discover/adopt projects and engines, and enable or sync toolset plugins in the project's .uproject.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@bunnylaunch Unreal Editor and wait until MCP is ready"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
bunny — always-on MCP proxy for Unreal Engine 5.8
A small proxy that sits between your MCP harness (Junie, Cursor, Claude Code, VS Code, MCP Inspector, …) and the ModelContextProtocol plugin embedded in Unreal Engine 5.8. Two jobs:
Fix the protocol-version deadlock. UE 5.8 whitelists
2025-11-25 / 2025-06-18 / 2024-11-05and replies with2025-11-25to anything else. Kotlin-based SDKs (e.g. Junie's) offer2025-03-26, see2025-11-25back, throwServer's protocol version is not supported: 2025-11-25and mark the server Failed. The proxy negotiates with each side in its own language: it echoes back whatever protocol version the client asked for (including2025-03-26) and talks2025-06-18upstream to UE.Never be offline. The proxy is its own MCP server. UE's tool catalog is cached to
data/tools_cache.jsonon first connect and served even when the editor is closed, so harnesses keep the same stable MCP surface through code → compile → restart-engine loops. Calls toue_*tools route to UE when it is running and return an actionable error when it is not (never a crash/timeout), and localproxy__*tools let the agent run the engine, build the project, and refresh the catalog itself.
harness ──http://127.0.0.1:8765/mcp──► bunny ──http://127.0.0.1:8000/mcp──► UE 5.8
(any protocol version) (shim + cache + launcher) (2025-06-18)Quick start
:: 1. install (once)
uv venv --python 3.14 .venv
uv pip install --python .venv\Scripts\python.exe -r requirements.txt
:: 2. point it at your project + engine
copy config.example.json config.json
notepad config.json
:: 3. run the proxy
bunny.bat
:: -> http://127.0.0.1:8765/health
:: -> MCP endpoint: http://127.0.0.1:8765/mcpInitial tool cache: start UE once, run ModelContextProtocol.StartServer in
its console (or set the plugin's Auto Start Server), then:
.venv\Scripts\python.exe -m bunny.server --refreshAfter that the tools stay cached. UE can come and go freely.
Point your harness at it
CLI-only (there is deliberately no MCP tool for this — it's setup, not a runtime capability):
:: print the entry for a harness to stdout (default --agent claude),
:: plus its default global config location on stderr
.venv\Scripts\python.exe -m bunny.server --emit-client-config
:: write/merge the entry into a file (existing servers in it are preserved)
.venv\Scripts\python.exe -m bunny.server --emit-client-config "C:\path\mcp.json" --agent junie--agent picks the harness syntax and default location:
| Syntax emitted | Default global location (no |
| Claude Desktop |
|
| TOML |
|
|
|
|
| YAML |
|
| VS Code user |
|
|
|
|
Writes merge: JSON files keep their other servers, TOML/YAML replace only the
bunny section. Restart the harness afterwards. Scope notes: Junie project scope
.junie/mcp/mcp.json; Copilot CLI is ~/.copilot/mcp-config.json
(mcpServers + type, write via explicit path); opencode also reads a
project-root opencode.json. Junie example of the emitted entry:
{
"mcpServers": {
"unreal-via-bunny": { "type": "http", "url": "http://127.0.0.1:8765/mcp" }
}
}No special client settings needed: the proxy accepts 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25 and 2026-07-28 clients.
Related MCP server: proxy-mcp
The tool surface
Always available (proxy-local, prefixed proxy__):
Tool | Purpose |
| Is UE's MCP reachable? Editor process running? Launch/build possible? |
| Start the editor ( |
| Block until MCP reachable (use after you start UE manually / after live-coding). |
|
|
| Terminate the editor ( |
| Re-cache UE's tools/resources/prompts (do this after enabling more toolset plugins). |
| Catalog counts, capture time, effective config. |
|
|
| Re-detect the running editor's project+engine and adopt as launch/build defaults. |
| Enable one toolset plugin (e.g. |
|
|
| List every installed engine (version, full build, path, discovery source, which is selected). |
Cached UE tools are listed as ue_<toolname> (e.g. ue_list_toolsets,
ue_call_tool), with their real UE schemas, at all times — UE online or not.
When UE is live they forward verbatim (name demangled) and responses pass
through untouched.
The intended agent loop:
(proxy__ue_status) -> ue offline
(proxy__ue_build) -> compile the C++ you just edited
(proxy__ue_launch) -> editor up, MCP reachable, catalog refreshed
(ue_call_tool) -> routed to the live engine
…close editor… -> proxy stays up, tools stay listed, calls stay actionableConfiguration
config.json (copy from config.example.json), data/, and logs/ live in
the root dir: the folder containing the bunny package, overridable with
the BUNNY_ROOT_DIR env var — point it at a deployment folder to keep your
config/state separate from the source tree and to run several independent
instances. config.json is gitignored; config.example.json is the committed
reference.
Key | Meaning |
| Proxy bind address (default |
| UE MCP endpoint (default |
| Absolute path to your |
|
|
| Derived from |
| Defaults to the Editor target discovered from |
| Build parameters (default |
| Appended on launch; keep |
| Full command templates (placeholders |
| UE liveness poll (default 12s; cache auto-refresh when UE comes up). |
| Long-call budgets. |
| Adoption / relaunch behaviors (see below). |
| Extra folders to scan for engine installs (engines kept outside the standard roots). |
Any key can be overridden per-run with env vars: BUNNY_PORT=8766,
BUNNY_UPSTREAM_URL=…, BUNNY_PROJECT_PATH=… (handy for second instances).
--print-config shows the effective config.
Follows any project (project adoption)
MCP tool routing is project-agnostic: UE owns 127.0.0.1:8000, so whichever
project the editor has open is what the ue_* tools act on. Launch/build
defaults follow it automatically: when UE comes up, the proxy detects the
running editor's .uproject from its command line, resolves its engine,
discovers its build targets from Source/*.Target.cs, and stores the result
in data/adopted.json (survives proxy restarts; config.json stays the
static default). proxy__ue_status shows active_project / active_engine / adopted_from; proxy__ue_adopt_project forces a re-scan after you open a
different project.
Engine discovery is layered, never guessed: running editor's own
executable → Epic Launcher manifests → Windows registry → standard install
roots → scan_extra_roots. When every layer misses, the proxy reports and
asks instead of guessing. Details:
docs/implementation_details.md.
proxy__ue_sync_toolsets {"dry_run": true?} keeps the project's toolset list
lean and engine-proof: AllToolsets is the enable-all switch (its manifest is
engine-maintained), the project file stores only the gap plugins it doesn't
cover. Sync adds missing gap plugins, prunes redundant/vanished ones, respects
explicit Enabled:false opt-outs, never touches marketplace plugins, backs up
the .uproject, and is idempotent. After a real sync run proxy__ue_build
(UE closed) to compile new modules — it auto-relaunches the editor.
proxy__ue_enable_toolset {"plugin": "LiveCodingToolset"} enables any engine
toolset plugin in the active project's .uproject; afterwards run
proxy__ue_build and ue_list_toolsets shows the new toolset.
LiveCodingToolset ships EnabledByDefault: false, so a harness that wants
in-editor compiles calls this once per project.
Notes & limits
The proxy binds to 127.0.0.1 and does not add auth; treat it like UE's own MCP server (local only). UE's optional MCP auth token, if you enable it, is not forwarded — leave UE's server unauthenticated on loopback.
Server→client SSE streams (
GET /mcp) answer 405: allowed by the spec; clients fall back to polling. Catalog freshness comes from refresh-on- launch / refresh-on-UE-boot / 60s-refresh-on-call.Tool-name collisions with harnesses are avoided by the
ue_prefix. Unprefixed cached names are also accepted, in case a harness strips prefixes.Resources/prompts are served from cache when offline;
resources/read/prompts/getneed UE live (forwarded, actionable error otherwise).proxy__ue_launchdetects "editor running but MCP server off" and tells the agent to runModelContextProtocol.StartServerinside it.Launch args must not include
-unattended: UE then runs the ExecCmds and exits seconds later.-ExecCmds=ModelContextProtocol.StartServer -nosplashkeeps the editor alive.The proxy only starts a persistent editor with the GUI
UnrealEditor.exe.UnrealEditor-Cmd.exeis for command/test runs that are supposed to close the engine afterwards. Ifeditor_binarypoints at-Cmd, the proxy silently switches to the siblingUnrealEditor.exe; if that sibling doesn't exist it refuses withcmd_editor_not_allowedand tells you to fixeditor_binary. Editor detection (running_project,proxy__ue_status) still sees-Cmdprocesses — reading is fine, launching is not. Why these rules exist: docs/implementation_details.md.
Running as a Windows service (nssm)
install_service.bat (run elevated — elevate_install.bat elevates it
with one UAC click; set NSSM= at the top of install_service.bat to your
nssm.exe) (re)installs ue-mcp-bunny: app = .venv\Scripts\python.exe -m bunny.server, working dir = the folder containing the script, autostart,
account LocalSystem. Run it from the folder you want the proxy to live in
(that folder holds its config.json / data/ / logs/).
LocalSystem is mandatory — an editor launched from a service must land on your desktop, and only LocalSystem has the privileges to reach the interactive session. Quick check:
sc qc ue-mcp-bunny→SERVICE_START_NAME : LocalSystem, andproxy__ue_status→window.cross_session_route: "WTSQueryUserToken".restartto load new code:nssm restart ue-mcp-bunny(elevated).The full story (why running the service as your user fails, session-0 spawn routes, environment blocks): docs/implementation_details.md.
Tests
:: self-contained (mocked, no real UE needed)
.venv\Scripts\python.exe tests\test_proxy.py :: proxy vs a mock UE (incl. the strict-SDK version deadlock)
.venv\Scripts\python.exe tests\test_sdk_client.py :: via the official MCP Python SDK client
.venv\Scripts\python.exe tests\test_targets.py :: build-target discovery
.venv\Scripts\python.exe tests\test_workspace.py :: harness workspace detection
.venv\Scripts\python.exe tests\test_cmd_guard.py :: proxy never launches UnrealEditor-Cmd.exe
.venv\Scripts\python.exe tests\test_crosssession.py :: session-0 -> interactive-session spawn logic
.venv\Scripts\python.exe tests\test_session_policy.py:: client session/policy bookkeeping
.venv\Scripts\python.exe tests\test_window.py :: child window policies (spawns short consoles)
.venv\Scripts\python.exe tests\test_guardian.py :: keeps build consoles minimized
:: real end-to-end (needs a running proxy + configured project/engine)
.venv\Scripts\python.exe tests\e2e_real.py :: launch -> cache -> real tool calls
.venv\Scripts\python.exe tests\e2e_lifecycle.py --keep-ue :: kill UE -> offline cached tools -> proxy relaunch -> live routing
.venv\Scripts\python.exe tests\e2e_soak.py --minutes 3 :: editor survives 3 min after proxy launch
.venv\Scripts\python.exe tests\e2e_adoption.py :: running project auto-adoption recorded cleanly in data/adopted.json
.venv\Scripts\python.exe tests\e2e_build.py :: build with UE closed -> auto-relaunchLogs: logs/bunny.log (proxy), logs/editor_launch.log (UE), logs/build.log.
Docs
docs/implementation_details.md — design notes: protocol shim internals, engine resolution layers, launch rules and the
-Cmdtrap, the service/session-0 story, toolset sync semantics.
Credits
Vibecode by Qwen Flash Next GSQ RCO IQ3_XXS on Strata engine, Human QA by Charnet3D
This server cannot be deployed
Maintenance
Related MCP Connectors
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal E…
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP server exposing the Backtest360 engine API as tools for AI agents.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceLocal MCP server that exposes fixed tools for GPT, Claude, and Gemini while routing to any OpenAI-compatible chat completions backend with independent configuration per target.1-
- FlicenseAqualityDmaintenanceUniversal MCP proxy server that discovers, searches, and executes tools across all configured MCP servers from a single entry point.7-
- AlicenseNot gradedqualityDmaintenanceThe Forge Engine runtime: a thin, MIT-licensed proxy that connects any MCP client to Forge — the design spec AI coding agents read before building and report back to. Serves the full 54-tool surface; discovery works signed out, tool calls authenticate.10 npmMIT
- AlicenseNot gradedqualityAmaintenanceServes as a single local MCP entry point that proxies configured upstream MCP tools to multiple coding agents, keeps sessions warm, serializes exclusive services, and provides SQLite-backed task, lock, and memory tools.MIT