Skip to content

Commit c46b373

Browse files
committed
use logger to print in run
1 parent 39a8515 commit c46b373

File tree

3 files changed

+59
-83
lines changed

3 files changed

+59
-83
lines changed

src/mcpm/commands/profile/run.py

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@
44
import logging
55

66
import click
7-
from rich.console import Console
87

98
from mcpm.fastmcp_integration.proxy import create_mcpm_proxy
109
from mcpm.profile.profile_config import ProfileConfigManager
1110
from mcpm.utils.config import DEFAULT_PORT
1211

13-
console = Console()
1412
profile_config_manager = ProfileConfigManager()
1513
logger = logging.getLogger(__name__)
1614

@@ -37,10 +35,8 @@ async def find_available_port(preferred_port, max_attempts=10):
3735
async def run_profile_fastmcp(profile_servers, profile_name, debug=False, http_mode=False, port=DEFAULT_PORT):
3836
"""Run profile servers using FastMCP proxy for proper aggregation."""
3937
server_count = len(profile_servers)
40-
if debug:
41-
debug_console = Console(stderr=True)
42-
debug_console.print(f"[dim]Using FastMCP proxy to aggregate {server_count} server(s)[/]")
43-
debug_console.print(f"[dim]Mode: {'HTTP' if http_mode else 'stdio'}[/]")
38+
logger.debug(f"Using FastMCP proxy to aggregate {server_count} server(s)")
39+
logger.debug(f"Mode: {'HTTP' if http_mode else 'stdio'}")
4440

4541
try:
4642
# Create FastMCP proxy for profile servers
@@ -50,9 +46,7 @@ async def run_profile_fastmcp(profile_servers, profile_name, debug=False, http_m
5046
stdio_mode=not http_mode, # stdio_mode=False for HTTP
5147
)
5248

53-
if debug:
54-
debug_console = Console(stderr=True)
55-
debug_console.print(f"[dim]FastMCP proxy initialized with: {[s.name for s in profile_servers]}[/]")
49+
logger.debug(f"FastMCP proxy initialized with: {[s.name for s in profile_servers]}")
5650

