Skip to content

Repository files navigation

Overdare MCP

An MCP server that lets AI agents (Claude Code / Claude Desktop) drive OVERDARE Studio — browse the DataModel, create and edit instances, write Luau scripts, and start playtests.

How it works

OVERDARE Studio already hosts a local JSON-RPC server (the same one its built-in "diligent" agent uses). This MCP server is a thin bridge to it — much like unity-mcp's connector, except Studio hosts the local server itself, so there's no plugin to install.

Claude  ──stdio──▶  overdare-mcp  ──raw TCP──▶  Studio RPC        (127.0.0.1:13377)
                                  ──HTTP────▶  UE Remote Control (127.0.0.1:30010)
                                                  └─ OVERDARE Studio (must be running)

Port 13377 is not HTTP. It is newline-delimited JSON-RPC 2.0 straight over a TCP socket, one connection per call — speaking HTTP at it yields a protocol violation instead of a response. Remote Control on 30010 is HTTP, and is a separate surface (the overdare_rc_* tools) that reaches the Unreal editor underneath rather than the OVERDARE DataModel.

Studio must be open with a project for tools to work. If Studio isn't running, tools return a clear "cannot reach Studio" error instead of hanging.

Setup

npm install
npm run build

Verify the connection (open OVERDARE Studio first):

npm run probe                                   # smoke test + level.browse
npm run probe -- instance.read '{"path":"Workspace.Baseplate"}'   # inspect any method

Register with Claude Code

Add to .mcp.json in your project (an example is included in this repo):

{
  "mcpServers": {
    "overdare": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/overdare-mcp/dist/index.js"]
    }
  }
}

For Claude Desktop, add the same block under mcpServers in claude_desktop_config.json.

Configuration (env vars)

Var Default Purpose
STUDIO_HOST localhost Studio RPC host (STUDIO_RPC_HOST also accepted)
STUDIO_PORT 13377 Studio RPC port (STUDIO_RPC_PORT also accepted)
STUDIO_RPC_TIMEOUT_MS 10000 Per-call timeout
OVERDARE_PROJECT_DIR auto-detected Fallback project directory for the file-backed tools
OVERDARE_BLENDER auto-detected Blender executable used by overdare_mesh_prepare

Tools

Three backends sit behind these, and the difference matters when something fails. RPC talks to Studio live over 13377. File edits the saved .ovdrjm and asks Studio to reload, which is how the tools whose RPC method does not exist are implemented — stop any playtest before using those. Each such edit first copies the level into .ovdr-backups/ beside it, keeping the last ten, and reports the path it wrote. RC is Unreal Remote Control on 30010.

Reading

Tool Via Purpose
overdare_browse RPC level.browse Browse the DataModel tree. Start here — everything else targets guid
overdare_find File Search by name substring and/or class; far more practical than browsing a large project
overdare_read_instance File Read one instance's properties as saved
overdare_script_read File Read a script's Luau source
overdare_validate_lua luau-lsp Type-check scripts against the OVERDARE type definitions
overdare_status Report what is reachable and configured

overdare_validate_lua runs the luau-lsp and overdare-types.d.lua that ship beside Studio's bundled agent, so it knows the real API surface — it will tell you that Key 'Bold' not found in external type 'TextLabel', which is exactly the kind of break an engine update causes and that otherwise only shows up as a runtime warning in Sandbox.log. It takes scripts already in the project (by GUID or dotted path, as overdare_find reports them) or files on disk.

Its blind spot is worth knowing: a local from Instance.new("TextLabel") is not narrowed to TextLabel, so property errors on that local go unreported. Annotate the local, or check the value at runtime with overdare_observe.

Editing

Tool Via Purpose
overdare_create_part File Create a Part
overdare_create_instance File Create one instance of any class
overdare_create_instances File Bulk-create under one parent in a single reload
overdare_update_instance File Change properties and/or rename
overdare_move_instance File Reparent
overdare_duplicate_instance File Copy a subtree with fresh GUIDs
overdare_delete_instance File Delete by GUID
overdare_instance_create RPC instance.create Create live, under one parent, no reload
overdare_instance_update RPC instance.update Change properties live, no reload
overdare_instance_delete RPC instance.delete Delete live, without a reload
overdare_script_add File Create a Script / LocalScript / ModuleScript
overdare_script_edit File Replace a script's source, or toggle Enabled

Prefer the RPC three when you are iterating: the file-backed tools rewrite the project and ask Studio to reload, so they need the playtest stopped, while these go to the running editor. Two things about them are worth knowing before you trust a result:

  • Properties go flat. Nesting them under a Properties key does not fail — the call succeeds, message says Properties is not a valid property of Frame, and every value is dropped. Same for a misspelled property name: a [WARNING] in message, not an error. Read message.
  • A class this build lacks is not an error either. The call succeeds and returns fewer GUIDs than you asked for. overdare_instance_create pairs them back up and reports guid: null per instance. UICorner, UIGradient, UIPadding, UISizeConstraint, UITextSizeConstraint, ViewportFrame, TextBox, CanvasGroup and VideoFrame are all absent; UIStroke, UIListLayout, UIGridLayout, UIAspectRatioConstraint, ProgressBar and ScrollingFrame are present.

Composite property values are tagged objects, and UDim2 spells its second axis with a lower-case y — an upper-case Y is silently dropped. Rather than write those by hand, pass the array short forms (Size: [0.5, 10, 0, 64], BackgroundColor3: [20, 180, 90], AnchorPoint: [0.5, 1]); see src/props.ts.

