UE Wingman getting ready for release

This commit is contained in:
2026-03-23 19:34:42 -04:00
parent 928abb5916
commit 4c84b1a5b7
6 changed files with 173 additions and 84 deletions

View File

@@ -2,7 +2,7 @@
"mcpServers": { "mcpServers": {
"ue-wingman": { "ue-wingman": {
"command": "python3", "command": "python3",
"args": ["tools/mcp-bridge.py"] "args": ["Plugins/UEWingman/ue-wingman-mcp.py"]
} }
} }
} }

View File

@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2026 BlueprintMCP Contributors Copyright (c) 2026 UE Wingman and BlueprintMCP Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,72 +1,177 @@
= History # UE Wingman
This plugin was originally vibe-coded by Claude Code. It UE Wingman is a tool that allows an AI to control the unreal
was then posted to David Gundry's github account, here: editor. When you're using it, it feels like the AI is right
there looking at the editor with you. You'll be able to
watch as it creates graph nodes and wires them together,
you'll see it add components to your blueprints, you'll see
it design widget hierarchies for you, and you'll see it write
shaders for your materials.
https://github.com/mirno-ehf/ue5-mcp The tool is not complete, not by a long shot. There are
tons of Unreal Editor functions that the AI just can't
access yet. Even so, I think it's useful: it has pretty
comprehensive support to allow the AI agent to help create
blueprints, widget blueprints, and materials.
He released it under the MIT license. ## How Does it Work?
How do I know it was vibe coded? Because he says so: This tool adds a command interpreter plugin to the Unreal
Editor. You can type commands, and the plugin in the editor
will execute them. You can actually type commands directly
from the command-line. Here's an example of what you might
see:
> For Humans: ```
> $ ue-wingman.py Graph_Dump Graph=/Game/Testing/BP_Test,graph:EventGraph
> You're welcome here, but probably not in the way you'd
> expect. This project is built and maintained entirely by
> AI coding agents — Claude Code, Cursor, Copilot Workspace,
> and the like. We don't accept human-written code or
> human-opened issues.
Huh, interesting. I (Josh Yelon) downloaded the code, and node K2Node_Event_0: Event BeginPlay
evaluated it. I was curious what vibe coding could do. output-pins OutputDelegate
Here's what I found:
* The code, overall, had issues, but in the end, it wasn't node K2Node_Event_2: Event Tick
that bad. It did work, mostly - and that matters. I wanted output-pins OutputDelegate, DeltaSeconds
my own working MCP server, and starting from a place where ```
you have working code is a lot easier than starting from
a blank slate.
* Claude really doesn't build any mechanisms to enforce There are tons of commands built in: Graph_Dump,
consistency. For example: there were all the handlers, and GraphNode_Create, GraphPin_Connect,
then in a different file, declarations of all the handlers, BlueprintComponent_Create, Widget_Create, and so forth.
then in another file registrations of all the handlers with Using these commands, it's possible to examine and modify
the webserver, then in another place a list of all the blueprints, widgets, and materials.
handlers that require undo support, then in an entirely
other directory, a list of all the handlers and their
parameters. If any of these lists got out of sync, it would
break.
* Claude doesn't seem to care at all about extra layers upon But, of course, these commands aren't really intended for humans.
layers, or about dependencies. Rather than building an MCP They're intended for an AI agent. The AI is given access to these
server in an unreal plugin, it built a *web* server in an commands using what's called "Model Context Protocol," which is
unreal plugin, then built an MCP-to-web translation program a goofy name for "a mechanism that an AI can use to send
in *javascript*. Requests to the server were getting commands to other software."
translated from json into URL parameters and then back into
json. Ouch. The javascript required installation of about
a thousand javascript libraries, some of which were not easy
to install. Why not just build an MCP server in the Unreal
plugin directly, skipping all the dependencies and
translation layers?
* Claude will repeat code over and over. I found endless ## Why Choose this Particular Unreal Engine MCP?
places where there were 10 copies of the same function, with
trivial variations, that could have all been merged into one
function with a parameter or two. When it does repeat code,
the repetitions are not generally consistent with each other:
one variant might have a bug, whereas another is fine.
* There were lots of little edge-case bugs throughout the There are a *lot* of Unreal Engine MCPs out there. Some of
code. Claude is actually not bad about noticing edge cases, them are, shall we say, not carefully engineered. I'm a
but it misses some. reasonably skilled software engineer and I've designed
this plugin to be robust and capable of sustained development.
Despite all this, it was much easier to start from something This MCP is also designed to be as broadly general as
than to start from nothing. possible. I've seen many Unreal Engine MCPs that claim "can
create 22 different kinds of graph nodes!" This makes me
ask: why not just provide the *entire catalog* of all
possible graph nodes? I've seen MCPs claim "you can edit 15
different material expression properties!" Why not provide
access to *all* editable material expression properties?
I've tried to make every tool in this MCP as capable as
possible, with as few limits as possible.
So, I undertook a massive refactoring effort. I did use This MCP is very extensible. Adding a new command requires
Claude Code extensively - in fact, I'd say Claude did 70% of a relatively small amount of code. I'm hoping some others
the work. But I monitored every step, and constantly pushed in the community will eventually start contributing new
Claude hard to use better software engineering practices. commands.
## Installation
There are three parts to UE Wingman:
* The Unreal Plugin, which does 99% of the work.
* The python program "ue-wingman.py" which a human can
use to send commands to the plugin.
* The python program "ue-wingman-mcp.py", which an AI
can use to send commands to the plugin.
If you build Unreal from source, the best way to install the
plugin is to drop the entire UEWingman source folder into
your Plugins folder. Then do a build. Restart the editor, and
go into your plugins configuration. Enable the UE Wingman
plugin. You're done.
If you don't build from source, then unfortunately, you're
out of luck. Precompiled plugins must be built for every
different OS, for every different engine version. I just
don't have the means to do that right now.
After installing the plugin, you need to install the two
python programs. They are both short and simple: all they
do is establish a network connection to the plugin, and then
send the command you typed. They require python 3.6 or later,
and no other dependencies.
To install the human version, ue-wingman.py, just drop it into
a folder on your PATH.
To install the AI version, ue-wingman-mcp.py, you have to
usually set up some config file for your AI agent. I use
Claude Code, for that, you have to create a file ".mcp.json"
in your project folder, and it needs to have this inside it:
```
{
"mcpServers": {
"ue-wingman": {
"command": "python3",
"args": ["Plugins/UEWingman/ue-wingman-mcp.py"]
}
}
}
```
You can usually ask your AI agent for help creating this
config file.
## The "User Manual"
You might be interested in seeing the "user manual" for the
plugin. To get that, you type this:
```
$ ue-wingman.py UserManual
```
Of course, you're not the intended user: your AI agent is.
When the AI agent starts up ue-wingman-mcp, it is
automatically told to read the user manual. From there, the
User Manual says, among other things, that the AI agent can
get a listing of built-in commands. You can see that too:
```
$ ue-wingman.py ShowCommands
```
With these two commands at your disposal, you'll have a better
understanding of what exactly your AI agent is doing with this
plugin, and how it all works.
## Fun things to Try
I really started enjoying this plugin when I asked my agent
to make me a "cool looking material, something psychedelic
and weird." It made a neat kaleidoscope thing. I then
asked it to make me an animated rendering of the mandelbrot
set. It's fun to watch it do things like that.
## History and Credits
When I myself needed an MCP for unreal development, I did a
survey of the plugins out there. I ended up choosing a
plugin called "Blueprint MCP" by David Gundry:
<https://github.com/mirno-ehf/ue5-mcp>
It was not bad, but it had some limitations, and I started
doing work to improve it. Incrementally, I ended rewriting
pretty much the whole thing. So this whole project is actually
a fork of Blueprint MCP. There's very little of the original
code remaining. However, you will find snippets here and there.
Even though I ended up rewriting most of the code, it really
was useful to have a functioning starting point. It meant I
could improve one thing at a time, without having to try to
get everything working all at once. So I'm quite grateful
to David Gundry and his work.
## Software License
UE Wingman is licensed under the MIT license, a copy of which
is enclosed. Its predecessor (of which it is a fork) was also
under the MIT license, so everything works out.
The result, I think, is a pretty clean MCP server.

View File

@@ -83,7 +83,7 @@ private:
// ----- TCP server ----- // ----- TCP server -----
FSocket* ListenSocket = nullptr; FSocket* ListenSocket = nullptr;
int32 Port = 9847; int32 Port = 9851;
bool bRunning = false; bool bRunning = false;
// ----- Client connections ----- // ----- Client connections -----

View File

@@ -1,10 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
MCP stdio-to-TCP bridge for BlueprintMCP. MCP stdio-to-TCP bridge for UE Wingman.
Exposes a single MCP tool "unreal" that forwards JSON commands to the Exposes a single MCP tool "unreal" that forwards JSON commands to the
BlueprintMCP TCP server in the Unreal Editor. The tool list is static, UE Wingman TCP server in the Unreal Editor.
so it works regardless of whether the editor is running at startup.
""" """
import sys import sys
@@ -12,12 +11,12 @@ import json
import socket import socket
HOST = "localhost" HOST = "localhost"
PORT = 9847 PORT = 9851
CONNECT_TIMEOUT = 2 CONNECT_TIMEOUT = 2
READ_TIMEOUT = 120 READ_TIMEOUT = 120
TOOL_DESCRIPTION = ( TOOL_DESCRIPTION = (
"Send a command to the Unreal Editor's BlueprintMCP plugin. " "Send a command to the Unreal Editor's UE Wingman plugin. "
"The 'command' field specifies which operation to perform; " "The 'command' field specifies which operation to perform; "
"additional fields are command-specific parameters. " "additional fields are command-specific parameters. "
'Use {"command": "UserManual"} to get an overview. ' 'Use {"command": "UserManual"} to get an overview. '
@@ -118,7 +117,7 @@ def handle_message(msg):
return make_jsonrpc(msg_id, { return make_jsonrpc(msg_id, {
"protocolVersion": "2024-11-05", "protocolVersion": "2024-11-05",
"capabilities": {"tools": {}}, "capabilities": {"tools": {}},
"serverInfo": {"name": "blueprint-mcp", "version": "1.0.0"}, "serverInfo": {"name": "ue-wingman", "version": "1.0.0"},
}) })
if method == "tools/list": if method == "tools/list":

View File

@@ -2,9 +2,7 @@
""" """
Human-friendly MCP test client. Human-friendly MCP test client.
Usage: mcp-test.py ShowCommands Usage: ue-wingman.py UserManual
mcp-test.py ListBlueprintAssets filter=lx
mcp-test.py ShowCommands verbose=true
""" """
import sys import sys
@@ -12,22 +10,14 @@ import json
import socket import socket
HOST = "localhost" HOST = "localhost"
PORT = 9847 PORT = 9851
TIMEOUT = 120 TIMEOUT = 120
# Map ASCII characters to the Unicode geometric delimiters used by the plugin.
DELIMITER_MAP = str.maketrans({
'<': '',
'>': '',
'*': '',
'.': '',
'|': '',
})
def main(): def main():
args = sys.argv[1:] args = sys.argv[1:]
if not args: if not args:
print("Usage: mcp-test.py ShowCommands [key=value ...]") print("Usage: ue-wingman.py ShowCommands [key=value ...]")
sys.exit(1) sys.exit(1)
msg = {"command": args[0]} msg = {"command": args[0]}
@@ -44,11 +34,6 @@ def main():
pass pass
msg[key] = value msg[key] = value
# Translate ASCII delimiter shortcuts to Unicode geometric shapes.
for key, value in msg.items():
if isinstance(value, str):
msg[key] = value.translate(DELIMITER_MAP)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(TIMEOUT) sock.settimeout(TIMEOUT)
try: try: