@@ -33,6 +33,122 @@ public static string SanitizeAssetPath(string path)
3333 return path ;
3434 }
3535
36+ /// <summary>
37+ /// Gets the absolute file system path to the package root.
38+ /// Uses StackTrace/ScriptableObject trick to resolve real path (bypassing PackageCache if symlinked).
39+ /// </summary>
40+ public static string GetPackageAbsolutePath ( )
41+ {
42+ // 1. Try to find path relative to this script file (Most reliable for local dev & mono scripts)
43+ try
44+ {
45+ // Get the path of THIS source file during execution
46+ string scriptFilePath = GetCallerFilePath ( ) ;
47+ if ( ! string . IsNullOrEmpty ( scriptFilePath ) && File . Exists ( scriptFilePath ) )
48+ {
49+ // Current file: .../MCPForUnity/Editor/Helpers/AssetPathUtility.cs
50+ // We need: .../MCPForUnity
51+ return Path . GetFullPath ( Path . Combine ( Path . GetDirectoryName ( scriptFilePath ) , ".." , ".." ) ) ;
52+ }
53+ }
54+ catch ( Exception ex )
55+ {
56+ McpLog . Warn ( $ "Failed to resolve path from stack trace: { ex . Message } ") ;
57+ }
58+
59+ // 2. Fallback to standard Unity PackageInfo (Reliable for Registry/Git packages)
60+ string packageRoot = GetMcpPackageRootPath ( ) ;
61+ if ( string . IsNullOrEmpty ( packageRoot ) ) return null ;
62+
63+ // If it's already an absolute path, we're good
64+ if ( Path . IsPathRooted ( packageRoot ) )
65+ {
66+ return packageRoot ;
67+ }
68+
69+ // If it's a virtual path (Packages/...), resolve it to physical path
70+ if ( packageRoot . StartsWith ( "Packages/" , StringComparison . OrdinalIgnoreCase ) )
71+ {
72+ var packageInfo = PackageInfo . FindForAssembly ( typeof ( AssetPathUtility ) . Assembly ) ;
73+ if ( packageInfo != null && ! string . IsNullOrEmpty ( packageInfo . resolvedPath ) )
74+ {
75+ return packageInfo . resolvedPath ;
76+ }
77+
78+ // If resolvedPath is failing but we have assetPath, try Path.GetFullPath
79+ // Note: This rarely works for Library/PackageCache, but worth a shot for local tarballs
80+ return Path . GetFullPath ( packageRoot ) ;
81+ }
82+ else if ( packageRoot . StartsWith ( "Assets/" , StringComparison . OrdinalIgnoreCase ) )
83+ {
84+ string relativePath = packageRoot . Substring ( "Assets/" . Length ) ;
85+ return Path . Combine ( Application . dataPath , relativePath ) ;
86+ }
87+
88+ return Path . GetFullPath ( packageRoot ) ;
89+ }
90+
91+ private static string GetCallerFilePath ( [ System . Runtime . CompilerServices . CallerFilePath ] string sourceFilePath = "" )
92+ {
93+ return sourceFilePath ;
94+ }
95+
96+ /// <summary>
97+ /// Gets the absolute path to the wrapper.js file in the package.
98+ /// </summary>
99+ /// <returns>Absolute path to wrapper.js, or null if not found</returns>
100+ public static string GetWrapperJsPath ( )
101+ {
102+ string packageRoot = GetMcpPackageRootPath ( ) ;
103+ if ( string . IsNullOrEmpty ( packageRoot ) )
104+ {
105+ return null ;
106+ }
107+
108+ // wrapper.js is expected to be in {packageRoot}/Server~/wrapper.js
109+ // But we need to handle virtual paths if consistent with GetPackageJson logic
110+
111+ string wrapperPath ;
112+
113+ // Convert virtual asset path to file system path (similar logic to GetPackageJson)
114+ if ( packageRoot . StartsWith ( "Packages/" , StringComparison . OrdinalIgnoreCase ) )
115+ {
116+ var packageInfo = PackageInfo . FindForAssembly ( typeof ( AssetPathUtility ) . Assembly ) ;
117+ if ( packageInfo != null && ! string . IsNullOrEmpty ( packageInfo . resolvedPath ) )
118+ {
119+ wrapperPath = Path . Combine ( packageInfo . resolvedPath , "Server~" , "wrapper.js" ) ;
120+ }
121+ else
122+ {
123+ return null ;
124+ }
125+ }
126+ else if ( packageRoot . StartsWith ( "Assets/" , StringComparison . OrdinalIgnoreCase ) )
127+ {
128+ string relativePath = packageRoot . Substring ( "Assets/" . Length ) ;
129+ wrapperPath = Path . Combine ( Application . dataPath , relativePath , "Server~" , "wrapper.js" ) ;
130+ }
131+ else
132+ {
133+ // Already absolute or unknown
134+ wrapperPath = Path . Combine ( packageRoot , "Server~" , "wrapper.js" ) ;
135+ }
136+
137+ if ( File . Exists ( wrapperPath ) )
138+ {
139+ return wrapperPath ;
140+ }
141+
142+ // Also check without the ~ just in case
143+ string wrapperPathNoTilde = Path . Combine ( Path . GetDirectoryName ( wrapperPath ) , "Server" , "wrapper.js" ) ;
144+ if ( File . Exists ( wrapperPathNoTilde ) )
145+ {
146+ return wrapperPathNoTilde ;
147+ }
148+
149+ return null ;
150+ }
151+
36152 /// <summary>
37153 /// Gets the MCP for Unity package root path.
38154 /// Works for registry Package Manager, local Package Manager, and Asset Store installations.
@@ -144,22 +260,39 @@ public static JObject GetPackageJson()
144260 /// <returns>Git URL string, or empty string if version is unknown and no override</returns>
145261 public static string GetMcpServerGitUrl ( )
146262 {
147- // Check for Git URL override first
263+ // Check for Git URL override first (still useful for forcing a specific repo)
148264 string gitUrlOverride = EditorPrefs . GetString ( EditorPrefKeys . GitUrlOverride , "" ) ;
149265 if ( ! string . IsNullOrEmpty ( gitUrlOverride ) )
150266 {
151267 return gitUrlOverride ;
152268 }
153269
154- // Fall back to default package version
155- string version = GetPackageVersion ( ) ;
156- if ( version == "unknown" )
270+ // Return hardcoded Git URL as requested by the user who prefers to push changes and use the clean URL
271+ // instead of local file paths.
272+ // Note: This means local changes MUST be pushed to GitHub to take effect in the server!
273+ return "git+https://github.com/choej2303/unity-mcp-gg.git@main#subdirectory=MCPForUnity/Server~" ;
274+
275+ /*
276+ // Local path logic disabled for clean config aesthetics
277+ string packageRoot = GetPackageAbsolutePath();
278+ if (!string.IsNullOrEmpty(packageRoot))
157279 {
158- // Fall back to main repo without pinned version so configs remain valid in test scenarios
159- return "git+https://github.com/CoplayDev/unity-mcp#subdirectory=Server" ;
280+ // The server code is in {packageRoot}/Server~ or {packageRoot}/Server
281+ // Try Server~ first (Unity hidden folder)
282+ string serverPathTilde = Path.Combine(packageRoot, "Server~");
283+ if (Directory.Exists(serverPathTilde))
284+ {
285+ return serverPathTilde;
286+ }
287+
288+ string serverPath = Path.Combine(packageRoot, "Server");
289+ return serverPath;
160290 }
161291
162- return $ "git+https://github.com/CoplayDev/unity-mcp@v{ version } #subdirectory=Server";
292+ // Fallback to git URL if local path cannot be determined
293+ // Note: pip/uv uses '#subdirectory=' syntax, not '?path='
294+ return "git+https://github.com/choej2303/unity-mcp-gg.git@main#subdirectory=MCPForUnity/Server~";
295+ */
163296 }
164297
165298 /// <summary>
0 commit comments