Skip to content

Commit 93da556

Browse files
authored
Merge branch 'main' into caozhen/fix-goose-rm-error
2 parents 3547ea7 + 35722af commit 93da556

File tree

10 files changed

+109
-26
lines changed

10 files changed

+109
-26
lines changed

src/mcpm/clients/base.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import logging
88
import os
99
import platform
10+
import re
1011
from typing import Any, Dict, List, Optional, Union
1112

1213
from pydantic import TypeAdapter
@@ -158,6 +159,35 @@ def deactivate_profile(self) -> bool:
158159
"""
159160
pass
160161

162+
def get_associated_profile(self) -> Optional[str]:
163+
"""
164+
Get the associated profile for this client
165+
166+
Returns:
167+
Optional[str]: Name of the associated profile, or None if no profile is associated
168+
"""
169+
router_service = self.get_server(ROUTER_SERVER_NAME)
170+
if not router_service:
171+
# No associated profile
172+
return None
173+
174+
# Extract profile name from router service
175+
if isinstance(router_service, STDIOServerConfig):
176+
if hasattr(router_service, "args") and "--headers" in router_service.args:
177+
try:
178+
idx = router_service.args.index("profile")
179+
if idx < len(router_service.args) - 1:
180+
return router_service.args[idx + 1]
181+
except ValueError:
182+
pass
183+
else:
184+
if hasattr(router_service, "url") and "profile=" in router_service.url:
185+
matched = re.search(r"profile=([^&]+)", router_service.url)
186+
if matched:
187+
return matched.group(1)
188+
189+
return None
190+
161191

162192
class JSONClientManager(BaseClientManager):
163193
"""

src/mcpm/clients/client_config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ def set_active_client(self, client_name: Optional[str]) -> bool:
5454

5555
# Set the active client
5656
result = self.config_manager.set_config("active_client", client_name)
57+
# refresh the active profile
58+
client = ClientRegistry.get_client_manager(client_name)
59+
self.set_active_profile(client.get_associated_profile()) # type: ignore
5760
self._refresh_config()
5861
return result
5962

src/mcpm/clients/managers/claude_desktop.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from mcpm.clients.base import JSONClientManager
1010
from mcpm.schemas.server_config import ServerConfig
11-
from mcpm.utils.router_server import format_server_url_with_proxy_param
11+
from mcpm.utils.router_server import format_server_url_with_proxy_headers
1212

1313
logger = logging.getLogger(__name__)
1414

@@ -114,7 +114,7 @@ def is_server_disabled(self, server_name: str) -> bool:
114114
return "disabledServers" in config and server_name in config["disabledServers"]
115115

116116
def _format_router_server(self, profile_name, base_url) -> ServerConfig:
117-
return format_server_url_with_proxy_param(self.client_key, profile_name, base_url)
117+
return format_server_url_with_proxy_headers(self.client_key, profile_name, base_url)
118118

119119
# Uses base class implementation of remove_server
120120

src/mcpm/clients/managers/continue_extension.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,10 @@ def __init__(self, config_path=None):
4343
self.config_path = config_path
4444
else:
4545
# Set config path based on detected platform
46-
if os.name == "Darwin": # macOS
47-
self.config_path = os.path.expanduser("~/.continue/config.yaml")
48-
elif os.name == "Windows":
46+
if self._system == "Windows":
4947
self.config_path = os.path.join(os.environ.get("USERPROFILE", ""), ".continue", "config.yaml")
5048
else:
51-
# Linux
49+
# MacOS or Linux
5250
self.config_path = os.path.expanduser("~/.continue/config.yaml")
5351

5452
# Also check for workspace config

src/mcpm/clients/managers/cursor.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,11 @@ def __init__(self, config_path=None):
3131
self.config_path = config_path
3232
else:
3333
# Set config path based on detected platform
34-
if self._system == "Darwin": # macOS
35-
self.config_path = os.path.expanduser("~/Library/Application Support/Cursor/User/mcp_config.json")
36-
elif self._system == "Windows":
37-
self.config_path = os.path.join(os.environ.get("APPDATA", ""), "Cursor", "User", "mcp_config.json")
34+
if self._system == "Windows":
35+
self.config_path = os.path.join(os.environ.get("USERPROFILE", ""), ".cursor", "mcp.json")
3836
else:
39-
# Linux
40-
self.config_path = os.path.expanduser("~/.config/Cursor/User/mcp_config.json")
37+
# MacOS or Linux
38+
self.config_path = os.path.expanduser("~/.cursor/mcp.json")
4139

4240
def _get_empty_config(self) -> Dict[str, Any]:
4341
"""Get empty config structure for Cursor"""

