esc
navigate openSearch by Pagefind

How it works

The addon-as-server architecture, the two-hop runtime IPC, and crash-aware discovery.

godot-mcp (Go CLI / client) --WebSocket (JSON-RPC 2.0) :9080--> Godot editor addon (server)
MCP client (streamable HTTP) --POST /mcp :9100-----------------> |
file IPC (user://) <------+--> running game
(MCPGameInspector / MCPGameInput autoloads)

Not Godot’s built-in CLI

Godot’s own command line (godot --headless, --export-release, --script) starts a fresh engine process each time, which is the right tool for CI exports and batch scripts and has no notion of a session. godot-mcp is the other half: it connects to the editor already running, reaching the open scene, the current selection, the undo history, and the game that editor is playing. Different jobs; use both. godot-mcp itself launches the editor through Godot’s CLI when needed.

The addon is the server

The addon runs a WebSocket server inside the editor, the long-lived process with a stable port. The CLI is a short-lived client that dials in, runs one command, and exits. The serve (MCP) mode is also just a long-lived client of the same server, so one connection model covers both.

  • The server binds 127.0.0.1 only. It is a local dev bridge.
  • The CLI resolves the port from <project>/.godot/godot-mcp.json (written by the addon on bind), so the common case needs no flags.
  • The message envelope is JSON-RPC 2.0 with dotted methods (node.add, scene.play, runtime.capture_frames).
  • The addon hosts a second transport: a streamable-HTTP MCP endpoint (POST /mcp, ports 9100-9115, recorded as http_port in the same discovery file), so an HTTP-capable MCP client drives the editor with no external process. Both transports dispatch through the same command router, so the safety guards below apply to each identically.

The two-hop runtime IPC

runtime and input commands reach the running game, a separate process. The editor brokers that hop over file IPC through two game-side autoloads. The addon self-installs these autoloads on plugin-enable, so they work in any project without being pre-committed.

Crash-aware discovery

The discovery file doubles as a liveness signal. A clean shutdown deletes it; a crash leaves it stale with a now-dead pid. On any connection failure the CLI attaches a verdict:

VerdictMeaning
runningthe server answered a TCP probe
startingthe file is present, pid alive, not bound yet
crashedthe file is present, pid dead
closedno discovery file

Safety guards

  • 127.0.0.1-only bind, never 0.0.0.0.
  • Origin-checked HTTP: the streamable-HTTP endpoint serves requests with no Origin (native MCP clients) or a loopback one and answers anything else with 403, so a web page cannot reach the editor over localhost. Its CORS header names the allowed origin, never *.
  • Audited code execution: both editor.run_script and runtime.eval log the body before running; run_script additionally refuses direct editor write APIs without --allow-unsafe-editor-io.
  • Project-path jailing on every write sink: caller-supplied paths that escape res:// / user:// are rejected.

Threat model

godot-mcp is a local dev bridge on a workstation you trust, and that assumption is load-bearing. While the editor is open with the plugin enabled:

  • The ports are unauthenticated by design. Any process on the machine can drive the editor, which is what lets godot-mcp project info work with no keys, config, or pairing step. Commands reach editor.run_script, so “can connect” means “can run code in the editor”.
  • The HTTP endpoint refuses browser traffic from anywhere but loopback (the Origin check above), so a page you have open cannot reach it.
  • The WebSocket transport has no equivalent gate. Browser WebSockets are exempt from CORS, and Godot gives a GDScript server no access to the handshake headers, so a page could open ws://127.0.0.1:9080 while the editor is running.

That last point is a known and accepted limitation. Closing it means putting a shared secret in the connect URL, and every client (the CLI, serve, and anything you script yourself) would have to carry it and keep it in sync. On a private-network workstation that is a lot of moving parts protecting a small surface.

Some situations are different: a shared or untrusted network, or a browser session you do not control. There, quit the editor when you are not driving it, since the servers exist only while it runs. godot_mcp/network/mcp_http turns the HTTP endpoint off independently, and disabling the plugin stops both.

Built with the help of godot-mcp. MIT licensed.