py-mcpdock-cli 1.0.13__py3-none-any.whl → 1.0.18__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cli/commands/install.py CHANGED
@@ -77,84 +77,81 @@ async def install_mcp_server(
77
77
  target_client = target_client or "claude" # Default to Claude if no client specified
78
78
  verbose(f"Initiating installation of {package_identifier} for {target_client}")
79
79
 
80
- console = Console()
81
-
82
80
  # Create and start spinner for package resolution
83
- with console.status(f"Resolving {package_identifier}...", spinner="dots") as status:
84
- try:
85
- # Resolve the package (fetch server metadata)
86
- verbose(f"Resolving package: {package_identifier}")
87
- server_data = await resolve_package(package_identifier)
88
- verbose(f"Package resolved successfully: {server_data.qualifiedName}")
89
-
90
- # Choose the appropriate connection type
91
- verbose("Choosing connection type...")
92
- connection = choose_connection(server_data)
93
- verbose(f"Selected connection type: {connection.type}")
94
-
95
- # Check for required runtimes and install if needed
96
- # Commented out as these are specific to JS environment
97
- # await ensure_uv_installed(connection)
98
- # await ensure_bun_installed(connection)
99
-
100
- # Inform users of remote server installation if applicable
101
- is_remote = check_and_notify_remote_server(server_data)
102
- if is_remote:
103
- verbose("Remote server detected, notification displayed")
104
-
105
- # Get the validated config values, no prompting
106
- status.update(f"Validating configuration for {package_identifier}...")
107
- collected_config_values = await validate_config_values(connection, initial_config)
108
-
109
- # Determine if we need to pass config flag
110
- config_flag_needed = initial_config is not None
111
-
112
- verbose(f"Config values validated: {json.dumps(collected_config_values, indent=2)}")
113
- verbose(f"Using config flag: {config_flag_needed}")
114
-
115
- # Format the server configuration
116
- verbose("Formatting server configuration...")
117
- server_config = format_server_config(
118
- package_identifier,
119
- collected_config_values,
120
- api_key,
121
- config_flag_needed,
122
- )
123
- verbose(f"Formatted server config: {json.dumps(server_config.__dict__, indent=2)}")
124
-
125
- # Read existing config from client
126
- status.update(f"Installing for {target_client}...")
127
- verbose(f"Reading configuration for client: {target_client}")
128
- client_config = read_config(target_client)
129
-
130
- # Get normalized server name to use as key
131
- server_name = get_server_name(package_identifier)
132
- verbose(f"Normalized server ID: {server_name}")
133
-
134
- # Update client configuration with new server
135
- verbose("Updating client configuration...")
136
- if not isinstance(client_config.mcpServers, dict):
137
- # Initialize if needed
138
- client_config.mcpServers = {}
139
-
140
- # Add the new server config
141
- client_config.mcpServers[server_name] = server_config
142
-
143
- # Write updated configuration
144
- verbose("Writing updated configuration...")
145
- write_config(client_config, target_client)
146
- verbose("Configuration successfully written")
147
-
148
- rprint(f"[green]{package_identifier} successfully installed for {target_client}[/green]")
149
-
150
- # No prompt for client restart
151
- verbose("Installation completed successfully")
152
-
153
- except Exception as e:
154
- verbose(f"Installation error: {str(e)}")
155
- rprint(f"[red]Failed to install {package_identifier}[/red]")
156
- rprint(f"[red]Error: {str(e)}[/red]")
157
- raise
81
+ try:
82
+ # Resolve the package (fetch server metadata)
83
+ verbose(f"Resolving package: {package_identifier}")
84
+ server_data = await resolve_package(package_identifier)
85
+ verbose(f"Package resolved successfully: {server_data.qualifiedName}")
86
+
87
+ # Choose the appropriate connection type
88
+ verbose("Choosing connection type...")
89
+ connection = choose_connection(server_data)
90
+ verbose(f"Selected connection type: {connection.type}")
91
+
92
+ # Check for required runtimes and install if needed
93
+ # Commented out as these are specific to JS environment
94
+ # await ensure_uv_installed(connection)
95
+ # await ensure_bun_installed(connection)
96
+
97
+ # Inform users of remote server installation if applicable
98
+ is_remote = check_and_notify_remote_server(server_data)
99
+ if is_remote:
100
+ verbose("Remote server detected, notification displayed")
101
+
102
+ # Get the validated config values, no prompting
103
+ verbose(f"Validating configuration for {package_identifier}...")
104
+ collected_config_values = await validate_config_values(connection, initial_config)
105
+
106
+ # Determine if we need to pass config flag
107
+ config_flag_needed = initial_config is not None
108
+
109
+ verbose(f"Config values validated: {json.dumps(collected_config_values, indent=2)}")
110
+ verbose(f"Using config flag: {config_flag_needed}")
111
+
112
+ # Format the server configuration
113
+ verbose("Formatting server configuration...")
114
+ server_config = format_server_config(
115
+ package_identifier,
116
+ collected_config_values,
117
+ api_key,
118
+ config_flag_needed,
119
+ )
120
+ verbose(f"Formatted server config: {json.dumps(server_config.__dict__, indent=2)}")
121
+
122
+ # Read existing config from client
123
+ verbose(f"Installing for {target_client}...")
124
+ verbose(f"Reading configuration for client: {target_client}")
125
+ client_config = read_config(target_client)
126
+
127
+ # Get normalized server name to use as key
128
+ server_name = get_server_name(package_identifier)
129
+ verbose(f"Normalized server ID: {server_name}")
130
+
131
+ # Update client configuration with new server
132
+ verbose("Updating client configuration...")
133
+ if not isinstance(client_config.mcpServers, dict):
134
+ # Initialize if needed
135
+ client_config.mcpServers = {}
136
+
137
+ # Add the new server config
138
+ client_config.mcpServers[server_name] = server_config
139
+
140
+ # Write updated configuration
141
+ verbose("Writing updated configuration...")
142
+ write_config(client_config, target_client)
143
+ verbose("Configuration successfully written")
144
+
145
+ rprint(f"[green]{package_identifier} successfully installed for {target_client}[/green]")
146
+
147
+ # No prompt for client restart
148
+ verbose("Installation completed successfully")
149
+
150
+ except Exception as e:
151
+ verbose(f"Installation error: {str(e)}")
152
+ rprint(f"[red]Failed to install {package_identifier}[/red]")
153
+ rprint(f"[red]Error: {str(e)}[/red]")
154
+ raise
158
155
 
159
156
 
160
157
  @click.command("install")
@@ -164,19 +161,19 @@ async def install_mcp_server(
164
161
  @click.option("--api-key", type=click.STRING, help="Provide an API key for fetching saved configurations")
165
162
  def install(mcp_server: str, client: Optional[str], env_json: Optional[str], api_key: Optional[str]):
166
163
  """Install an AI mcp-server with optional configuration."""
167
- click.echo(f"Attempting to install {mcp_server}...")
164
+ verbose(f"Attempting to install {mcp_server}...")
168
165
  user_config = None
169
166
  if env_json:
170
167
  try:
171
168
  user_config = json.loads(env_json)
172
- click.echo(f"Using provided config: {user_config}")
169
+ verbose(f"Using provided config: {user_config}")
173
170
  except json.JSONDecodeError as e:
174
- click.echo(f"Error: Invalid JSON provided for --config: {e}", err=True)
171
+ verbose(f"Error: Invalid JSON provided for --config: {e}", err=True)
175
172
  return
176
173
 
177
174
  try:
178
175
  # Run the async installation process
179
176
  asyncio.run(install_mcp_server(mcp_server, client, user_config, api_key))
180
177
  except Exception as e:
181
- click.echo(f"Installation failed: {str(e)}", err=True)
178
+ verbose(f"Installation failed: {str(e)}", err=True)
182
179
  return 1
@@ -0,0 +1,36 @@
1
+ from cli.utils.logger import verbose
2
+ import click
3
+ import json
4
+ import sys
5
+ from ..utils.run_query_pid_by_packagename import query_pid_by_packagename
6
+
7
+
8
+ @click.command("query-pid")
9
+ @click.argument("package_names", type=click.STRING, nargs=-1, required=True)
10
+ @click.option("--json-output", is_flag=True, help="Output results in JSON format")
11
+ def query_pid(package_names, json_output):
12
+ """
13
+ Check if the processes for the specified package names are running.
14
+
15
+ PACKAGE_NAMES: One or more package names to check.
16
+ Returns the running status for each package name. If the --json-output option is used, outputs the result in JSON format.
17
+ """
18
+ try:
19
+ # Get the running status for each package name
20
+ status_dict = query_pid_by_packagename(list(package_names))
21
+
22
+ if json_output:
23
+ # Output results in JSON format
24
+ print(json.dumps(status_dict))
25
+ else:
26
+ # Output results in plain text format
27
+ for package_name, is_running in status_dict.items():
28
+ status = "Running" if is_running else "Not running"
29
+ verbose(f"Package name '{package_name}': {status}")
30
+
31
+ # Check if any process is running
32
+ any_running = any(status_dict.values())
33
+ exit(0 if any_running else 1)
34
+ except Exception as e:
35
+ print(f"Error occurred while executing query-pid command: {e}", file=sys.stderr)
36
+ exit(1) # Return 1 to indicate an error
cli/commands/run.py CHANGED
@@ -3,7 +3,7 @@ import json
3
3
  import asyncio
4
4
  from typing import Dict, Any, Optional
5
5
 
6
- from rich import print as rprint
6
+ from rich import print as verbose
7
7
  from rich.console import Console
8
8
 
9
9
  from ..utils.logger import verbose
@@ -91,8 +91,8 @@ async def run_server(
91
91
  # Inform about remote server if applicable
92
92
  # check_and_notify_remote_server(resolved_server)
93
93
 
94
- rprint(f"[blue][Runner] Connecting to server:[/blue] {resolved_server.qualifiedName}")
95
- rprint(f"Connection types: {[c.type for c in resolved_server.connections]}")
94
+ verbose(f"[blue][Runner] Connecting to server:[/blue] {resolved_server.qualifiedName}")
95
+ verbose(f"Connection types: {[c.type for c in resolved_server.connections]}")
96
96
 
97
97
  # Assume analytics is disabled for now
98
98
  analytics_enabled = False
@@ -105,7 +105,7 @@ async def run_server(
105
105
  analytics_enabled
106
106
  )
107
107
  except Exception as e:
108
- rprint(f"[red][Runner] Fatal error:[/red] {str(e)}")
108
+ verbose(f"[red][Runner] Fatal error:[/red] {str(e)}")
109
109
  raise
110
110
 
111
111
 
@@ -115,18 +115,18 @@ async def run_server(
115
115
  @click.option("--api-key", type=click.STRING, help="API key for retrieving saved configuration")
116
116
  def run(mcp_server: str, config_json: Optional[str], api_key: Optional[str]):
117
117
  """Run an AI MCP server."""
118
- click.echo(f"Attempting to run {mcp_server}...")
118
+ verbose(f"Attempting to run {mcp_server}...")
119
119
  server_config = None
120
120
 
121
121
  # Parse command line provided configuration
122
122
  if config_json:
123
123
  try:
124
+ verbose(config_json)
124
125
  server_config = json.loads(config_json)
125
- click.echo(f"Using provided config: {server_config}")
126
+ verbose(f"Using provided config: {server_config}")
126
127
  except json.JSONDecodeError as e:
127
- click.echo(f"Error: Invalid JSON provided for --config: {e}", err=True)
128
+ verbose(f"Error: Invalid JSON provided for --config: {e}")
128
129
  return 1
129
-
130
130
  # If no config provided, use empty dict
131
131
  if server_config is None:
132
132
  verbose("No config provided, running with empty config")
@@ -135,8 +135,6 @@ def run(mcp_server: str, config_json: Optional[str], api_key: Optional[str]):
135
135
  if api_key:
136
136
  verbose(f"API key provided: {'*' * len(api_key)}")
137
137
 
138
- console = Console()
139
-
140
138
  try:
141
139
  # with console.status(f"Starting {mcp_server}...", spinner="dots") as status:
142
140
  # Run the server asynchronously
@@ -144,5 +142,5 @@ def run(mcp_server: str, config_json: Optional[str], api_key: Optional[str]):
144
142
  asyncio.run(run_server(mcp_server, server_config, api_key))
145
143
  # status.update(f"Successfully started {mcp_server}")
146
144
  except Exception as e:
147
- click.echo(f"Run failed: {str(e)}", err=True)
145
+ verbose(f"Run failed: {str(e)}")
148
146
  return 1
cli/main.py CHANGED
@@ -1,12 +1,16 @@
1
1
  import click
2
2
  from .commands.install import install
3
3
  from .commands.run import run
4
+ from .commands.query_pid import query_pid
5
+
4
6
 
5
7
  @click.group()
6
- @click.version_option(version="1.0.0", package_name="py-cli") # Corresponds to program.version("1.0.0")
8
+ @click.version_option(version="1.0.0", package_name="py-cli") # Corresponds to program.version("1.0.0")
7
9
  def cli():
8
10
  """A custom CLI tool translated to Python."""
9
11
  pass
10
12
 
13
+
11
14
  cli.add_command(install)
12
- cli.add_command(run)
15
+ cli.add_command(run)
16
+ cli.add_command(query_pid)