Skip to content

feat: Add search_console_logs tool for Unity log searching #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

Saqoosha
Copy link
Contributor

@Saqoosha Saqoosha commented Jun 16, 2025

Summary

  • Add comprehensive Unity console log search functionality as an MCP tool
  • Support keyword and regex pattern searching with advanced filtering options
  • Implement tool-based approach (preferred by Claude Code over resource-based)

Features Added

  • SearchConsoleLogsTool.cs: Unity-side implementation with IConsoleLogsService integration
  • searchConsoleLogsTool.ts: Node.js MCP server integration with Zod validation
  • Keyword search: Partial text matching with case sensitivity options
  • Regex search: Full regular expression pattern support
  • Log type filtering: Filter by error/warning/info log types
  • Stack trace control: Optional inclusion/exclusion for token optimization
  • Pagination: Offset and limit support for large result sets

Implementation Details

  • Integrated with existing ConsoleLogsService and ConsoleLogsServiceUnity6
  • Uses McpToolBase architecture for consistent tool behavior
  • Follows existing MCP Unity patterns and error handling
  • Removed previous resource-based implementation to avoid confusion
  • Added LogEntryModeFlags.cs with Unity's internal mode flag constants for better log type classification
  • Added Unity 6 internal API reference documentation for future maintainability
  • Added configuration option in Unity Editor settings to select console log service implementation
  • Improved error/warning classification accuracy in Unity 6 implementation

Testing

  • ✅ Keyword search: shader, texture, Player
  • ✅ Regex search: GameObject.*not found, ^\[MCP\].*
  • ✅ Log type filtering: error, warning, info
  • ✅ Case sensitivity: both sensitive and insensitive modes
  • ✅ Stack trace inclusion/exclusion
  • ✅ Pagination with offset and limit
  • ✅ Comprehensive search result statistics

Test plan

  • Test keyword search functionality
  • Test regex pattern matching
  • Test log type filtering (error/warning/info)
  • Test case sensitivity options
  • Test pagination with large log sets
  • Test stack trace inclusion/exclusion
  • Verify integration with both ConsoleLogsService implementations
  • Test error handling for invalid regex patterns
  • Verify tool appears correctly in MCP Inspector
  • Test Unity 6 enhanced implementation with different log types
  • Verify console log service selection UI works correctly

🤖 Generated with Claude Code

Created with Palmier

Summary by CodeRabbit

  • New Features

    • Added advanced search functionality for Unity console logs, allowing filtering by keyword or regular expression, log type, case sensitivity, and stack trace inclusion, with pagination support.
    • Introduced a user-selectable option in the MCP Unity Editor to choose between two console log service implementations: Event-Based and Unity 6 Enhanced (requires Unity 6+ and server restart).
    • Enhanced Unity 6+ support with a new log service using internal Unity APIs for more reliable log retrieval.
    • Provided a new tool for searching console logs directly from the MCP server.
  • Improvements

    • Added debug logging for socket message handling and unknown method warnings.
    • Updated internal error and log level handling for improved reliability.
  • Documentation

    • Added internal documentation detailing Unity 6 log entry structures and mode flags.
  • Chores

    • Updated ignore rules to exclude local Claude settings.
    • Added Unity meta files for new scripts and documentation.

Saqoosha and others added 6 commits June 7, 2025 18:01
…ementation

- Add ConsoleLogServiceType enum with EventBased and Unity6Enhanced options
- Implement ConsoleLogsServiceUnity6 using internal LogEntries API for better reliability
- Add command line argument support (-mcpConsoleLogService) for runtime switching
- Update McpUnityServer to dynamically select service based on settings and Unity version
- Add UI controls in McpUnityEditorWindow with warning dialogs for internal API usage
- Default to safe EventBased implementation, Unity6Enhanced only when explicitly selected
- Add clear startup logging to identify which implementation is active

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
…ered values

- Create LogEntryModeFlags.cs with Unity's internal mode flag constants
- Add support for observed mode values from debugging:
  * Compiler warnings: 266240 (0x41000)
  * Compiler errors: 272384 (0x42800)
  * Shader errors: 262212 (0x40044)
  * Runtime warnings: 8405504 (0x804200)
  * Runtime errors: 8405248 (0x804100)
- Update Unity6InternalAPIReference.md with complete documentation
- Add conditional debug logging for future mode value discovery
- Improve error/warning classification accuracy in Unity 6 implementation

This enables proper filtering of shader errors, compile errors, and runtime
exceptions that were previously misclassified as "Log" type.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Removed GetEffectiveConsoleLogService() method
- Console log service now only configurable via Unity Editor settings UI
- Simplified configuration as command-line args are not practical for Unity Hub users

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Keep file locally but stop tracking it in git

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Add SearchConsoleLogsTool.cs with keyword/regex search support
- Support case-sensitive/insensitive search with logType filtering
- Include pagination (offset/limit) and optional stack trace inclusion
- Implement both C# (Unity) and TypeScript (Node.js) components
- Register tool in McpUnityServer and Node.js MCP server
- Remove previous resource-based implementation in favor of tool-based approach
- Add comprehensive search capabilities:
  - Keyword search with partial matching
  - Regular expression pattern matching
  - Log type filtering (error/warning/info)
  - Configurable case sensitivity
  - Stack trace inclusion/exclusion for token optimization
  - Pagination support for large result sets

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Copy link
Contributor

coderabbitai bot commented Jun 16, 2025

📝 Walkthrough

Walkthrough

This update introduces advanced search functionality for Unity console logs, supporting keyword and regex filtering, log type selection, case sensitivity, and pagination. It adds a Unity 6-specific log service using internal APIs, a new log mode flag utility, UI for selecting the log service, and integrates the search tool into both the Unity and Node.js servers.

Changes

File(s) Change Summary
.gitignore Added .claude/settings.local.json to ignore Claude-specific settings.
Editor/Services/ConsoleLogsService.cs, Editor/Services/IConsoleLogsService.cs Added SearchLogsAsJson method to interface and implementation, enabling keyword/regex search, log type filtering, stack trace inclusion, case sensitivity, and pagination for console logs.
Editor/Services/ConsoleLogsServiceUnity6.cs, .meta New Unity 6-specific log service using internal Unity APIs via reflection; supports advanced log retrieval, search, pagination, type mapping, and error handling. Includes metadata file.
Editor/Services/LogEntryModeFlags.cs, .meta New utility class defining log mode flag constants and a method to map mode integers to log type strings, encapsulating Unity's internal log flag logic. Includes metadata file.
Editor/Services/Unity6InternalAPIReference.md, .meta Added internal documentation detailing Unity 6's internal LogEntry structure, mode flags, and analysis of observed values for log classification. Includes metadata file.
Editor/Tools/SearchConsoleLogsTool.cs, .meta New tool class for searching console logs via keyword or regex, supporting filters and pagination; delegates to the log service and formats JSON results. Includes metadata file.
Editor/UnityBridge/McpUnityEditorWindow.cs Added UI element to select the console log service implementation (EventBased or Unity6Enhanced), with tooltips and dialogs explaining choices and restart requirements.
Editor/UnityBridge/McpUnityServer.cs Refactored to use IConsoleLogsService for polymorphism; selects log service implementation based on user setting and Unity version; registers the new search tool and exposes resource names for debugging.
Editor/UnityBridge/McpUnitySettings.cs Added ConsoleLogServiceType enum and corresponding field to settings, allowing user selection of log service implementation.
Editor/UnityBridge/McpUnitySocketHandler.cs Added debug logging for resource/method resolution in the socket handler.
Server~/build/index.js, Server~/src/index.ts Registered the new search console logs tool in the MCP server initialization.
Server~/build/utils/errors.js, Server~/build/utils/logger.js Fixed enum initialization to ensure proper assignment in all runtime environments.

Sequence Diagram(s)

sequenceDiagram
    participant UI as MCP Unity Editor Window
    participant Settings as McpUnitySettings
    participant Server as McpUnityServer
    participant LogService as IConsoleLogsService (EventBased/Unity6Enhanced)
    participant Tool as SearchConsoleLogsTool

    UI->>Settings: User selects Console Log Service type
    UI->>Server: (On restart) InitializeServices()
    Server->>Settings: Read ConsoleLogService setting
    Server->>LogService: Instantiate correct implementation (EventBased or Unity6Enhanced)
    Server->>Tool: Register SearchConsoleLogsTool with LogService

    Note over UI,Tool: User requests log search via UI or socket

    UI->>Tool: Execute({keyword/regex, logType, ...})
    Tool->>LogService: SearchLogsAsJson(...)
    LogService-->>Tool: JSON results
    Tool-->>UI: JSON response (with summary)
Loading

Possibly related PRs

  • CoderGamester/mcp-unity#42: Adds pagination support to console log retrieval; related as both PRs enhance log service interfaces and JSON retrieval, but this PR adds search/filtering capabilities.

Suggested reviewers

  • CoderGamester

Poem

In the warren of logs, a bunny did peek,
Searching with regex, or keywords unique.
From Unity’s depths, new secrets arise,
With flags and pagination, no log ever hides.
Now hop through the console—
🐇 Enhanced and spry—
For every bug’s burrow,
This rabbit will try!

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Commit Unit Tests in branch feat/search-console-logs-tool
  • Post Copyable Unit Tests in Comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Saqoosha
Copy link
Contributor Author

Apology for Incorrect PR 🙏

I sincerely apologize for creating this pull request incorrectly. This PR contains code that was previously rejected and should not have been submitted to the upstream repository.

Issues with this PR:

  • Contains Unity 6 specific code that was not approved
  • Includes modifications that conflict with the main repository's direction
  • Was created without proper review of the changes included

I will close this PR immediately to avoid any confusion or merge conflicts.

Next Steps:

  • Will work on a clean, separate branch with only the search console logs feature
  • Will ensure no previously rejected code is included
  • Will follow proper contribution guidelines before creating any future PRs

Again, my sincere apologies for this oversight. Thank you for your understanding.

🤖 Generated with Claude Code

@Saqoosha Saqoosha closed this Jun 16, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (13)
.gitignore (1)

124-125: Ignore local Claude configuration.

Adding .claude/settings.local.json prevents committing personal Claude settings. Consider broadening this to ignore the entire .claude/ directory (e.g., /.claude/) to cover any additional files in that folder.

Editor/UnityBridge/McpUnitySocketHandler.cs (1)

77-84: Log level & verbosity

  1. You prefix the messages with [DEBUG] but log them through LogInfo / LogWarning.
    • Consider switching to a dedicated debug-level method (or extend McpLogger) to avoid polluting info logs in production.

  2. string.Join(", ", _server.GetResourceNames()) allocates on every unknown call. Probably fine, but if spam becomes an issue caching or conditional compilation might help.

Minor, no blocker.

Editor/UnityBridge/McpUnitySettings.cs (2)

12-19: Tooltip attributes on enum members are ignored by Unity

Tooltip works only on serialized fields, not on individual enum values. These attributes increase bundle size and developer expectations without any runtime/inspector effect.

-        [Tooltip("Event-based implementation (default, safe) - may occasionally miss logs")]
         EventBased,
-        
-        [Tooltip("Unity 6 enhanced implementation (experimental) - uses internal APIs for better reliability")]
         Unity6Enhanced

If you want per-item help you’ll need a custom PropertyDrawer.


52-54: Persisting a brand-new setting can break older check-outs

Existing projects that already have a McpUnitySettings.json won’t have ConsoleLogService stored.
JsonUtility.FromJsonOverwrite will silently leave the field at its default (EventBased) on load, but SaveSettings() is called in the ctor and immediately writes the file back – that means the first project open will mutate the file and create unnecessary churn in version control.

Consider deferring SaveSettings() until the user makes an explicit change, or add a version tag / migration path.

Editor/Services/ConsoleLogsService.cs (1)

274-279: Compile the regex for repeated use

Each search may hit hundreds of log entries; adding RegexOptions.Compiled (where supported) gives ~2-3× perf gain for medium-size result sets.

-    searchRegex = new Regex(regex, caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase);
+    var regexOptions = caseSensitive ? RegexOptions.Compiled
+                                     : RegexOptions.Compiled | RegexOptions.IgnoreCase;
+    searchRegex = new Regex(regex, regexOptions);
Editor/UnityBridge/McpUnityServer.cs (1)

269-284: Repeated fallback every domain reload

When Unity6Enhanced is selected in a pre-6 editor, we log a warning each reload but still keep the setting.
Couple this with the editor-window feedback above or automatically downgrade the enum here to avoid noisy logs.

No code sample – see previous comment in McpUnityEditorWindow.cs.

Editor/Services/Unity6InternalAPIReference.md (2)

8-10: Table should be surrounded by blank lines (MD058).

Insert a blank line before and after the table to satisfy markdown-lint and improve readability.

-| Field Name | Type | Description |
+ 
+| Field Name | Type | Description |- | callstackTextStartUTF16 | Int32 | UTF-16 character position where stack trace starts |
+

74-78: Missing language identifier for fenced code block (MD040).

Add text or csharp to the triple-backticks to enable proper syntax highlighting.

-```
+```text
Editor/Services/LogEntryModeFlags.cs (2)

24-31: ObservedRuntime constants are never used.*

Dead code increases maintenance cost and can confuse readers. Either remove the constants or extend GetLogTypeFromMode to make use of them.


10-23: Prefer an enum with [Flags] over raw int constants.

An enum improves type-safety and self-documentation:

[Flags]
public enum LogEntryMode
{
    Error = 1 << 0,
    Assert = 1 << 1,
    ...
}

This change is optional but aligns with C# best practices.

Editor/Services/ConsoleLogsServiceUnity6.cs (3)

78-83: Unused reflection fields.

_fileField and _lineField are fetched but never referenced, adding unnecessary reflection overhead. Remove them or integrate the data.


201-204: Synthetic timestamp is misleading.

DateTime.Now.AddSeconds(-(currentCount - i)) fabricates a time that has no relation to the real log time and may even produce future timestamps when logs are cleared. Either omit the timestamp or derive it from Unity’s LogEntry (if available).


320-346: Duplicate log-type inference logic.

DetermineLogTypeFromModeAndContent duplicates logic already in LogEntryModeFlags.GetLogTypeFromMode. Rely exclusively on the central helper to avoid divergence.

-// First try to determine from stack trace content …
-
-// Fallback to mode flags
-return GetLogTypeFromMode(mode);
+return LogEntryModeFlags.GetLogTypeFromMode(mode);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 219eccc and 5b2ebf4.

📒 Files selected for processing (19)
  • .gitignore (1 hunks)
  • Editor/Services/ConsoleLogsService.cs (2 hunks)
  • Editor/Services/ConsoleLogsServiceUnity6.cs (1 hunks)
  • Editor/Services/ConsoleLogsServiceUnity6.cs.meta (1 hunks)
  • Editor/Services/IConsoleLogsService.cs (1 hunks)
  • Editor/Services/LogEntryModeFlags.cs (1 hunks)
  • Editor/Services/LogEntryModeFlags.cs.meta (1 hunks)
  • Editor/Services/Unity6InternalAPIReference.md (1 hunks)
  • Editor/Services/Unity6InternalAPIReference.md.meta (1 hunks)
  • Editor/Tools/SearchConsoleLogsTool.cs (1 hunks)
  • Editor/Tools/SearchConsoleLogsTool.cs.meta (1 hunks)
  • Editor/UnityBridge/McpUnityEditorWindow.cs (1 hunks)
  • Editor/UnityBridge/McpUnityServer.cs (5 hunks)
  • Editor/UnityBridge/McpUnitySettings.cs (2 hunks)
  • Editor/UnityBridge/McpUnitySocketHandler.cs (1 hunks)
  • Server~/build/index.js (2 hunks)
  • Server~/build/utils/errors.js (1 hunks)
  • Server~/build/utils/logger.js (1 hunks)
  • Server~/src/index.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
Editor/Services/IConsoleLogsService.cs (1)
Server~/build/resources/getConsoleLogsResource.js (4)
  • logType (63-63)
  • includeStackTrace (70-70)
  • offset (67-67)
  • limit (68-68)
Editor/Services/LogEntryModeFlags.cs (1)
Editor/Services/ConsoleLogsServiceUnity6.cs (1)
  • GetLogTypeFromMode (349-353)
Editor/UnityBridge/McpUnityEditorWindow.cs (1)
Editor/UnityBridge/McpUnitySettings.cs (1)
  • SaveSettings (111-124)
🪛 markdownlint-cli2 (0.17.2)
Editor/Services/Unity6InternalAPIReference.md

8-8: Tables should be surrounded by blank lines
null

(MD058, blanks-around-tables)


74-74: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🔇 Additional comments (12)
Server~/build/utils/logger.js (1)

8-8: Explicit enum assignment for stability
Switching to LogLevel = LogLevel || (LogLevel = {}) ensures the enum variable is always initialized or reused before population, avoiding potential undefined behavior in various module loaders. This matches the pattern in errors.js.

Server~/build/utils/errors.js (1)

9-9: Align enum initialization pattern
The explicit assignment ErrorType = ErrorType || (ErrorType = {}) prevents uninitialized enum errors and keeps consistency with the LogLevel change in logger.js.

Editor/Services/ConsoleLogsServiceUnity6.cs.meta (1)

1-2: Add Unity asset metadata
The .meta file correctly specifies fileFormatVersion and a unique guid for the ConsoleLogsServiceUnity6 asset, enabling Unity to track and manage the script.

Editor/Tools/SearchConsoleLogsTool.cs.meta (1)

1-2: Add Unity asset metadata
The .meta file provides the required version and guid for the new SearchConsoleLogsTool asset, ensuring proper Unity Editor integration.

Editor/Services/Unity6InternalAPIReference.md.meta (1)

1-7: Add Unity asset metadata for API doc
This metadata file correctly configures fileFormatVersion, guid, and the TextScriptImporter settings, enabling Unity to import and track the internal API reference document.

Editor/Services/LogEntryModeFlags.cs.meta (1)

1-11: Meta-file looks good

Nothing to flag – the meta only registers the new script with Unity.

Server~/build/index.js (1)

23-24: Import + registration align with existing pattern

The added registerSearchConsoleLogsTool follows the same ordering and invocation style as the other tools, so the bootstrap sequence remains deterministic.

Also applies to: 52-53

Server~/src/index.ts (1)

23-24: ```shell
#!/bin/bash
set -e

echo "Listing contents of Server~/src/tools recursively:"
ls -R 'Server~/src/tools'


</details>
<details>
<summary>Editor/Services/IConsoleLogsService.cs (1)</summary>

`45-57`: ```shell
#!/bin/bash
# Find SearchLogsAsJson signature and its documentation
rg "SearchLogsAsJson" -n Editor/Services/IConsoleLogsService.cs
```)

</details>
<details>
<summary>Editor/Tools/SearchConsoleLogsTool.cs (1)</summary>

`50-71`: **Looks solid – good defensive parameter handling**

Null-safe extraction, sensible min/max for `offset`/`limit`, and clean result shaping.

</details>
<details>
<summary>Editor/UnityBridge/McpUnityServer.cs (1)</summary>

`219-221`: **Null-check `_consoleLogsService` before tool registration**

If `InitializeServices()` fails for any reason (e.g. reflection error inside `ConsoleLogsServiceUnity6`) `_consoleLogsService` could be `null`, and the constructor of `SearchConsoleLogsTool` would throw.

```diff
-SearchConsoleLogsTool searchConsoleLogsTool = new SearchConsoleLogsTool(_consoleLogsService);
-_tools.Add(searchConsoleLogsTool.Name, searchConsoleLogsTool);
+if (_consoleLogsService != null)
+{
+    var searchConsoleLogsTool = new SearchConsoleLogsTool(_consoleLogsService);
+    _tools.Add(searchConsoleLogsTool.Name, searchConsoleLogsTool);
+}
+else
+{
+    McpLogger.LogError("[MCP Unity] Console log service unavailable – search_console_logs tool not registered.");
+}
Editor/Services/LogEntryModeFlags.cs (1)

50-58: Return value should distinguish unknown types.

Falling back to "Log" hides genuinely unknown modes. Returning "Unknown" (or throwing) will surface mis-classifications early.

-            return "Log"; // Default to Log instead of Unknown
+            return "Unknown";

