Skip to content

feat: add built-in MCP server - #136

Open
LibraHp wants to merge 2 commits into
originalnicodr:masterfrom
LibraHp:master
Open

LibraHp wants to merge 2 commits into
originalnicodr:masterfrom
LibraHp:master

Conversation

@LibraHp

@LibraHp LibraHp commented Aug 29, 2026

Copy link
Copy Markdown

Summary

This PR adds a native MCP server directly inside CinematicUnityExplorer.

The MCP server is implemented entirely in C# and runs inside the game process. It does not require Node.js, an
external bridge process, or any additional runtime dependency.

The implementation supports both legacy SSE and Streamable HTTP transports, selectable from the in-game MCP settings
panel.

Preview

ScreenShot_2026-08-30_122237_529

Changes

Built-in MCP server

  • Add a native MCP server under src/MCP/.
  • Implement JSON-RPC request handling inside the DLL.
  • Add support for:
    • initialize
    • notifications/initialized
    • ping
    • tools/list
    • tools/call
  • Add Unity main-thread request queuing and execution.
  • Ensure Unity object access and mutations are performed from the Unity update loop.

Runtime game-control tools

Add MCP tools for:

  • Querying runtime status.
  • Listing loaded scenes.
  • Searching and inspecting GameObjects.
  • Reading fields, properties, and nested member paths.
  • Discovering instance and static methods.
  • Modifying fields and properties.
  • Modifying transforms.
  • Enabling and disabling GameObjects or components.
  • Invoking methods with converted arguments.
  • Creating GameObjects, primitives, and components.
  • Destroying GameObjects.
  • Executing multiple operations in sequence.

IL2CPP compatibility

  • Add runtime type resolution for IL2CPP-generated wrapper types.
  • Support accessing fields and methods declared on IL2CPP-derived game classes instead of only the exposed base
    wrapper type.
  • Add value conversion between JSON values and CLR/Unity/IL2CPP values.
  • Avoid passing System.Collections.Generic.List<T> into IL2CPP Unity APIs where
    Il2CppSystem.Collections.Generic.List<T> is required.

HTTP transports

  • Add legacy SSE transport support.
  • Add Streamable HTTP transport support.
  • Allow switching transport mode from the MCP UI.
  • Keep the server bound to the loopback address by default.
  • Add bearer-token authentication.
  • Add request size and queue limits.
  • Add configurable request timeout and per-frame execution limits.

MCP settings UI

Add a scrollable MCP settings panel with the same visual style as the other CUE panels.

The panel provides controls for:

  • Enable/disable MCP.
  • Transport mode.
  • Bind address.
  • Port.
  • RPC path.
  • Health-check path.
  • Authentication token.
  • Health endpoint authentication.
  • Read-only mode.
  • Dangerous-operation permission.
  • Request logging.
  • Request timeout.
  • Maximum request body size.
  • Maximum pending requests.
  • Maximum requests executed per frame.

The UI also displays runtime status and generates client configuration information for Agent/MCP clients.

Documentation

Add:

  • docs/MCP.md
  • docs/MCP_SECURITY.md

The documentation describes:

  • DLL-only deployment.
  • SSE and Streamable HTTP configuration.
  • Trae configuration.
  • Available MCP tools.
  • Read-only and dangerous-operation modes.
  • Authentication requirements.
  • Runtime and prompt-injection security considerations.
  • Object-handle lifetime limitations.

Security considerations

The MCP server is disabled by default and binds to 127.0.0.1 by default.

Mutation and dangerous operations are protected by runtime checks:

  • Read-only mode blocks mutation operations.
  • Dangerous operations require an additional explicit permission.
  • Authentication is enforced inside the DLL.
  • Batch operations apply permission checks to each sub-operation.
  • Requests are queued before Unity main-thread execution.
  • The server does not rely on MCP client-side approval settings for security.

Users should only enable write access for trusted local MCP clients and should use a recoverable test save.

Compatibility

The implementation is intended to support:

  • Standalone Mono builds.
  • Standalone IL2CPP builds using Unhollower.
  • IL2CPP interop builds.

The MCP transport and runtime code does not depend on Node.js or an external process.

Testing

  • Performed static source review of the Mono/IL2CPP Dropdown API differences.
  • Verified that the transport-mode dropdown uses individual Dropdown.OptionData entries, which avoids the IL2CPP
    List<T> type mismatch.
  • Verified that test scripts and the legacy mcp-server/ Node.js adapter are not part of this PR.
  • Full project build was not run in this environment.
  • Manual validation in a target Unity game is still recommended for:
    • SSE connection establishment.
    • Streamable HTTP requests.
    • Trae MCP configuration.
    • IL2CPP-derived field/property access.
    • Method invocation and mutation permissions.

barankrky added a commit to barankrky/UnityExplorer that referenced this pull request Sep 19, 2026
Add a native MCP (Model Context Protocol) server that runs inside the
UnityExplorer DLL. No Node.js, stdio adapter, or external bridge process is
required, and no new third-party dependency is introduced.

Transport (src/MCP/Transport):
- McpHttpBridge: loopback-only HTTP server built on TcpListener, with bearer
  token auth, request size and header limits, bounded request queue, and
  per-request timeout. Non-loopback peers are rejected at the socket level.
- Legacy HTTP+SSE and stateless Streamable HTTP modes, selectable in the UI.
- JsonWire: dependency-free JSON scanner so the transport works on net35 and
  IL2CPP without pulling in a serializer.
- Handlers are only ever invoked from the Unity main thread; network workers
  parse, authorize, and enqueue, then PumpMainThread dispatches.

Protocol and runtime (src/MCP/Runtime):
- McpNativeProtocolHandler implements initialize, notifications/initialized,
  ping, tools/list, and tools/call. Negotiated protocol versions span
  2024-11-05 through 2025-11-25.
- McpGameCapabilityExecutor exposes 13 tools: get_status, list_scenes,
  search_objects, get_object, get_member, list_methods, set_member,
  set_transform, set_enabled, invoke_method, create_object, destroy_object,
  and execute_batch.
- McpObjectRegistry hands out session-local object handles keyed by native
  instance ID for IL2CPP wrapper stability.
- McpValueCodec and McpMemberPath handle JSON <-> CLR/Unity conversion and
  nested member paths, including write-back for boxed value types.
- McpReflection resolves IL2CPP-generated types via GetActualType so members
  declared on derived wrappers stay visible, and respects UnityExplorer's
  reflection blacklist.

Security defaults: MCP is disabled, binds 127.0.0.1, starts read-only with
dangerous operations off, and auto-generates a token when none is set. The
dangerous-operations flag is reset to off on every startup. Permissions are
enforced in the executor, so execute_batch cannot bypass them.

UI and wiring:
- McpPanel configures enable/disable, transport, port, paths, token,
  read-only mode, dangerous operations, logging, and limits, and shows live
  status plus copyable client configuration.
- ConfigManager gains the MCP_* settings; ExplorerCore initializes the
  manager, ExplorerBehaviour pumps and shuts it down.
- docs/MCP.md and docs/MCP_SECURITY.md document setup, the tool list,
  permission matrix, runtime limits, and the threat model.

Adaptations from the reference implementation
(originalnicodr#136):
- Scene handle reads go through UnityHelpers.GetSceneIntHandle() instead of
  Scene.handle directly, so list_scenes and search_objects work on Unity 6.3+
  where handle became a SceneHandle struct.
- The 2026-07-28 protocol revision is not advertised, because it mandates
  Mcp-Method/Mcp-Name headers this transport does not implement.
- The panel calls McpManager directly rather than through a reflection
  bridge, since the server is compiled into this assembly.
- Docs are English and naming reflects UnityExplorer rather than the fork.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant