-
Notifications
You must be signed in to change notification settings - Fork 541
Added optional telemetry #264
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
Merged
Merged
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
e5039c8
added optional telemetry
justinpbarnett 8303ed1
Merge remote-tracking branch 'origin/main' into feat/telemetry
justinpbarnett 99beca7
endpoint adjustment
justinpbarnett 81dcd69
Merge commit '3e83f993bfe632034bf7302d4319e3cd16353eb8' into feat/tel…
dsarno f127024
telemetry: enable tool_execution across tools via strict, async-aware…
dsarno bbe4b07
feat: improve telemetry and parameter validation
dsarno 979757e
tests green: align SDK outputs + harden inputs\n\n- find_in_file: sta…
dsarno 7f0527f
chore: apply CodeRabbit suggestions
dsarno f6a5568
telemetry: prefer config with env override; validate scheme; robust l…
dsarno 2abca24
telemetry: pluggable Unity sender; add MCP_DISABLE_TELEMETRY; server …
dsarno 2e907f1
tests: disable telemetry during pytest via conftest; lock milestone s…
dsarno ba45051
fix she descrip
dsarno bd55a56
MCP server: hardened startup + telemetry queue
dsarno 1e00374
telemetry: bounded queue + single worker; INFO-level send logs; endpo…
dsarno c1bde80
telemetry: main-thread routing + timeout for manage_scene; stderr + r…
dsarno 46df725
attempted ManageScene debugging for hang
dsarno 397ba32
telemetry: fire-and-forget queue; remove context propagation; reduce …
dsarno 2fd74f5
manage_scene: tolerant params + optional buildIndex; add writer IO lo…
dsarno 89714d0
telemetry: record sub_action for tool executions; decorator extracts …
dsarno 9f7308b
mcp-unity: telemetry fire-and-forget; safer sender reg; defer startup…
dsarno 9b5488d
telemetry_decorator: guard record_tool_usage and milestone emits (syn…
dsarno 33979d3
telemetry: use Cloud Run default, reject localhost overrides, add sta…
dsarno 283597d
fix(startup): capture exception message before deferred telemetry lambda
dsarno File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| # Unity MCP Telemetry | ||
|
|
||
| Unity MCP includes privacy-focused, anonymous telemetry to help us improve the product. This document explains what data is collected, how to opt out, and our privacy practices. | ||
|
|
||
| ## 🔒 Privacy First | ||
|
|
||
| - **Anonymous**: We use randomly generated UUIDs - no personal information | ||
| - **Non-blocking**: Telemetry never interferes with your Unity workflow | ||
| - **Easy opt-out**: Simple environment variable or Unity Editor setting | ||
| - **Transparent**: All collected data types are documented here | ||
|
|
||
| ## 📊 What We Collect | ||
|
|
||
| ### Usage Analytics | ||
| - **Tool Usage**: Which MCP tools you use (manage_script, manage_scene, etc.) | ||
| - **Performance**: Execution times and success/failure rates | ||
| - **System Info**: Unity version, platform (Windows/Mac/Linux), MCP version | ||
| - **Milestones**: First-time usage events (first script creation, first tool use, etc.) | ||
|
|
||
| ### Technical Diagnostics | ||
| - **Connection Events**: Bridge startup/connection success/failures | ||
| - **Error Reports**: Anonymized error messages (truncated to 200 chars) | ||
| - **Server Health**: Startup time, connection latency | ||
|
|
||
| ### What We **DON'T** Collect | ||
| - ❌ Your code or script contents | ||
| - ❌ Project names, file names, or paths | ||
| - ❌ Personal information or identifiers | ||
| - ❌ Sensitive project data | ||
| - ❌ IP addresses (beyond what's needed for HTTP requests) | ||
|
|
||
| ## 🚫 How to Opt Out | ||
|
|
||
| ### Method 1: Environment Variable (Recommended) | ||
| Set any of these environment variables to `true`: | ||
|
|
||
| ```bash | ||
| # Disable all telemetry | ||
| export DISABLE_TELEMETRY=true | ||
|
|
||
| # Unity MCP specific | ||
| export UNITY_MCP_DISABLE_TELEMETRY=true | ||
|
|
||
| # MCP protocol wide | ||
| export MCP_DISABLE_TELEMETRY=true | ||
| ``` | ||
|
|
||
| ### Method 2: Unity Editor (Coming Soon) | ||
| In Unity Editor: `Window > MCP for Unity > Settings > Disable Telemetry` | ||
|
|
||
| ### Method 3: Manual Config | ||
| Add to your MCP client config: | ||
| ```json | ||
| { | ||
| "env": { | ||
| "DISABLE_TELEMETRY": "true" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## 🔧 Technical Implementation | ||
|
|
||
| ### Architecture | ||
| - **Python Server**: Core telemetry collection and transmission | ||
| - **Unity Bridge**: Local event collection from Unity Editor | ||
| - **Anonymous UUIDs**: Generated per-installation for aggregate analytics | ||
| - **Thread-safe**: Non-blocking background transmission | ||
| - **Fail-safe**: Errors never interrupt your workflow | ||
|
|
||
| ### Data Storage | ||
| Telemetry data is stored locally in: | ||
| - **Windows**: `%APPDATA%\UnityMCP\` | ||
| - **macOS**: `~/Library/Application Support/UnityMCP/` | ||
| - **Linux**: `~/.local/share/UnityMCP/` | ||
|
|
||
| Files created: | ||
| - `customer_uuid.txt`: Anonymous identifier | ||
| - `milestones.json`: One-time events tracker | ||
|
|
||
| ### Data Transmission | ||
| - **Endpoint**: `https://telemetry.coplay.dev/unity-mcp/anonymous` | ||
| - **Method**: HTTPS POST with JSON payload | ||
| - **Retry**: Background thread with graceful failure | ||
| - **Timeout**: 10 second timeout, no retries on failure | ||
|
|
||
| ## 📈 How We Use This Data | ||
|
|
||
| ### Product Improvement | ||
| - **Feature Usage**: Understand which tools are most/least used | ||
| - **Performance**: Identify slow operations to optimize | ||
| - **Reliability**: Track error rates and connection issues | ||
| - **Compatibility**: Ensure Unity version compatibility | ||
|
|
||
| ### Development Priorities | ||
| - **Roadmap**: Focus development on most-used features | ||
| - **Bug Fixes**: Prioritize fixes based on error frequency | ||
| - **Platform Support**: Allocate resources based on platform usage | ||
| - **Documentation**: Improve docs for commonly problematic areas | ||
|
|
||
| ### What We Don't Do | ||
| - ❌ Sell data to third parties | ||
| - ❌ Use data for advertising/marketing | ||
| - ❌ Track individual developers | ||
| - ❌ Store sensitive project information | ||
|
|
||
| ## 🛠️ For Developers | ||
|
|
||
| ### Testing Telemetry | ||
| ```bash | ||
| cd UnityMcpBridge/UnityMcpServer~/src | ||
| python test_telemetry.py | ||
| ``` | ||
|
|
||
| ### Custom Telemetry Events | ||
| ```python | ||
| from telemetry import record_telemetry, RecordType | ||
|
|
||
| record_telemetry(RecordType.USAGE, { | ||
| "custom_event": "my_feature_used", | ||
| "metadata": "optional_data" | ||
| }) | ||
| ``` | ||
|
|
||
| ### Telemetry Status Check | ||
| ```python | ||
| from telemetry import is_telemetry_enabled | ||
|
|
||
| if is_telemetry_enabled(): | ||
| print("Telemetry is active") | ||
| else: | ||
| print("Telemetry is disabled") | ||
| ``` | ||
|
|
||
| ## 📋 Data Retention Policy | ||
|
|
||
| - **Aggregated Data**: Retained indefinitely for product insights | ||
| - **Raw Events**: Automatically purged after 90 days | ||
| - **Personal Data**: None collected, so none to purge | ||
| - **Opt-out**: Immediate - no data sent after opting out | ||
|
|
||
| ## 🤝 Contact & Transparency | ||
|
|
||
| - **Questions**: [Discord Community](https://discord.gg/y4p8KfzrN4) | ||
| - **Issues**: [GitHub Issues](https://github.com/CoplayDev/unity-mcp/issues) | ||
| - **Privacy Concerns**: Create a GitHub issue with "Privacy" label | ||
| - **Source Code**: All telemetry code is open source in this repository | ||
|
|
||
| ## 📊 Example Telemetry Event | ||
|
|
||
| Here's what a typical telemetry event looks like: | ||
|
|
||
| ```json | ||
| { | ||
| "record": "tool_execution", | ||
| "timestamp": 1704067200, | ||
| "customer_uuid": "550e8400-e29b-41d4-a716-446655440000", | ||
| "session_id": "abc123-def456-ghi789", | ||
| "version": "3.0.2", | ||
| "platform": "posix", | ||
| "data": { | ||
| "tool_name": "manage_script", | ||
| "success": true, | ||
| "duration_ms": 42.5 | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Notice: | ||
| - ✅ Anonymous UUID (randomly generated) | ||
| - ✅ Tool performance metrics | ||
| - ✅ Success/failure tracking | ||
| - ❌ No code content | ||
| - ❌ No project information | ||
| - ❌ No personal data | ||
|
|
||
| --- | ||
|
|
||
| *Unity MCP Telemetry is designed to respect your privacy while helping us build a better tool. Thank you for helping improve Unity MCP!* |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,188 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using UnityEngine; | ||
|
|
||
| namespace MCPForUnity.Editor.Helpers | ||
| { | ||
| /// <summary> | ||
| /// Unity Bridge telemetry helper for collecting usage analytics | ||
| /// Following privacy-first approach with easy opt-out mechanisms | ||
| /// </summary> | ||
| public static class TelemetryHelper | ||
| { | ||
| private const string TELEMETRY_DISABLED_KEY = "MCPForUnity.TelemetryDisabled"; | ||
| private const string CUSTOMER_UUID_KEY = "MCPForUnity.CustomerUUID"; | ||
|
|
||
| /// <summary> | ||
| /// Check if telemetry is enabled (can be disabled via Environment Variable or EditorPrefs) | ||
| /// </summary> | ||
| public static bool IsEnabled | ||
| { | ||
| get | ||
| { | ||
| // Check environment variables first | ||
| var envDisable = Environment.GetEnvironmentVariable("DISABLE_TELEMETRY"); | ||
| if (!string.IsNullOrEmpty(envDisable) && | ||
| (envDisable.ToLower() == "true" || envDisable == "1")) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| var unityMcpDisable = Environment.GetEnvironmentVariable("UNITY_MCP_DISABLE_TELEMETRY"); | ||
| if (!string.IsNullOrEmpty(unityMcpDisable) && | ||
| (unityMcpDisable.ToLower() == "true" || unityMcpDisable == "1")) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| // Check EditorPrefs | ||
| return !UnityEditor.EditorPrefs.GetBool(TELEMETRY_DISABLED_KEY, false); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Get or generate customer UUID for anonymous tracking | ||
| /// </summary> | ||
| public static string GetCustomerUUID() | ||
| { | ||
| var uuid = UnityEditor.EditorPrefs.GetString(CUSTOMER_UUID_KEY, ""); | ||
| if (string.IsNullOrEmpty(uuid)) | ||
| { | ||
| uuid = System.Guid.NewGuid().ToString(); | ||
| UnityEditor.EditorPrefs.SetString(CUSTOMER_UUID_KEY, uuid); | ||
| } | ||
| return uuid; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Disable telemetry (stored in EditorPrefs) | ||
| /// </summary> | ||
| public static void DisableTelemetry() | ||
| { | ||
| UnityEditor.EditorPrefs.SetBool(TELEMETRY_DISABLED_KEY, true); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Enable telemetry (stored in EditorPrefs) | ||
| /// </summary> | ||
| public static void EnableTelemetry() | ||
| { | ||
| UnityEditor.EditorPrefs.SetBool(TELEMETRY_DISABLED_KEY, false); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Send telemetry data to Python server for processing | ||
| /// This is a lightweight bridge - the actual telemetry logic is in Python | ||
| /// </summary> | ||
| public static void RecordEvent(string eventType, Dictionary<string, object> data = null) | ||
| { | ||
| if (!IsEnabled) | ||
| return; | ||
|
|
||
| try | ||
| { | ||
| var telemetryData = new Dictionary<string, object> | ||
| { | ||
| ["event_type"] = eventType, | ||
| ["timestamp"] = DateTimeOffset.UtcNow.ToUnixTimeSeconds(), | ||
| ["customer_uuid"] = GetCustomerUUID(), | ||
| ["unity_version"] = Application.unityVersion, | ||
| ["platform"] = Application.platform.ToString(), | ||
| ["source"] = "unity_bridge" | ||
| }; | ||
|
|
||
| if (data != null) | ||
| { | ||
| telemetryData["data"] = data; | ||
| } | ||
|
|
||
| // Send to Python server via existing bridge communication | ||
| // The Python server will handle actual telemetry transmission | ||
| SendTelemetryToPythonServer(telemetryData); | ||
| } | ||
| catch (Exception e) | ||
| { | ||
| // Never let telemetry errors interfere with functionality | ||
| if (IsDebugEnabled()) | ||
| { | ||
| Debug.LogWarning($"Telemetry error (non-blocking): {e.Message}"); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Record bridge startup event | ||
| /// </summary> | ||
| public static void RecordBridgeStartup() | ||
| { | ||
| RecordEvent("bridge_startup", new Dictionary<string, object> | ||
| { | ||
| ["bridge_version"] = "3.0.2", | ||
| ["auto_connect"] = MCPForUnityBridge.IsAutoConnectMode | ||
dsarno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }); | ||
| } | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /// <summary> | ||
| /// Record bridge connection event | ||
| /// </summary> | ||
| public static void RecordBridgeConnection(bool success, string error = null) | ||
| { | ||
| var data = new Dictionary<string, object> | ||
| { | ||
| ["success"] = success | ||
| }; | ||
|
|
||
| if (!string.IsNullOrEmpty(error)) | ||
| { | ||
| data["error"] = error.Substring(0, Math.Min(200, error.Length)); | ||
| } | ||
|
|
||
| RecordEvent("bridge_connection", data); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Record tool execution from Unity side | ||
| /// </summary> | ||
| public static void RecordToolExecution(string toolName, bool success, float durationMs, string error = null) | ||
| { | ||
| var data = new Dictionary<string, object> | ||
| { | ||
| ["tool_name"] = toolName, | ||
| ["success"] = success, | ||
| ["duration_ms"] = Math.Round(durationMs, 2) | ||
| }; | ||
|
|
||
| if (!string.IsNullOrEmpty(error)) | ||
| { | ||
| data["error"] = error.Substring(0, Math.Min(200, error.Length)); | ||
| } | ||
|
|
||
| RecordEvent("tool_execution_unity", data); | ||
| } | ||
|
|
||
| private static void SendTelemetryToPythonServer(Dictionary<string, object> telemetryData) | ||
| { | ||
| // This would integrate with the existing bridge communication system | ||
| // For now, we'll just log it when debug is enabled | ||
| if (IsDebugEnabled()) | ||
| { | ||
| Debug.Log($"<b><color=#2EA3FF>MCP-TELEMETRY</color></b>: {telemetryData["event_type"]}"); | ||
| } | ||
|
|
||
| // TODO: Integrate with MCPForUnityBridge command system | ||
| // We would send this as a special telemetry command to the Python server | ||
| } | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| private static bool IsDebugEnabled() | ||
| { | ||
| try | ||
| { | ||
| return UnityEditor.EditorPrefs.GetBool("MCPForUnity.DebugLogs", false); | ||
| } | ||
| catch | ||
| { | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.