src/mcpm/clients/managers/goose.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,10 @@ def __init__(self, config_path=None):
4141
self.config_path = config_path
4242
else:
4343
# Set config path based on detected platform
44-
if os.name == "Darwin": # macOS
45-
self.config_path = os.path.expanduser("~/.config/goose/config.yaml")
46-
elif os.name == "Windows":
44+
if self._system == "Windows":
4745
self.config_path = os.path.join(os.environ.get("USERPROFILE", ""), ".config", "goose", "config.yaml")
4846
else:
49-
# Linux
47+
# MacOS or Linux
5048
self.config_path = os.path.expanduser("~/.config/goose/config.yaml")
5149

5250
# Also check for workspace config

src/mcpm/clients/managers/windsurf.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,12 @@ def __init__(self, config_path=None):
3232
self.config_path = config_path
3333
else:
3434
# Set config path based on detected platform
35-
if self._system == "Darwin": # macOS
36-
self.config_path = os.path.expanduser("~/.codeium/windsurf/mcp_config.json")
37-
elif self._system == "Windows":
35+
if self._system == "Windows":
3836
self.config_path = os.path.join(
39-
os.environ.get("LOCALAPPDATA", ""), "Codeium", "windsurf", "mcp_config.json"
37+
os.environ.get("USERPROFILE", ""), ".codeium", "windsurf", "mcp_config.json"
4038
)
4139
else:
42-
# Linux
40+
# MacOS or Linux
4341
self.config_path = os.path.expanduser("~/.codeium/windsurf/mcp_config.json")
4442

4543
def to_client_format(self, server_config: ServerConfig) -> Dict[str, Any]:

src/mcpm/commands/client.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def list_clients():
4646
table.add_column("Client Name", style="cyan")
4747
table.add_column("Installation", style="yellow")
4848
table.add_column("Status", style="green")
49+
table.add_column("Profile", style="magenta")
4950

5051
active_client = ClientRegistry.get_active_client()
5152
installed_clients = ClientRegistry.detect_installed_clients()
@@ -61,8 +62,12 @@ def list_clients():
6162
# Get client info for more details
6263
client_info = ClientRegistry.get_client_info(client)
6364
display_name = client_info.get("name", client)
65+
# Get Profile activated
66+
client_manager = ClientRegistry.get_client_manager(client)
67+
profile = client_manager.get_associated_profile() if client_manager else None
68+
active_profile = f"[bold magenta]{profile}[/]" if profile else ""
6469

65-
table.add_row(f"{display_name} ({client})", install_status, active_status)
70+
table.add_row(f"{display_name} ({client})", install_status, active_status, active_profile)
6671

6772
console.print(table)
6873

@@ -83,6 +88,7 @@ def set_client(client_name):
8388
8489
CLIENT is the name of the client to set as active.
8590
"""
91+
8692
# Get the list of supported clients
8793
supported_clients = ClientRegistry.get_supported_clients()
8894

@@ -97,10 +103,13 @@ def set_client(client_name):
97103
console.print(f"[bold yellow]Note:[/] {client_name} is already the active client")
98104
return
99105

100-
# Attempt to set the active client
106+
# Attempt to set the active client with active profile inner switched
101107
success = ClientRegistry.set_active_client(client_name)
102108
if success:
103109
console.print(f"[bold green]Success:[/] Active client set to {client_name}")
110+
active_profile = ClientRegistry.get_active_profile()
111+
if active_profile:
112+
console.print(f"[bold green]Success:[/] Active profile set to {active_profile}")
104113

105114
# Provide information about what this means
106115
panel = Panel(

src/mcpm/commands/profile.py

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ def activate(profile_name, client=None):
3636
client_registry = ClientRegistry()
3737
config_manager = ConfigManager()
3838

39+
activate_this_client: bool = client is None
40+
3941
if client:
42+
if client == ClientRegistry.get_active_client():
43+
activate_this_client = True
44+
4045
console.print(f"[bold cyan]Activating profile '{profile_name}' in client '{client}'...[/]")
4146
client_manager = ClientRegistry.get_client_manager(client)
4247
if client_manager is None:
@@ -54,9 +59,11 @@ def activate(profile_name, client=None):
5459
console.print(f"[bold red]Error:[/] Client '{client}' not found.")
5560
return
5661
success = client_manager.activate_profile(profile_name, config_manager.get_router_config())
57-
if success:
62+
if success and activate_this_client:
5863
client_registry.set_active_profile(profile_name)
5964
console.print(f"\n[green]Profile '{profile_name}' activated successfully.[/]\n")
65+
elif success:
66+
console.print(f"\n[green]Profile '{profile_name}' activated successfully for client '{client}'.[/]\n")
6067
else:
6168
console.print(f"[bold red]Error:[/] Failed to activate profile '{profile_name}'.")
6269

@@ -69,15 +76,20 @@ def deactivate(client=None):
6976
7077
Unsets the active profile.
7178
"""
79+
deactivate_this_client: bool = client is None
80+
7281
# Set the active profile
7382
active_profile = ClientRegistry.get_active_profile()
74-
if active_profile is None:
83+
if deactivate_this_client and active_profile is None:
7584
console.print("[bold yellow]No active profile found.[/]\n")
7685
return
7786
console.print(f"\n[green]Deactivating profile '{active_profile}'...[/]")
7887
client_registry = ClientRegistry()
7988

8089
if client:
90+
if client == ClientRegistry.get_active_client():
91+
deactivate_this_client = True
92+
8193
console.print(f"[bold cyan]Deactivating profile '{active_profile}' in client '{client}'...[/]")
8294
client_manager = ClientRegistry.get_client_manager(client)
8395
if client_manager is None:
@@ -95,9 +107,11 @@ def deactivate(client=None):
95107
console.print(f"[bold red]Error:[/] Client '{client}' not found.")
96108
return
97109
success = client_manager.deactivate_profile()
98-
if success:
110+
if success and deactivate_this_client:
99111
client_registry.set_active_profile(None)
100112
console.print(f"\n[yellow]Profile '{active_profile}' deactivated successfully.[/]\n")
113+
elif success:
114+
console.print(f"\n[yellow]Profile '{active_profile}' deactivated successfully for client '{client}'.[/]\n")
101115
else:
102116
console.print(f"[bold red]Error:[/] Failed to deactivate profile '{active_profile}' in client '{client}'.")
103117

@@ -197,6 +211,22 @@ def remove(profile_name):
197211
if not profile_config_manager.delete_profile(profile_name):
198212
console.print(f"[bold red]Error:[/] Profile '{profile_name}' not found.")
199213
return
214+
# Check whether any client is associated with the deleted profile
215+
clients = ClientRegistry.get_supported_clients()
216+
for client in clients:
217+
client_manager = ClientRegistry.get_client_manager(client)
218+
if client_manager:
219+
profile_this_client_associated = client_manager.get_associated_profile()
220+
if profile_this_client_associated == profile_name:
221+
# Deactivate the profile in this client
222+
client_manager.deactivate_profile()
223+
console.print(f"\n[green]Profile '{profile_name}' deactivated successfully for client '{client}'.[/]\n")
224+
225+
# fresh the active_profile
226+
activated_profile = ClientRegistry.get_active_profile()
227+
if activated_profile == profile_name:
228+
ClientRegistry.set_active_profile(None)
229+
200230
console.print(f"\n[green]Profile '{profile_name}' deleted successfully.[/]\n")
201231

202232

@@ -212,4 +242,22 @@ def rename(profile_name):
212242
if not profile_config_manager.rename_profile(profile_name, new_profile_name):
213243
console.print(f"[bold red]Error:[/] Profile '{profile_name}' not found.")
214244
return
245+
# Check whether any client is associated with the profile to be renamed
246+
clients = ClientRegistry.get_supported_clients()
247+
config_manager = ConfigManager()
248+
for client in clients:
249+
client_manager = ClientRegistry.get_client_manager(client)
250+
if client_manager:
251+
profile_this_client_associated = client_manager.get_associated_profile()
252+
if profile_this_client_associated == profile_name:
253+
# fresh the config
254+
client_manager.deactivate_profile()
255+
client_manager.activate_profile(new_profile_name, config_manager.get_router_config())
256+
console.print(f"\n[green]Profile '{profile_name}' deactivated successfully for client '{client}'.[/]\n")
257+
258+
# fresh the active_profile
259+
activated_profile = ClientRegistry.get_active_profile()
260+
if activated_profile == profile_name:
261+
ClientRegistry.set_active_profile(new_profile_name)
262+
215263
console.print(f"\n[green]Profile '{profile_name}' renamed to '{new_profile_name}' successfully.[/]\n")

src/mcpm/commands/server_operations/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def profile_add_server(profile: str, server_config: ServerConfig, force: bool =
5757
if profile_manager.get_profile(profile) is None:
5858
console.print(f"[bold red]Error:[/] Profile '{profile}' not found.")
5959
return False
60+
6061
if profile_manager.get_profile_server(profile, server_config.name) and not force:
6162
console.print(f"[bold red]Error:[/] Server '{server_config.name}' already exists in {profile}.")
6263
console.print("Use --force to override.")

0 commit comments

Comments
 (0)