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 for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
MCP server exposing the Backtest360 engine API as tools for AI agents.
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.9 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