How to Contribute to the Unity MCP Project: A Complete Developer Guide
To contribute to the Unity MCP project, fork the CoplayDev/unity-mcp repository, create a feature branch off beta, implement parallel changes in both the Python MCP layer (Server/src/services/tools/) and the Unity C# layer (MCPForUnity/Editor/Tools/), add comprehensive tests for both codebases, and submit a pull request targeting the beta branch.
The Unity MCP (Model Context Protocol) bridge enables AI assistants to control the Unity Editor through a dual-layer architecture. Contributors to the CoplayDev/unity-mcp repository must maintain domain symmetry by implementing every feature in both Python (the MCP server side) and C# (the Unity Editor side). This guide walks you through the complete contribution workflow based on the project's CONTRIBUTING.md and CLAUDE.md specifications.
Understanding the Unity MCP Architecture
The repository contains two parallel codebases that communicate via the MCP protocol. Before contributing, understand where your changes must reside:
-
Python MCP Tools (
Server/src/services/tools/) – Exposed to AI assistants via the@mcp_for_unity_tooldecorator. These handle protocol-level communication and forward commands to Unity. -
CLI Commands (
Server/src/cli/commands/) – Python Click interfaces for terminal-based development workflows. -
Resources (
Server/src/services/resources/) – Read-only state exposed via@mcp_for_unity_resourcedecorators. -
Unity Editor Tools (
MCPForUnity/Editor/Tools/) – C# implementations using the[McpForUnityTool]attribute that actually execute operations within the Unity Editor. -
Compatibility Shims (
MCPForUnity/Runtime/Helpers/) – Version-specific adapters for Unity API changes.
Any functional change requires updates to both the Python tool definition and its corresponding C# handler to maintain protocol compatibility.
Setting Up Your Development Environment
Start by forking the repository and configuring your local workspace to track the upstream beta branch.
- Fork the repository on GitHub, then clone your fork:
git clone https://github.com/<your-username>/unity-mcp.git
cd unity-mcp
- Add the upstream remote and create your feature branch:
git remote add upstream https://github.com/CoplayDev/unity-mcp.git
git fetch upstream
git checkout -b feat/your-feature-name upstream/beta
The project uses the beta branch as the active development target. Never open pull requests against main unless specifically requested by maintainers.
Implementing a New Tool (Parallel Implementation)
When adding functionality, you must create mirrored implementations in both languages. The following example demonstrates registering a new tool called manage_example.
Python MCP Tool Implementation
Create your tool definition in Server/src/services/tools/manage_example.py. The @mcp_for_unity_tool decorator registers the function with the MCP server:
# Server/src/services/tools/manage_example.py
from services.registry import mcp_for_unity_tool
@mcp_for_unity_tool(
description="Demonstrates a simple example tool.",
group="core",
)
async def manage_example(ctx, action: str) -> dict:
unity = await get_unity_instance_from_context(ctx)
params = {"action": action}
return await send_with_unity_instance(
async_send_command_with_retry, unity, "manage_example", params
)
Key components include:
@mcp_for_unity_tool– Registers the function with metadata for AI assistants.get_unity_instance_from_context– Retrieves the active Unity connection from the request context.send_with_unity_instance– Forwards the command to the Unity Editor process with automatic retry logic.
C# Unity Editor Implementation
Create the counterpart in MCPForUnity/Editor/Tools/ManageExample.cs. The [McpForUnityTool] attribute maps this class to the Python tool:
// MCPForUnity/Editor/Tools/ManageExample.cs
using UnityEngine;
using UnityEditor;
using McpForUnity;
[McpForUnityTool("manage_example", AutoRegister = true, Group = "core")]
public static class ManageExample
{
public static object HandleCommand(JObject @params)
{
var p = new ToolParams(@params);
string action = p.RequireString("action");
Debug.Log($"Example tool received action: {action}");
return new SuccessResponse("Done.", new { echo = action });
}
}
Critical elements:
-
[McpForUnityTool]– Maps the C# handler to the Python tool name (must match exactly). -
HandleCommand– The entry point that receives JSON parameters from the Python side. -
ToolParams– Helper class for type-safe parameter extraction. -
SuccessResponse– Standardized response format for the MCP protocol.
Testing Your Changes
Every contribution requires tests for both the Python and C# implementations.
Python Tests
Add asynchronous pytest cases in Server/tests/:
# Server/tests/test_manage_example.py
import pytest
from services.tools.manage_example import manage_example
@pytest.mark.asyncio
async def test_example_action():
ctx = make_test_context()
resp = await manage_example(ctx, action="demo")
assert resp["status"] == "success"
assert resp["data"]["echo"] == "demo"
Unity Edit-Mode Tests
Add NUnit tests in the Unity test project:
// TestProjects/UnityMCPTests/Assets/Tests/ManageExampleTests.cs
using NUnit.Framework;
using UnityEngine;
using UnityEditor;
using McpForUnity.Editor.Tools;
public class ManageExampleTests
{
[Test]
public void HandlesCommand()
{
var result = ManageExample.HandleCommand(
JObject.FromObject(new { action = "ping" })
);
Assert.IsTrue(result is SuccessResponse);
}
}
Local Verification and Submission
Before pushing, verify your changes pass the full validation suite.
Run Python tests using uv:
cd Server
uv run pytest tests/ -v
Verify Unity compilation across supported versions:
tools/check-unity-versions.sh
This script ensures your C# changes compile against all supported Unity Editor versions.
When ready to submit:
- Push your branch:
git push origin feat/your-feature-name - Open a pull request on GitHub targeting the
betabranch - Complete the PR template checklist (verify branch origin, test coverage, documentation updates, and removal of dead code)
Summary
- Fork and branch off
beta(notmain) when starting work on CoplayDev/unity-mcp. - Maintain domain symmetry by implementing every tool in both
Server/src/services/tools/(Python) andMCPForUnity/Editor/Tools/(C#). - Use the correct decorators and attributes:
@mcp_for_unity_toolfor Python and[McpForUnityTool]for C#. - Test both layers: Python tests in
Server/tests/and Unity Edit-mode tests inTestProjects/UnityMCPTests/Assets/Tests/. - Validate locally using
uv run pytestandtools/check-unity-versions.shbefore submitting your PR.
Frequently Asked Questions
What branch should I target for pull requests?
Always target the beta branch. The beta branch serves as the active development line for the Unity MCP project, while main typically represents the latest stable release. The maintainers will merge beta into main when preparing releases.
Do I need to implement both Python and C# code for every contribution?
Yes. The architecture requires domain symmetry—every Python tool in Server/src/services/tools/ must have a corresponding C# implementation in MCPForUnity/Editor/Tools/. The Python layer handles MCP protocol communication, while the C# layer executes the actual Unity Editor operations.
How do I handle Unity version compatibility?
Place version-specific compatibility code in MCPForUnity/Runtime/Helpers/ using the existing shim pattern (e.g., Unity*Compat.cs files). The repository maintains support for multiple Unity versions, and the tools/check-unity-versions.sh script validates compilation across these versions.
What testing framework does the project use?
The Python codebase uses pytest with pytest-asyncio for asynchronous test support, located in Server/tests/. The Unity codebase uses NUnit for Edit-mode and Play-mode tests, located in TestProjects/UnityMCPTests/Assets/Tests/. Both test suites must pass before a pull request can be merged.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →