Debugging and Troubleshooting
Relevant source files
The following files were used as context for generating this wiki page:
- Packages/src/Editor/UI/McpCommunicationLog.cs
- Packages/src/Editor/Core/Logging/VibeLogger.cs
- Assets/Util/test_port_blocker.py
- Packages/src/Editor/Utils/McpPortValidator.cs
- Packages/src/TypeScriptServer~/README.md
- Packages/src/Cli~/src/tests/cli-e2e.test.ts
- Packages/src/Editor/UI/McpEditorWindow.cs
- Packages/src/Editor/Api/McpTools/ExecuteDynamicCode/ExecuteDynamicCodeTool.cs
- Packages/src/TOOL_REFERENCE.md
- README.md
- SECURITY.md
The uLoopMCP project provides a comprehensive suite of tools and mechanisms for debugging and troubleshooting interactions between LLM clients (like Cursor), the TypeScript MCP server, and the Unity Editor. These facilities are designed to diagnose connection issues, inspect data flow, analyze tool execution, and handle errors gracefully. The system includes UI diagnostics within the Unity Editor, a powerful command-line interface (CLI) with debug scripts, structured logging, and detailed error reporting in tool responses.
This guide covers the various debugging features, from high-level UI indicators to low-level command-line tests and structured logging, enabling both developers and AI agents to effectively identify and resolve issues within the autonomous development loop. For detailed specifications of tool parameters and error responses, refer to the Tool Reference.
Unity Editor UI Diagnostics
The primary interface for debugging within the Unity Editor is the Window > uLoopMCP editor window. This window provides real-time feedback on the state of the MCP server and its connections.
Sources: Packages/src/Editor/UI/McpEditorWindow.cs
Server Status and Port Validation
The McpEditorWindow displays the server's current status ("Running" or "Stopped"), the port it is using, and provides controls to start or stop it. A critical feature is the built-in port validation, which checks for issues before the server starts.
The validation logic performs two main checks:
- Port Validity: Ensures the port number is 1024 or higher and not a reserved system port, using
McpPortValidator.ValidatePort. - Port Availability: Checks if the port is already in use by another process, using
NetworkUtility.IsPortInUse.
If a port is invalid or in use, a warning message is displayed in the UI, preventing the user from starting the server with a problematic configuration.
The following diagram illustrates the port validation flow within the McpEditorWindow.
This diagram shows how the UI uses validator utilities to provide immediate feedback on port configuration.
Sources: Packages/src/Editor/UI/McpEditorWindow.cs:228-246, Packages/src/Editor/Utils/McpPortValidator.cs
You can test the "Port in use" warning by running a simple Python script to block a port.
# Assets/Util/test_port_blocker.py
import socket
import time
import argparse
def block_port(port):
"""Blocks a specified port to test port-in-use detection."""
print(f"Attempting to block port {port}...")
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('127.0.0.1', port))
s.listen()
print(f"Port {port} is now blocked. Press Ctrl+C to release.")
while True:
time.sleep(1)
except OSError as e:
print(f"Error: Could not block port {port}. It might already be in use. Details: {e}")
except KeyboardInterrupt:
print(f"\nReleasing port {port}.")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Block a TCP port for testing.")
parser.add_argument("port", type=int, help="The port number to block.")
args = parser.parse_args()
block_port(args.port)
Sources: Assets/Util/test_port_blocker.py
Connected Clients and Communication Log
The "Connected Tools" section of the McpEditorWindow lists all clients currently connected to the Unity MCP server. This is useful for verifying that your LLM tool (e.g., Cursor) has successfully established a connection. The window also shows a "Reconnecting..." state UI after a domain reload to indicate that it's waiting for clients to reconnect.
For more granular debugging, the project includes a McpCommunicationLog (though its UI integration is not detailed in the provided files), which is designed to log raw JSON-RPC messages between the server and clients.
Sources: Packages/src/Editor/UI/McpEditorWindow.cs:283-306, Packages/src/Editor/UI/McpCommunicationLog.cs
TypeScript Server and CLI
The TypeScript server component includes a rich set of debug scripts and a command-line interface (uloop) for testing and diagnostics without needing a full LLM client.
Debug Scripts
The TypeScriptServer~ package provides several npm scripts for debugging different functionalities. These scripts can be run from the Packages/src/TypeScriptServer~ directory.
| Script | Description |
|---|---|
npm run debug:compile | Executes a compilation check against the Unity project. |
npm run debug:logs | Fetches and displays logs from the Unity Console. |
npm run debug:connection | Runs a comprehensive connection test, including ping, compile, and logs. |
npm run debug:all-logs | Retrieves a large number of logs and displays statistics. |
These scripts are useful for isolating issues between the TypeScript server and the Unity Editor. For example, if npm run debug:connection fails, the problem likely lies in the TCP connection or the Unity-side server, not the LLM client.
Sources: Packages/src/TypeScriptServer~/README.md:128-179
Direct Communication Test
For low-level debugging, you can send JSON-RPC commands directly to the Unity MCP server using tools like netcat (nc). This bypasses the TypeScript server entirely and is the most direct way to test a specific tool's functionality on the Unity side. The Unity MCP server must be running.
The following sequence diagram shows the flow of a direct netcat call.
Example Commands:
- Run Compilation:
echo '{"jsonrpc":"2.0","id":1,"method":"compile","params":{"forceRecompile":false}}' | nc localhost 7400 - Get Logs:
echo '{"jsonrpc":"2.0","id":1,"method":"getLogs","params":{"logType":"All","maxCount":10}}' | nc localhost 7400
Sources: Packages/src/TypeScriptServer~/README.md:105-121
CLI End-to-End Tests
The project includes a suite of end-to-end (e2e) tests for the uloop CLI, which serve as excellent examples of how to use the CLI for diagnostics. A key feature of these tests is a retry mechanism to handle Unity's domain reloads, which can temporarily interrupt the connection.
The runCliWithRetry function demonstrates this robust approach: it attempts to run a CLI command, and if it detects a domain reload error, it waits and retries up to a maximum number of attempts.
// Packages/src/Cli~/src/__tests__/cli-e2e.test.ts
function isDomainReloadError(output: string): boolean {
return output.includes('Unity is reloading') || output.includes('Domain Reload');
}
function runCliWithRetry(args: string): { stdout: string; stderr: string; exitCode: number } {
for (let attempt = 0; attempt < DOMAIN_RELOAD_MAX_RETRIES; attempt++) {
const result = runCli(args);
const output = result.stderr || result.stdout;
if (result.exitCode === 0 || !isDomainReloadError(output)) {
return result;
}
// Domain Reload in progress, wait and retry
if (attempt < DOMAIN_RELOAD_MAX_RETRIES - 1) {
sleepSync(DOMAIN_RELOAD_RETRY_MS);
}
}
return runCli(args);
}
This logic is crucial for building reliable automation scripts that interact with the Unity Editor.
Sources: Packages/src/Cli~/src/tests/cli-e2e.test.ts:39-65
Logging and Error Handling
uLoopMCP employs structured logging and detailed error responses to facilitate debugging.
Structured Logging with VibeLogger
VibeLogger is a logging utility used on the Unity side to produce structured, machine-readable logs. This is particularly useful for monitoring the behavior of tools invoked by an AI. Logs include an event_name, a human-readable message, a JSON payload, and a correlationId to trace a request through the system.
Here is an example of how VibeLogger is used in the ExecuteDynamicCodeTool:
// Packages/src/Editor/Api/McpTools/ExecuteDynamicCode/ExecuteDynamicCodeTool.cs:64-79
VibeLogger.LogInfo(
"execute_dynamic_code_start",
"Dynamic code execution started (return optional)",
new {
correlationId,
codeLength = parameters.Code?.Length ?? 0,
compileOnly = parameters.CompileOnly,
parametersCount = parameters.Parameters?.Count ?? 0,
securityLevel = _currentSecurityLevel.ToString()
},
correlationId,
"Dynamic code execution request received (return is optional)",
"Monitor execution flow and performance"
);
Sources: Packages/src/Editor/Core/Logging/VibeLogger.cs, Packages/src/Editor/Api/McpTools/ExecuteDynamicCode/ExecuteDynamicCodeTool.cs:64-79
execute-dynamic-code Error Handling
The execute-dynamic-code tool has a sophisticated error handling pipeline. When code execution fails, it doesn't just return a raw compiler error. Instead, it processes the error to provide a more user-friendly and actionable response.
The flow is as follows:
- The
IDynamicCodeExecutorattempts to compile and run the code. - If an error occurs, the
ExecutionResultis passed to aUserFriendlyErrorConverter. - This converter analyzes the error and generates an
ExecuteDynamicCodeResponsecontaining:- A friendly error message.
- An explanation of the likely problem.
- Suggested solutions and examples.
- A structured list of
CompilationErrorswith line numbers, error codes, and context.
The following diagram illustrates this error-handling sequence.
This process transforms a cryptic compiler error like CS0103 into a helpful message like "Add 'using UnityEngine;' at the top or use fully-qualified name (e.g., UnityEngine.Mathf)."
Sources: Packages/src/Editor/Api/McpTools/ExecuteDynamicCode/ExecuteDynamicCodeTool.cs:176-291
Troubleshooting Common Issues
Connection Problems
- Unity Connection Errors:
- Ensure the MCP server is running in Unity (
Window > uLoopMCP > Start Server). - Check that the port displayed in the uLoopMCP window is not blocked by a firewall and is not in use by another application.
- Use
npm run debug:connectionfrom theTypeScriptServer~directory to test the connection.
- Ensure the MCP server is running in Unity (
- Known Bug in Cursor: Cursor may fail to connect with a timeout after initial setup or a port change. The workaround is to toggle the uLoopMCP server off and then on again in Cursor's "Tools & MCP" settings. If that fails, restart Cursor.
Sources: Packages/src/TypeScriptServer~/README.md:250-254, README.md:200-205
Tool Execution Failures
- Security Restrictions: Many powerful tools like
run-tests,execute-menu-item, andexecute-dynamic-codeare disabled by default for security. To enable them, go toWindow > uLoopMCP, expand the "Security Settings" section, and toggle the corresponding permissions. - Dynamic Code Execution Levels: The
execute-dynamic-codetool has three security levels. If your code fails with a security error, check the current level in the "Security Settings". "Level 1 (Restricted)" is recommended, as it blocks dangerous operations like file I/O and networking.
Sources: README.md:160-179, SECURITY.md:26-29
- Compilation Errors: When a tool like
compileorexecute-dynamic-codefails, check theErrors,CompilationErrors, orDiagnosticsfields in the JSON response. These provide structured information about what went wrong, including file paths, line numbers, and error messages.