Comment on lines +146 to +166
// Console log service selection
ConsoleLogServiceType newConsoleLogService = (ConsoleLogServiceType)EditorGUILayout.EnumPopup(
new GUIContent("Console Log Service", "Select console log service implementation. EventBased is safe but may miss some logs. Unity6Enhanced uses internal APIs for better reliability but requires Unity 6+. Server restart required when changed."),
settings.ConsoleLogService);
if (newConsoleLogService != settings.ConsoleLogService)
{
settings.ConsoleLogService = newConsoleLogService;
settings.SaveSettings();

// Show warning for Unity6Enhanced
if (newConsoleLogService == ConsoleLogServiceType.Unity6Enhanced)
{
#if UNITY_6000_0_OR_NEWER
EditorUtility.DisplayDialog("Console Log Service Changed",
"Unity 6 enhanced console log service selected. This uses internal Unity APIs for better reliability but may break in future Unity versions.\n\nRestart the MCP server for changes to take effect.", "OK");
#else
EditorUtility.DisplayDialog("Console Log Service Warning",
$"Unity 6 enhanced console log service selected but current Unity version is {Application.unityVersion}. The service will fall back to event-based implementation.\n\nRestart the MCP server for changes to take effect.", "OK");
#endif
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Storing an unsupported option can confuse users

On pre-Unity-6 editors the user can still select Unity6Enhanced.
You warn that it “will fall back”, but the value is nevertheless persisted, so every project reopen shows the (inoperative) selection again and re-triggers the warning.

                 settings.ConsoleLogService = newConsoleLogService;
                 settings.SaveSettings();
-
+#if !UNITY_6000_0_OR_NEWER
+                if (newConsoleLogService == ConsoleLogServiceType.Unity6Enhanced)
+                {
+                    // Immediately revert so the inspector reflects the real runtime state
+                    settings.ConsoleLogService = ConsoleLogServiceType.EventBased;
+                    settings.SaveSettings();
+                }
+#endif

Alternatively disable the enum value via EditorGUI.BeginDisabledGroup when !UNITY_6000_0_OR_NEWER.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Console log service selection
ConsoleLogServiceType newConsoleLogService = (ConsoleLogServiceType)EditorGUILayout.EnumPopup(
new GUIContent("Console Log Service", "Select console log service implementation. EventBased is safe but may miss some logs. Unity6Enhanced uses internal APIs for better reliability but requires Unity 6+. Server restart required when changed."),
settings.ConsoleLogService);
if (newConsoleLogService != settings.ConsoleLogService)
{
settings.ConsoleLogService = newConsoleLogService;
settings.SaveSettings();
// Show warning for Unity6Enhanced
if (newConsoleLogService == ConsoleLogServiceType.Unity6Enhanced)
{
#if UNITY_6000_0_OR_NEWER
EditorUtility.DisplayDialog("Console Log Service Changed",
"Unity 6 enhanced console log service selected. This uses internal Unity APIs for better reliability but may break in future Unity versions.\n\nRestart the MCP server for changes to take effect.", "OK");
#else
EditorUtility.DisplayDialog("Console Log Service Warning",
$"Unity 6 enhanced console log service selected but current Unity version is {Application.unityVersion}. The service will fall back to event-based implementation.\n\nRestart the MCP server for changes to take effect.", "OK");
#endif
}
}
// Console log service selection
ConsoleLogServiceType newConsoleLogService = (ConsoleLogServiceType)EditorGUILayout.EnumPopup(
new GUIContent("Console Log Service", "Select console log service implementation. EventBased is safe but may miss some logs. Unity6Enhanced uses internal APIs for better reliability but requires Unity 6+. Server restart required when changed."),
settings.ConsoleLogService);
if (newConsoleLogService != settings.ConsoleLogService)
{
settings.ConsoleLogService = newConsoleLogService;
settings.SaveSettings();
#if !UNITY_6000_0_OR_NEWER
if (newConsoleLogService == ConsoleLogServiceType.Unity6Enhanced)
{
// Immediately revert so the inspector reflects the real runtime state
settings.ConsoleLogService = ConsoleLogServiceType.EventBased;
settings.SaveSettings();
}
#endif
// Show warning for Unity6Enhanced
if (newConsoleLogService == ConsoleLogServiceType.Unity6Enhanced)
{
#if UNITY_6000_0_OR_NEWER
EditorUtility.DisplayDialog("Console Log Service Changed",
"Unity 6 enhanced console log service selected. This uses internal Unity APIs for better reliability but may break in future Unity versions.\n\nRestart the MCP server for changes to take effect.", "OK");
#else
EditorUtility.DisplayDialog("Console Log Service Warning",
$"Unity 6 enhanced console log service selected but current Unity version is {Application.unityVersion}. The service will fall back to event-based implementation.\n\nRestart the MCP server for changes to take effect.", "OK");
#endif
}
}
🤖 Prompt for AI Agents
In Editor/UnityBridge/McpUnityEditorWindow.cs around lines 146 to 166, the code
allows selecting the Unity6Enhanced console log service on Unity versions older
than 6, which causes the unsupported option to be saved and repeatedly trigger
warnings. To fix this, disable the Unity6Enhanced enum option in the EnumPopup
using EditorGUI.BeginDisabledGroup when UNITY_6000_0_OR_NEWER is not defined,
preventing users from selecting and saving an unsupported option.

Comment on lines +313 to +384
lock (_logEntries)
{
totalCount = _logEntries.Count;

// Search through logs (newest first)
for (int i = _logEntries.Count - 1; i >= 0; i--)
{
var entry = _logEntries[i];

// Skip if filtering by log type and entry doesn't match
if (unityLogTypes != null && !unityLogTypes.Contains(entry.Type.ToString()))
continue;

filteredCount++;

// Check if entry matches search criteria
bool matches = true;
if (hasSearchCriteria)
{
matches = false;

// Search in message
if (searchRegex != null)
{
matches = searchRegex.IsMatch(entry.Message);
if (!matches && includeStackTrace && !string.IsNullOrEmpty(entry.StackTrace))
{
matches = searchRegex.IsMatch(entry.StackTrace);
}
}
else if (!string.IsNullOrEmpty(searchKeyword))
{
string messageToSearch = caseSensitive ? entry.Message : entry.Message.ToLower();
matches = messageToSearch.Contains(searchKeyword);

if (!matches && includeStackTrace && !string.IsNullOrEmpty(entry.StackTrace))
{
string stackTraceToSearch = caseSensitive ? entry.StackTrace : entry.StackTrace.ToLower();
matches = stackTraceToSearch.Contains(searchKeyword);
}
}
}

if (!matches) continue;

matchedCount++;

// Check if we're in the offset range and haven't reached the limit yet
if (currentIndex >= offset && logsArray.Count < limit)
{
var logObject = new JObject
{
["message"] = entry.Message,
["type"] = entry.Type.ToString(),
["timestamp"] = entry.Timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff")
};

// Only include stack trace if requested
if (includeStackTrace)
{
logObject["stackTrace"] = entry.StackTrace;
}

logsArray.Add(logObject);
}

currentIndex++;

// Early exit if we've collected enough logs
if (currentIndex >= offset + limit) break;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid holding the _logEntries lock while running heavy pattern matching

Regex.IsMatch, ToLower(), etc. inside the lock can freeze the UI thread while new editor logs are waiting to be appended.

-    lock (_logEntries)
-    {
-        totalCount = _logEntries.Count;
-        // iterate, regex-match, build result …
-    }
+    List<LogEntry> snapshot;
+    lock (_logEntries)
+    {
+        totalCount = _logEntries.Count;
+        snapshot   = _logEntries.ToList();   // copy once
+    }
+
+    // search over the *snapshot* outside the lock
+    for (int i = snapshot.Count - 1; i >= 0; i--)
+    {
+        var entry = snapshot[i];
+
+    }

This keeps append latency O(µs) even for expensive searches.

🤖 Prompt for AI Agents
In Editor/Services/ConsoleLogsService.cs between lines 313 and 384, the code
holds the _logEntries lock while performing expensive operations like
Regex.IsMatch and ToLower, which can block the UI thread. To fix this, refactor
the code to first copy the relevant _logEntries data into a separate list or
array inside the lock, then release the lock before performing any pattern
matching or string manipulation. This ensures the lock is held only briefly for
copying, preventing UI freezes during heavy searches.

Comment on lines +37 to +41
// Check for observed compiler/shader message patterns first
if (mode == ObservedCompilerError) return "Error";
if (mode == ObservedCompilerWarning) return "Warning";
if (mode == ObservedShaderError) return "Error";

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Exact equality check may miss messages that include undocumented high bits.

mode == ObservedCompilerError requires an exact match; Unity often ORs extra bits. Consider masking instead:

-if (mode == ObservedCompilerError) return "Error";
+if ((mode & ObservedCompilerError) == ObservedCompilerError) return "Error";

This makes the detection resilient to future Unity changes.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Check for observed compiler/shader message patterns first
if (mode == ObservedCompilerError) return "Error";
if (mode == ObservedCompilerWarning) return "Warning";
if (mode == ObservedShaderError) return "Error";
// Check for observed compiler/shader message patterns first
if ((mode & ObservedCompilerError) == ObservedCompilerError) return "Error";
if (mode == ObservedCompilerWarning) return "Warning";
if (mode == ObservedShaderError) return "Error";
🤖 Prompt for AI Agents
In Editor/Services/LogEntryModeFlags.cs around lines 37 to 41, the code uses
exact equality checks for mode against ObservedCompilerError and similar
constants, which can fail if Unity ORs extra bits. To fix this, replace the
equality checks with bitwise masking to compare only the relevant bits, ensuring
the detection works even if additional bits are set in mode.

Comment on lines +152 to +226
// Start getting entries
_startGettingEntriesMethod?.Invoke(null, null);

int currentCount = (int)_getCountMethod.Invoke(null, null);
var collectedLogs = new List<JObject>();

// Iterate through all logs (newest first)
for (int i = currentCount - 1; i >= 0; i--)
{
// Create LogEntry instance
var logEntry = Activator.CreateInstance(_logEntryType);

// GetEntryInternal(int row, LogEntry outputEntry)
bool success = (bool)_getEntryInternalMethod.Invoke(null, new object[] { i, logEntry });

if (!success) continue;

// Extract fields (see Unity6InternalAPIReference.md for field details)
string fullMessage = _messageField?.GetValue(logEntry) as string ?? "";
string file = _fileField?.GetValue(logEntry) as string ?? "";
int line = _lineField?.GetValue(logEntry) as int? ?? 0;
int mode = _modeField?.GetValue(logEntry) as int? ?? 0;
int callstackStartUTF8 = _callstackTextStartUTF8Field?.GetValue(logEntry) as int? ?? 0;
int callstackStartUTF16 = _callstackTextStartUTF16Field?.GetValue(logEntry) as int? ?? 0;

// Debug: Write mode values to file for analysis (disabled by default)
#if MCP_UNITY_DEBUG_MODE_VALUES
if (fullMessage.Contains("error") || fullMessage.Contains("Error") ||
fullMessage.Contains("warning") || fullMessage.Contains("Warning") ||
fullMessage.Contains("failed") || fullMessage.Contains("Failed") ||
fullMessage.Contains("exception") || fullMessage.Contains("Exception"))
{
WriteDebugInfo(fullMessage, mode);
}
#endif

// Parse message and stack trace using Unity's internal callstack position (prefer UTF-16)
var (actualMessage, stackTrace) = ParseMessageAndStackTrace(fullMessage, callstackStartUTF16, callstackStartUTF8);

// Determine log type from mode and stack trace
string entryType = DetermineLogTypeFromModeAndContent(mode, stackTrace);

// Skip if filtering and doesn't match
if (filter && !unityLogTypes.Contains(entryType))
continue;

// Create log object
var logObject = new JObject
{
["message"] = actualMessage,
["type"] = entryType,
["timestamp"] = DateTime.Now.AddSeconds(-(currentCount - i)).ToString("yyyy-MM-dd HH:mm:ss.fff")
};

// Include stack trace if requested
if (includeStackTrace && !string.IsNullOrEmpty(stackTrace))
{
logObject["stackTrace"] = stackTrace;
}

collectedLogs.Add(logObject);
}

// End getting entries
_endGettingEntriesMethod?.Invoke(null, null);

// Apply pagination
var paginatedLogs = collectedLogs
.Skip(offset)
.Take(limit)
.ToList();

foreach (var log in paginatedLogs)
{
logsArray.Add(log);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Inefficient pagination – all logs are materialised before slicing.

collectedLogs stores every console entry, which can be tens of thousands, just to Skip(offset).Take(limit) later. Build the result incrementally and stop once offset + limit have been satisfied to reduce memory and CPU usage.

🤖 Prompt for AI Agents
In Editor/Services/ConsoleLogsServiceUnity6.cs between lines 152 and 226, the
code collects all log entries into a list before applying pagination with Skip
and Take, which is inefficient for large log volumes. Modify the loop to track
how many entries have been processed and only add logs to the result after
reaching the offset, stopping the iteration once offset plus limit entries have
been collected. This incremental approach avoids storing all logs in memory and
reduces CPU usage by terminating early.

Comment on lines +419 to +433
// Get total count using reflection
try
{
totalCount = (int)_getCountMethod.Invoke(null, null);
}
catch (Exception ex)
{
Debug.LogError($"[MCP Unity] Error getting log count: {ex.Message}");
return new JObject
{
["logs"] = logsArray,
["error"] = "Failed to access Unity console logs",
["success"] = false
};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Null-reference risk when reflection is unavailable.

SearchLogsAsJson calls _getCountMethod.Invoke without verifying that reflection succeeded. If InitializeReflection failed, this will throw and crash the tool.

Add the same availability guard used in GetLogsAsJson:

+if (_logEntriesType == null || _getCountMethod == null || _getEntryInternalMethod == null)
+{
+    return new JObject
+    {
+        ["logs"] = new JArray(),
+        ["message"] = "LogEntries API not available",
+        ["success"] = false
+    };
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Get total count using reflection
try
{
totalCount = (int)_getCountMethod.Invoke(null, null);
}
catch (Exception ex)
{
Debug.LogError($"[MCP Unity] Error getting log count: {ex.Message}");
return new JObject
{
["logs"] = logsArray,
["error"] = "Failed to access Unity console logs",
["success"] = false
};
}
// Guard against missing reflection APIs
if (_logEntriesType == null || _getCountMethod == null || _getEntryInternalMethod == null)
{
return new JObject
{
["logs"] = new JArray(),
["message"] = "LogEntries API not available",
["success"] = false
};
}
// Get total count using reflection
try
{
totalCount = (int)_getCountMethod.Invoke(null, null);
}
catch (Exception ex)
{
Debug.LogError($"[MCP Unity] Error getting log count: {ex.Message}");
return new JObject
{
["logs"] = logsArray,
["error"] = "Failed to access Unity console logs",
["success"] = false
};
}
🤖 Prompt for AI Agents
In Editor/Services/ConsoleLogsServiceUnity6.cs around lines 419 to 433, the code
calls _getCountMethod.Invoke without checking if _getCountMethod is null,
risking a null-reference exception if reflection initialization failed. Add a
null check for _getCountMethod before invoking it, similar to the guard used in
GetLogsAsJson, and handle the case where it is null by returning an error
JObject to prevent crashes.

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