From a8cc4711b63a037dfc275f0fc3b084b3363ef88e Mon Sep 17 00:00:00 2001 From: Egor Date: Sat, 10 Jan 2026 14:42:44 +0200 Subject: [PATCH] fix: add WSL path normalization for JetBrains plugin matching (#916) * fix: add WSL path normalization for JetBrains plugin matching When running Serena MCP server inside WSL2 with JetBrains IDE on Windows, the plugin returns paths like `//wsl.localhost/Ubuntu-24.04/home/user/...` while Serena expects `/home/user/...`. This causes `ServerNotFoundError` because the paths don't match despite pointing to the same location. This commit adds `_normalize_wsl_path()` method that converts WSL UNC paths to standard Linux paths before comparison, enabling seamless integration between WSL-based Claude Code and Windows-based JetBrains IDEs. Fixes #912 --- src/serena/tools/jetbrains_plugin_client.py | 24 ++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/serena/tools/jetbrains_plugin_client.py b/src/serena/tools/jetbrains_plugin_client.py index 1695e4db..f38c5709 100644 --- a/src/serena/tools/jetbrains_plugin_client.py +++ b/src/serena/tools/jetbrains_plugin_client.py @@ -4,6 +4,7 @@ Client for the Serena JetBrains Plugin import json import logging +import re from pathlib import Path from typing import Any, Optional, Self, TypeVar @@ -74,9 +75,30 @@ class JetBrainsPluginClient(ToStringMixin): raise ServerNotFoundError("Found no Serena service in a JetBrains IDE instance for the project at " + str(resolved_path)) + @staticmethod + def _normalize_wsl_path(path_str: str) -> Path: + """ + Normalize WSL UNC paths to Linux paths for comparison. + + When JetBrains IDE runs on Windows with a project opened from WSL, + it returns paths like `//wsl.localhost/Ubuntu-24.04/home/user/project` + or `//wsl$/Ubuntu/home/user/project`. This method converts such paths + to standard Linux format `/home/user/project` for proper matching. + + :param path_str: Path string that may be a WSL UNC path + :return: Normalized Path object + """ + path_str = str(path_str) + # Match //wsl.localhost//... or //wsl$//... + match = re.match(r"^//wsl(?:\.localhost|\$)/[^/]+(.*)$", path_str, re.IGNORECASE) + if match: + return Path(match.group(1)) + return Path(path_str) + def matches(self, resolved_path: Path) -> bool: try: - return Path(self.project_root()).resolve() == resolved_path + plugin_root = self._normalize_wsl_path(self.project_root()) + return plugin_root.resolve() == resolved_path except ConnectionError: return False