5751
# Record profile usage
5852
from mcpm.commands.usage import record_profile_usage
@@ -64,15 +58,9 @@ async def run_profile_fastmcp(profile_servers, profile_name, debug=False, http_m
6458
actual_port = await find_available_port(port)
6559
if actual_port != port:
6660
logger.warning(f"Port {port} is busy, using port {actual_port} instead")
67-
if debug:
68-
debug_console = Console(stderr=True)
69-
debug_console.print(f"[yellow]Port {port} is busy, using port {actual_port} instead[/]")
7061

7162
logger.info(f"Starting profile '{profile_name}' on HTTP port {actual_port}")
72-
if debug:
73-
debug_console = Console(stderr=True)
74-
debug_console.print(f"[cyan]Starting profile '{profile_name}' on HTTP port {actual_port}...[/]")
75-
debug_console.print("[yellow]Press Ctrl+C to stop the profile.[/]")
63+
logger.info("Press Ctrl+C to stop the profile.")
7664

7765
# Run the aggregated proxy over HTTP
7866
await proxy.run_streamable_http_async(host="127.0.0.1", port=actual_port)
@@ -85,14 +73,9 @@ async def run_profile_fastmcp(profile_servers, profile_name, debug=False, http_m
8573

8674
except KeyboardInterrupt:
8775
logger.info("Profile execution interrupted")
88-
if debug:
89-
debug_console = Console(stderr=True)
90-
debug_console.print("\n[yellow]Profile execution interrupted[/]")
9176
return 130
9277
except Exception as e:
9378
logger.error(f"Error running profile '{profile_name}': {e}")
94-
# For errors, still use console.print as we need to show the error to user
95-
console.print(f"[red]Error running profile '{profile_name}': {e}[/]")
9679
return 1
9780

9881

@@ -110,15 +93,15 @@ def run(profile_name, debug, http, port):
11093
11194
Examples:
11295
113-
\\b
96+
\b
11497
mcpm profile run web-dev # Run over stdio (default)
11598
mcpm profile run --http web-dev # Run over HTTP on port 8000
11699
mcpm profile run --http --port 9000 ai # Run over HTTP on port 9000
117100
mcpm profile run --debug --http web-dev # Debug + HTTP mode
118101
"""
119102
# Validate profile name
120103
if not profile_name or not profile_name.strip():
121-
console.print("[red]Error: Profile name cannot be empty[/]")
104+
logger.error("Profile name cannot be empty")
122105
return 1
123106

124107
profile_name = profile_name.strip()
@@ -127,41 +110,39 @@ def run(profile_name, debug, http, port):
127110
try:
128111
profile_servers = profile_config_manager.get_profile(profile_name)
129112
if profile_servers is None:
130-
console.print(f"[red]Error: Profile '[bold]{profile_name}[/]' not found[/]")
131-
console.print()
132-
console.print("[yellow]Available options:[/]")
133-
console.print(" • Run 'mcpm profile ls' to see available profiles")
134-
console.print(" • Run 'mcpm profile create {name}' to create a profile")
113+
logger.error(f"Profile '{profile_name}' not found")
114+
logger.info("Available options:")
115+
logger.info(" • Run 'mcpm profile ls' to see available profiles")
116+
logger.info(" • Run 'mcpm profile create {name}' to create a profile")
135117
return 1
136118
except Exception as e:
137-
console.print(f"[red]Error accessing profile '{profile_name}': {e}[/]")
119+
logger.error(f"Error accessing profile '{profile_name}': {e}")
138120
return 1
139121

140122
if not profile_servers:
141-
console.print(f"[yellow]Profile '[bold]{profile_name}[/]' has no servers configured[/]")
142-
console.print()
143-
console.print("[dim]Add servers to this profile with:[/]")
144-
console.print(f" mcpm profile edit {profile_name}")
123+
logger.warning(f"Profile '{profile_name}' has no servers configured")
124+
logger.info("Add servers to this profile with:")
125+
logger.info(f" mcpm profile edit {profile_name}")
145126
return 0
146127

147128
logger.info(f"Running profile '{profile_name}' with {len(profile_servers)} server(s)")
148129

130+
if debug:
131+
logging.basicConfig(level=logging.DEBUG)
132+
149133
# Only show visual output in debug mode or HTTP mode
150134
if debug or http:
151-
debug_console = Console(stderr=True)
152-
debug_console.print(f"[bold green]Running profile '[cyan]{profile_name}[/]' with {len(profile_servers)} server(s)[/]")
135+
logger.info(f"Running profile '{profile_name}' with {len(profile_servers)} server(s)")
153136

154137
if debug:
155-
debug_console.print("[dim]Servers to run:[/]")
138+
logger.debug("Servers to run:")
156139
for server_config in profile_servers:
157-
debug_console.print(f" - {server_config.name}: {server_config}")
140+
logger.debug(f" - {server_config.name}: {server_config}")
158141

159142
# Use FastMCP proxy for all cases (single or multiple servers)
160-
if debug:
161-
debug_console = Console(stderr=True)
162-
debug_console.print(f"[dim]Using FastMCP proxy for {len(profile_servers)} server(s)[/]")
163-
if http:
164-
debug_console.print(f"[dim]HTTP mode on port {port}[/]")
143+
logger.debug(f"Using FastMCP proxy for {len(profile_servers)} server(s)")
144+
if http:
145+
logger.debug(f"HTTP mode on port {port}")
165146

166147
# Run the async function
167148
return asyncio.run(run_profile_fastmcp(profile_servers, profile_name, debug, http_mode=http, port=port))

src/mcpm/commands/run.py

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@
77
import sys
88

99
import click
10-
from rich.console import Console
1110

1211
from mcpm.global_config import GlobalConfigManager
1312
from mcpm.fastmcp_integration.proxy import create_mcpm_proxy
1413

15-
console = Console()
1614
global_config_manager = GlobalConfigManager()
1715
logger = logging.getLogger(__name__)
1816

@@ -29,7 +27,6 @@ def execute_server_command(server_config, server_name):
2927
"""Execute a server command with proper environment setup."""
3028
if not server_config:
3129
logger.error(f"Invalid server configuration for '{server_name}'")
32-
console.print(f"[red]Invalid server configuration for '{server_name}'[/]")
3330
sys.exit(1)
3431

3532
# Get command and args from the server config
@@ -38,7 +35,6 @@ def execute_server_command(server_config, server_name):
3835

3936
if not command:
4037
logger.error(f"Invalid command format for server '{server_name}'")
41-
console.print(f"[red]Invalid command format for server '{server_name}'[/]")
4238
sys.exit(1)
4339

4440
# Build the full command list
@@ -76,16 +72,14 @@ def execute_server_command(server_config, server_name):
7672

7773
except FileNotFoundError:
7874
logger.error(f"Command not found: {full_command[0]}")
79-
console.print(f"[red]Command not found: {full_command[0]}[/]")
80-
console.print(f"[yellow]Make sure the required runtime is installed[/]")
75+
logger.warning("Make sure the required runtime is installed")
8176
sys.exit(1)
8277
except KeyboardInterrupt:
8378
logger.info("Server execution interrupted")
84-
console.print("\n[yellow]Server execution interrupted[/]")
79+
logger.warning("\nServer execution interrupted")
8580
sys.exit(130)
8681
except Exception as e:
8782
logger.error(f"Error running server '{server_name}': {e}")
88-
console.print(f"[red]Error running server '{server_name}': {e}[/]")
8983
sys.exit(1)
9084

9185

@@ -104,15 +98,13 @@ async def run_server_with_fastmcp(server_config, server_name, http_mode=False, p
10498
)
10599

106100
if http_mode:
107-
logger.info(f"Starting server '{server_name}' on HTTP port {port}")
108-
console.print(f"[cyan]Starting server '{server_name}' on HTTP port {port}...[/]")
109-
console.print("[yellow]Press Ctrl+C to stop the server.[/]")
101+
logger.info(f"Starting server '{server_name}' on HTTP port {port}...")
102+
logger.info("Press Ctrl+C to stop the server.")
110103

111104
# Try to find an available port if the requested one is taken
112105
actual_port = await find_available_port(port)
113106
if actual_port != port:
114107
logger.warning(f"Port {port} is busy, using port {actual_port} instead")
115-
console.print(f"[yellow]Port {port} is busy, using port {actual_port} instead[/]")
116108

117109
# Run FastMCP proxy in HTTP mode
118110
await proxy.run_streamable_http_async(host="127.0.0.1", port=actual_port)
@@ -126,11 +118,10 @@ async def run_server_with_fastmcp(server_config, server_name, http_mode=False, p
126118
except KeyboardInterrupt:
127119
logger.info("Server execution interrupted")
128120
if http_mode:
129-
console.print("\\n[yellow]Server execution interrupted[/]")
121+
logger.warning("\nServer execution interrupted")
130122
return 130
131123
except Exception as e:
132124
logger.error(f"Error running server '{server_name}': {e}")
133-
console.print(f"[red]Error running server '{server_name}': {e}[/]")
134125
return 1
135126

136127

@@ -174,7 +165,7 @@ def run(server_name, http, port):
174165
"""
175166
# Validate server name
176167
if not server_name or not server_name.strip():
177-
console.print("[red]Error: Server name cannot be empty[/]")
168+
logger.error("Error: Server name cannot be empty")
178169
sys.exit(1)
179170

180171
server_name = server_name.strip()
@@ -183,23 +174,22 @@ def run(server_name, http, port):
183174
server_config, location = find_installed_server(server_name)
184175

185176
if not server_config:
186-
console.print(f"[red]Error: Server '[bold]{server_name}[/]' not found[/]")
187-
console.print()
188-
console.print("[yellow]Available options:[/]")
189-
console.print(" • Run 'mcpm ls' to see installed servers")
190-
console.print(" • Run 'mcpm search {name}' to find available servers")
191-
console.print(" • Run 'mcpm install {name}' to install a server")
177+
logger.error(f"Error: Server '{server_name}' not found")
178+
logger.warning("Available options:")
179+
logger.info(" • Run 'mcpm ls' to see installed servers")
180+
logger.info(" • Run 'mcpm search {name}' to find available servers")
181+
logger.info(" • Run 'mcpm install {name}' to install a server")
192182
sys.exit(1)
193183

194184
# Show debug info in verbose mode or if MCPM_DEBUG is set
195185
debug = os.getenv("MCPM_DEBUG", "").lower() in ("1", "true", "yes")
196186
if debug:
197-
debug_console = Console(file=sys.stderr)
198-
debug_console.print(f"[dim]Running server '{server_name}' from {location} configuration[/]")
199-
debug_console.print(f"[dim]Command: {server_config.command} {' '.join(server_config.args or [])}[/]")
200-
debug_console.print(f"[dim]Mode: {'HTTP' if http else 'stdio'}[/]")
187+
logging.basicConfig(level=logging.DEBUG)
188+
logger.debug(f"Running server '{server_name}' from {location} configuration")
189+
logger.debug(f"Command: {server_config.command} {' '.join(server_config.args or [])}")
190+
logger.debug(f"Mode: {'HTTP' if http else 'stdio'}")
201191
if http:
202-
debug_console.print(f"[dim]Port: {port}[/]")
192+
logger.debug(f"Port: {port}")
203193

204194
# Choose execution method
205195
if http:

tests/test_run.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def test_run_server_success(tmp_path):
5555
mock_usage.assert_called_once_with("test-server", "run")
5656

5757

58-
def test_run_server_not_found(tmp_path):
58+
def test_run_server_not_found(tmp_path, caplog):
5959
"""Test running non-existent server from global configuration"""
6060
# Setup temporary global config
6161
global_config_path = tmp_path / "servers.json"
@@ -67,9 +67,12 @@ def test_run_server_not_found(tmp_path):
6767
result = runner.invoke(run, ["non-existent-server"])
6868

6969
assert result.exit_code == 1
70-
assert "Server 'non-existent-server' not found" in result.output
71-
assert "mcpm ls" in result.output
72-
assert "mcpm install" in result.output
70+
71+
assert len(caplog.records) == 2
72+
assert caplog.records[0].levelname == "ERROR"
73+
assert "Error: Server 'non-existent-server' not found" in caplog.records[0].message
74+
assert caplog.records[1].levelname == "WARNING"
75+
assert "Available options:" in caplog.records[1].message
7376

7477

7578
def test_run_server_with_debug(tmp_path):
@@ -104,7 +107,7 @@ def test_run_server_with_debug(tmp_path):
104107
# We can't easily separate them in this test context
105108

106109

107-
def test_run_server_keyboard_interrupt(tmp_path):
110+
def test_run_server_keyboard_interrupt(tmp_path, caplog):
108111
"""Test server execution interrupted by keyboard"""
109112
# Setup temporary global config
110113
global_config_path = tmp_path / "servers.json"
@@ -129,10 +132,11 @@ def test_run_server_keyboard_interrupt(tmp_path):
129132
result = runner.invoke(run, ["interrupt-server"])
130133

131134
assert result.exit_code == 130
132-
assert "Server execution interrupted" in result.output
135+
assert "Server execution interrupted" in caplog.text
136+
133137

134138

135-
def test_run_server_command_not_found(tmp_path):
139+
def test_run_server_command_not_found(tmp_path, caplog):
136140
"""Test server execution with non-existent command"""
137141
# Setup temporary global config
138142
global_config_path = tmp_path / "servers.json"
@@ -157,8 +161,9 @@ def test_run_server_command_not_found(tmp_path):
157161
result = runner.invoke(run, ["missing-cmd-server"])
158162

159163
assert result.exit_code == 1
160-
assert "Command not found: nonexistent-command" in result.output
161-
assert "Make sure the required runtime is installed" in result.output
164+
assert "Command not found: nonexistent-command" in caplog.text
165+
assert "Make sure the required runtime is installed" in caplog.text
166+
162167

163168

164169
def test_run_server_with_cwd(tmp_path):
@@ -194,25 +199,25 @@ def test_run_server_with_cwd(tmp_path):
194199
assert call_args[1]['cwd'] is None
195200

196201

197-
def test_run_empty_server_name():
202+
def test_run_empty_server_name(caplog):
198203
"""Test running with empty server name"""
199204
runner = CliRunner()
200205
result = runner.invoke(run, [""])
201206

202207
assert result.exit_code == 1
203-
assert "Server name cannot be empty" in result.output
208+
assert "Error: Server name cannot be empty" in caplog.text
204209

205210

206-
def test_run_whitespace_server_name():
211+
def test_run_whitespace_server_name(caplog):
207212
"""Test running with whitespace-only server name"""
208213
runner = CliRunner()
209214
result = runner.invoke(run, [" "])
210215

211216
assert result.exit_code == 1
212-
assert "Server name cannot be empty" in result.output
217+
assert "Error: Server name cannot be empty" in caplog.text
213218

214219

215-
def test_run_server_no_command(tmp_path):
220+
def test_run_server_no_command(tmp_path, caplog):
216221
"""Test server with missing command field"""
217222
# Setup temporary global config
218223
global_config_path = tmp_path / "servers.json"
@@ -242,4 +247,4 @@ def test_run_server_no_command(tmp_path):
242247
result = runner.invoke(run, ["broken-server"])
243248

244249
assert result.exit_code == 1
245-
assert "Invalid command format for server 'broken-server'" in result.output
250+
assert "Invalid command format for server 'broken-server'" in caplog.text

0 commit comments

Comments
 (0)