using System; using System.Net; using System.Net.Sockets; using UnityEngine; namespace MCPForUnity.Editor.Config { /// /// Distribution controls so we can ship different defaults (Asset Store vs. git) without forking code. /// [CreateAssetMenu(menuName = "MCP/Distribution Settings", fileName = "McpDistributionSettings")] public class McpDistributionSettings : ScriptableObject { [SerializeField] internal string defaultHttpBaseUrl = "http://localhost:8080"; [SerializeField] internal bool skipSetupWindowWhenRemoteDefault = false; internal bool IsRemoteDefault => !string.IsNullOrWhiteSpace(defaultHttpBaseUrl) && !IsLocalAddress(defaultHttpBaseUrl); private static bool IsLocalAddress(string url) { if (string.IsNullOrWhiteSpace(url)) { return true; } if (!Uri.TryCreate(url, UriKind.Absolute, out var uri)) { return false; } string host = uri.Host; if (string.Equals(host, "localhost", StringComparison.OrdinalIgnoreCase)) { return true; } if (IPAddress.TryParse(host, out var ip)) { if (IPAddress.IsLoopback(ip)) { return true; } if (ip.AddressFamily == AddressFamily.InterNetwork) { var bytes = ip.GetAddressBytes(); // 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 if (bytes[0] == 10) return true; if (bytes[0] == 172 && bytes[1] >= 16 && bytes[1] <= 31) return true; if (bytes[0] == 192 && bytes[1] == 168) return true; if (bytes[0] == 169 && bytes[1] == 254) return true; } else if (ip.AddressFamily == AddressFamily.InterNetworkV6) { // ::1 loopback or fe80::/10 link-local if (ip.IsIPv6LinkLocal || ip.Equals(IPAddress.IPv6Loopback)) { return true; } } return false; } // Hostname: treat *.local as local network; otherwise assume remote. if (host.EndsWith(".local", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } } internal static class McpDistribution { private const string ResourcePath = "McpDistributionSettings"; private static McpDistributionSettings _cached; internal static McpDistributionSettings Settings { get { if (_cached != null) { return _cached; } _cached = UnityEngine.Resources.Load(ResourcePath); if (_cached != null) { return _cached; } // No asset present (git/dev installs) - fall back to baked-in defaults. _cached = ScriptableObject.CreateInstance(); _cached.name = "McpDistributionSettings (Runtime Defaults)"; return _cached; } } } }