Skip to content

Commit eb799d5

Browse files
committed
Update client commands
1 parent 760bbb6 commit eb799d5

File tree

6 files changed

+455
-203
lines changed

6 files changed

+455
-203
lines changed

pages/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,8 @@ <h3><span><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox
435435
<h3><span><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg></span> Edit Configuration</h3>
436436
<p>View or edit your client's configuration:</p>
437437
<div class="code-block">
438-
<code><span class="command-prompt">$</span> mcpm edit</code>
439-
<button class="copy-button" data-command="mcpm edit"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></button>
438+
<code><span class="command-prompt">$</span> mcpm client edit</code>
439+
<button class="copy-button" data-command="mcpm client edit"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></button>
440440
</div>
441441
</div>
442442
</div>
@@ -523,7 +523,7 @@ <h2>Supported Clients</h2>
523523

524524
if (commandText && cursor) {
525525
// Commands to type - updated to match actual CLI commands
526-
const commands = [" search", " add", " list", " remove", " edit", " stash", " pop"];
526+
const commands = [" search", " add", " list", " remove", " client edit", " stash", " pop"];
527527
let currentCommand = 0;
528528
let charIndex = 0;
529529
let isTyping = true;

src/mcpm/cli.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
add,
1313
client,
1414
config,
15-
edit,
1615
inspector,
1716
list,
1817
pop,
@@ -121,10 +120,6 @@ def main(ctx, help_flag):
121120
commands_table.add_row(" [cyan]add[/]", "Add an MCP server directly to a client.")
122121
commands_table.add_row(" [cyan]client[/]", "Manage the active MCPM client.")
123122
commands_table.add_row(" [cyan]config[/]", "Manage MCPM configuration.")
124-
commands_table.add_row(
125-
" [cyan]edit[/]",
126-
"View or edit the active MCPM client's configuration file.",
127-
)
128123
commands_table.add_row(" [cyan]inspector[/]", "Launch the MCPM Inspector UI to examine servers.")
129124
commands_table.add_row(" [cyan]list[/]", "List all installed MCP servers.")
130125
commands_table.add_row(" [cyan]remove[/]", "Remove an installed MCP server.")
@@ -144,7 +139,6 @@ def main(ctx, help_flag):
144139
main.add_command(remove.remove)
145140
main.add_command(add.add)
146141
main.add_command(list.list)
147-
main.add_command(edit.edit)
148142

149143
main.add_command(stash.stash)
150144
main.add_command(pop.pop)

src/mcpm/commands/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
MCPM commands package
33
"""
44

5-
__all__ = ["add", "client", "edit", "inspector", "list", "pop", "profile", "remove", "search", "stash"]
5+
__all__ = ["add", "client", "inspector", "list", "pop", "profile", "remove", "search", "stash"]
66

77
# All command modules
8-
from . import add, client, edit, inspector, list, pop, profile, remove, search, stash
8+
from . import add, client, inspector, list, pop, profile, remove, search, stash

src/mcpm/commands/client.py

Lines changed: 166 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,87 +2,89 @@
22
Client command for MCPM
33
"""
44

5+
import json
6+
import os
7+
import subprocess
8+
59
import click
610
from rich.console import Console
711
from rich.panel import Panel
12+
from rich.prompt import Confirm
813
from rich.table import Table
914

1015
from mcpm.clients.client_config import ClientConfigManager
1116
from mcpm.clients.client_registry import ClientRegistry
17+
from mcpm.utils.display import print_client_error, print_error, print_server_config
1218

1319
console = Console()
1420
client_config_manager = ClientConfigManager()
1521

1622

17-
@click.command()
18-
@click.argument("client_name", required=False)
19-
@click.option("--list", is_flag=True, help="List all supported clients")
20-
def client(client_name, list):
21-
"""Manage the active MCP client.
23+
@click.group(context_settings=dict(help_option_names=["-h", "--help"]))
24+
def client():
25+
"""Manage MCP clients.
2226
23-
If no arguments are provided, shows the current active client.
24-
If a client name is provided, sets it as the active client.
27+
Commands for listing, setting the active client, and editing client configurations.
2528
2629
Examples:
27-
mcpm client # Show current active client
28-
mcpm client --list # List all supported clients
29-
mcpm client claude-desktop # Set Claude Desktop as the active client
30+
31+
\b
32+
mcpm client ls # List all supported MCP clients and their status
33+
mcpm client set CLIENT # Set the active client
34+
mcpm client edit # Open active client MCP settings in external editor
3035
"""
36+
pass
37+
38+
39+
@client.command(name="ls", context_settings=dict(help_option_names=["-h", "--help"]))
40+
def list_clients():
41+
"""List all supported MCP clients and their status."""
3142
# Get the list of supported clients
3243
supported_clients = ClientRegistry.get_supported_clients()
3344

34-
# List all supported clients if requested
35-
if list:
36-
table = Table(title="Supported MCP Clients")
37-
table.add_column("Client Name", style="cyan")
38-
table.add_column("Installation", style="yellow")
39-
table.add_column("Status", style="green")
45+
table = Table(title="Supported MCP Clients")
46+
table.add_column("Client Name", style="cyan")
47+
table.add_column("Installation", style="yellow")
48+
table.add_column("Status", style="green")
4049

41-
active_client = ClientRegistry.get_active_client()
42-
installed_clients = ClientRegistry.detect_installed_clients()
50+
active_client = ClientRegistry.get_active_client()
51+
installed_clients = ClientRegistry.detect_installed_clients()
4352

44-
for client in sorted(supported_clients):
45-
# Determine installation status
46-
installed = installed_clients.get(client, False)
47-
install_status = "[green]Installed[/]" if installed else "[gray]Not installed[/]"
53+
for client in sorted(supported_clients):
54+
# Determine installation status
55+
installed = installed_clients.get(client, False)
56+
install_status = "[green]Installed[/]" if installed else "[gray]Not installed[/]"
4857

49-
# Determine active status
50-
active_status = "[bold green]ACTIVE[/]" if client == active_client else ""
58+
# Determine active status
59+
active_status = "[bold green]ACTIVE[/]" if client == active_client else ""
5160

52-
# Get client info for more details
53-
client_info = ClientRegistry.get_client_info(client)
54-
display_name = client_info.get("name", client)
61+
# Get client info for more details
62+
client_info = ClientRegistry.get_client_info(client)
63+
display_name = client_info.get("name", client)
5564

56-
table.add_row(f"{display_name} ({client})", install_status, active_status)
65+
table.add_row(f"{display_name} ({client})", install_status, active_status)
5766

58-
console.print(table)
67+
console.print(table)
5968

60-
# Add helpful instructions for non-installed clients
61-
non_installed = [c for c, installed in installed_clients.items() if not installed]
62-
if non_installed:
63-
console.print("\n[italic]To use a non-installed client, you need to install it first.[/]")
64-
for client in non_installed:
65-
info = ClientRegistry.get_client_info(client)
66-
if "download_url" in info:
67-
console.print(f"[yellow]{info.get('name', client)}[/]: {info['download_url']}")
69+
# Add helpful instructions for non-installed clients
70+
non_installed = [c for c, installed in installed_clients.items() if not installed]
71+
if non_installed:
72+
console.print("\n[italic]To use a non-installed client, you need to install it first.[/]")
73+
for client in non_installed:
74+
info = ClientRegistry.get_client_info(client)
75+
if "download_url" in info:
76+
console.print(f"[yellow]{info.get('name', client)}[/]: {info['download_url']}")
6877

69-
return
7078

71-
# If no client name specified, show the current active client
72-
if not client_name:
73-
active_client = ClientRegistry.get_active_client()
74-
console.print(f"Current active client: [bold cyan]{active_client}[/]")
79+
@client.command(name="set", context_settings=dict(help_option_names=["-h", "--help"]))
80+
@click.argument("client_name", required=True)
81+
def set_client(client_name):
82+
"""Set the active MCP client.
7583
76-
# Display some helpful information about setting clients
77-
console.print("\nTo change the active client, run:")
78-
for client in sorted(supported_clients):
79-
if client != active_client:
80-
console.print(f" mcpm client {client}")
81-
82-
# Display a note about using --list
83-
console.print("\nTo see all supported clients:")
84-
console.print(" mcpm client --list")
85-
return
84+
CLIENT is the name of the client to set as active.
85+
"""
86+
# Get the list of supported clients
87+
supported_clients = ClientRegistry.get_supported_clients()
8688

8789
# Set the active client if provided
8890
if client_name not in supported_clients:
@@ -110,3 +112,115 @@ def client(client_name, list):
110112
console.print(panel)
111113
else:
112114
console.print(f"[bold red]Error:[/] Failed to set {client_name} as the active client")
115+
116+
117+
@client.command(name="edit", context_settings=dict(help_option_names=["-h", "--help"]))
118+
def edit_client():
119+
"""Open the active client's MCP settings in external editor."""
120+
# Get the active client manager and related information
121+
client_manager = ClientRegistry.get_active_client_manager()
122+
client = ClientRegistry.get_active_client()
123+
client_info = ClientRegistry.get_client_info(client)
124+
client_name = client_info.get("name", client)
125+
126+
# Check if client is supported
127+
if client_manager is None:
128+
print_client_error(client_name)
129+
return
130+
131+
# Get the client config file path
132+
config_path = client_manager.config_path
133+
134+
# Check if the client is installed
135+
if not client_manager.is_client_installed():
136+
print_error(f"{client_name} installation not detected.")
137+
return
138+
139+
# Check if config file exists
140+
config_exists = os.path.exists(config_path)
141+
142+
# Display the config file information
143+
console.print(f"[bold]{client_name} config file:[/] {config_path}")
144+
console.print(f"[bold]Status:[/] {'[green]Exists[/]' if config_exists else '[yellow]Does not exist[/]'}\n")
145+
146+
# Create config file if it doesn't exist and user confirms
147+
if not config_exists:
148+
console.print(f"[bold yellow]Creating new {client_name} config file...[/]")
149+
150+
# Create a basic config template
151+
basic_config = {
152+
"mcpServers": {
153+
"filesystem": {
154+
"command": "npx",
155+
"args": [
156+
"-y",
157+
"@modelcontextprotocol/server-filesystem",
158+
os.path.expanduser("~/Desktop"),
159+
os.path.expanduser("~/Downloads"),
160+
],
161+
}
162+
}
163+
}
164+
165+
# Create the directory if it doesn't exist
166+
os.makedirs(os.path.dirname(config_path), exist_ok=True)
167+
168+
# Write the template to file
169+
try:
170+
with open(config_path, "w") as f:
171+
json.dump(basic_config, f, indent=2)
172+
console.print("[green]Successfully created config file![/]\n")
173+
config_exists = True
174+
except Exception as e:
175+
print_error("Error creating config file", str(e))
176+
return
177+
178+
# Show the current configuration if it exists
179+
if config_exists:
180+
try:
181+
with open(config_path, "r") as f:
182+
config_content = f.read()
183+
184+
# Display the content
185+
console.print("[bold]Current configuration:[/]")
186+
panel = Panel(config_content, title=f"{client_name} Config", expand=False)
187+
console.print(panel)
188+
189+
# Count the configured servers
190+
try:
191+
config_json = json.loads(config_content)
192+
server_count = len(config_json.get("mcpServers", {}))
193+
console.print(f"[bold]Configured servers:[/] {server_count}")
194+
195+
# Display detailed information for each server
196+
if server_count > 0:
197+
console.print("\n[bold]MCP Server Details:[/]")
198+
for server_name, server_config in config_json.get("mcpServers", {}).items():
199+
print_server_config(server_name, server_config)
200+
201+
except json.JSONDecodeError:
202+
console.print("[yellow]Warning: Config file contains invalid JSON[/]")
203+
204+
except Exception as e:
205+
print_error("Error reading config file", str(e))
206+
207+
# Prompt to edit if file exists
208+
should_edit = False
209+
if config_exists:
210+
should_edit = Confirm.ask("Would you like to open this file in your default editor?")
211+
212+
# Open in default editor if requested
213+
if should_edit and config_exists:
214+
try:
215+
console.print("[bold green]Opening config file in your default editor...[/]")
216+
217+
# Use appropriate command based on platform
218+
if os.name == "nt": # Windows
219+
os.startfile(config_path)
220+
elif os.name == "posix": # macOS and Linux
221+
subprocess.run(["open", config_path] if os.uname().sysname == "Darwin" else ["xdg-open", config_path])
222+
223+
console.print(f"[italic]After editing, {client_name} must be restarted for changes to take effect.[/]")
224+
except Exception as e:
225+
print_error("Error opening editor", str(e))
226+
console.print(f"You can manually edit the file at: {config_path}")

0 commit comments

Comments
 (0)