Project lifecycle

Tool Via Purpose
overdare_save RPC level.save.file Save the project to disk
overdare_apply RPC level.apply Reload pending level changes
overdare_publish RPC level.publish Publish to the Hub (owner only)
overdare_set_project Re-detect or pin the project directory

Playtest and viewport

Tool Via Purpose
overdare_play / overdare_stop RPC game.play / game.stop Start / stop a playtest
overdare_screenshot RPC game.screenshot Capture the viewport and return the image. UI is included; locate projects instances into click coordinates
overdare_camera RC Aim the editor camera before a screenshot
overdare_viewport RC Read or change how the editor viewport renders

Runtime observation

Only meaningful while a playtest is running. A screenshot shows pixels and the saved project shows what was authored; neither shows what the running game currently holds, which is where UI bugs live — a label a script rewrote, a frame a layout pushed off screen, a button buried under a higher ZIndex.

Tool Via Purpose
overdare_pie_status RPC game.pie.status Is a playtest running, and which clients take input
overdare_ui_browse RPC game.ui.browse The live UI as flat elements: path, class, text, normalized rect, visibility
overdare_observe RPC game.observe Character, UI, and live instance state in one game-thread read
overdare_character_read RPC game.character.read CFrame, speed, facing, what it stands on
overdare_input_inject RPC game.input.inject Keys, pointer, look, scroll, waits — up to 64 events

Two things the underlying method does not tell you, which the tool handles:

  • pieSessionId and clientId are mandatory on the wire. Omitting either fails the batch with the same Invalid input event as a malformed event, so overdare_input_inject resolves both from game.pie.status when you leave them out.
  • action: "press" is documented but rejected by this build; only down/up are accepted. The tool expands press into a down/wait/up triple so the short form still works.

Pointer events only land on the part of the viewport that lies inside the Studio window. When the window hangs off screen the reachable region shrinks — sometimes to a sliver — and overdare_ui_browse reports it under viewport.reachable. The game still renders the whole frame, so a screenshot looks fine while a click at those coordinates goes nowhere.

Assets

Tool Via Purpose
overdare_assets List the curated Asset Drawer catalog
overdare_asset_import RPC Import an Asset Drawer model by id
overdare_image_import RPC Import a local PNG/JPG into the asset manager
overdare_mesh_prepare Blender Make a 3D file import-ready (see below)
overdare_mesh_bulk_import GUI Drive many prepared meshes through the import dialog
overdare_engine_assets RC Query the engine asset registry
overdare_rc_search_assets RC Search the Unreal asset library

Unreal Remote Control (low level)

Tool Purpose
overdare_rc_call Call a UFunction on an Unreal object
overdare_rc_property Read or write a property
overdare_rc_describe Describe an object's properties and functions
overdare_rc_list_actors / overdare_actors Enumerate live actors and their object paths
overdare_selection Read or change the editor's actor selection
overdare_console Run a console command or read a cvar
overdare_rc_batch Several RC requests in one round-trip
overdare_rc_python Run an Unreal Python command

overdare_rc_batch and overdare_rc_python do not work against a shipping Studio build: PUT /remote/batch has crashed Studio outright, and ExecutePythonCommand returns 400 because the Python plugin is not loaded. They are kept for builds that do support them.

Escape hatch

Tool Purpose
overdare_rpc Call any Studio RPC method with raw params
overdare_recipe Read a build recipe adapted from the built-in agent's skills

Smart mesh import (overdare_mesh_prepare)

OVERDARE caps imported meshes at 30,000 triangles per mesh and recommends 512px textures (large 4K textures OOM the importer). overdare_mesh_prepare runs headless Blender to make any .fbx / .obj / .glb / .gltf / .blend import-ready:

  • decimates an over-budget mesh to fit the triangle limit,
  • downscales & re-embeds textures to the target size,
  • writes a self-contained <name>_overdare.fbx.

The final Import into Studio (Home ▸ Import) is still a manual GUI step. Requires Blender installed — Steam installs are auto-detected; set OVERDARE_BLENDER to override the path.

Switching projects (overdare_set_project)

The .ovdrjm file-edit tools now auto-follow whichever project is open in Studio (recovered from its screenshot path). After switching projects in Studio, call overdare_set_project with no args to re-detect, or pass a dir to pin a specific project directory. OVERDARE_PROJECT_DIR remains a fallback.

Which RPC methods actually exist

Method names were originally read out of the Studio runtime, and several of them turned out not to be dispatchable. Probed against a live Studio (2026-09-07):

Present. level.browse · level.apply · level.save.file · level.publish · instance.create · instance.update · instance.read · instance.move · instance.delete · game.play · game.stop · game.screenshot · game.observe · game.ui.browse · game.pie.status · game.character.read · game.input.inject · viewport.camera.read · viewport.camera.set · hub.token.read

Absent — these return -32601, so anything routed to them fails: every script.* method, instance.upsert, procedural.run, the asset-import methods, and validatelua. They belong to the bundled agent, not to the RPC surface. The script and instance tools here go through the project file instead, which is why they carry the "stop the playtest first" caveat.

There is no discovery method — rpc.discover and system.listMethods are both absent. To check whether a method exists, call it with empty params and read the error: -32601 means no such method, anything else means it is there. npm run probe -- <method> '<json>' does this, and overdare_rpc is the fallback for a method with no dedicated tool.

About

MCP server bridging OVERDARE Studio's local RPC (13377) + UE Remote Control (30010) so AI agents can browse, edit, script, playtest, and publish OVERDARE games.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages