Skip to content

Commit bc442b0

Browse files
Improve log hygiene and interactions in deploy and configure commands (#572)
* Unify verbose logging configuration flags * Use context var to define unconditional verbose logger * Prune some extraneous logs
1 parent d6f1c98 commit bc442b0

File tree

16 files changed

+567
-205
lines changed

16 files changed

+567
-205
lines changed

LLMS.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1406,7 +1406,7 @@ Example usage:
14061406

14071407
### src/mcp_agent/cli/main.py
14081408

1409-
**Function:** `main(verbose: bool = typer.Option(False, '--verbose', '-v', help='Enable verbose mode'), quiet: bool = typer.Option(False, '--quiet', '-q', help='Disable output'), color: bool = typer.Option(True, '--color/--no-color', help='Enable/disable color output'))`
1409+
**Function:** `main(verbose: bool = typer.Option(False, '--verbose', '-v', help='Enable verbose mode'), color: bool = typer.Option(True, '--color/--no-color', help='Enable/disable color output'))`
14101410

14111411
- **Description**: Main entry point for the MCP Agent CLI.
14121412
- **Parameters**

docs/cli-reference.mdx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ Available for all commands:
2626
| Option | Description |
2727
| :----- | :---------- |
2828
| `--verbose, -v` | Enable verbose output |
29-
| `--quiet, -q` | Minimize output |
3029
| `--format <type>` | Output format (`text`, `json`, `yaml`) |
3130
| `--color/--no-color` | Enable/disable colored output |
3231
| `--version` | Show version and exit |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{"level":"INFO","timestamp":"2025-10-22T20:09:28.253383","namespace":"mcp_agent.core.context","message":"Configuring logger with level: debug"}
2+
{"level":"INFO","timestamp":"2025-10-22T20:09:28.257335","namespace":"mcp_agent.core.context","message":"Configuring logger with level: debug"}

src/mcp_agent/cli/cloud/commands/configure/main.py

Lines changed: 91 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
"""
66

77
from pathlib import Path
8+
from datetime import datetime, timezone
89
from typing import Optional, Union
10+
import json
911

1012
import typer
11-
from rich.panel import Panel
1213
from rich.progress import Progress, SpinnerColumn, TextColumn
1314

1415
from mcp_agent.cli.auth import load_api_key_credentials
@@ -35,10 +36,13 @@
3536
print_configuration_header,
3637
print_info,
3738
print_success,
39+
print_verbose,
40+
LOG_VERBOSE,
3841
)
3942

4043

4144
def configure_app(
45+
ctx: typer.Context,
4246
app_server_url: str = typer.Option(
4347
None,
4448
"--id",
@@ -84,6 +88,12 @@ def configure_app(
8488
help="API key for authentication. Defaults to MCP_API_KEY environment variable.",
8589
envvar=ENV_API_KEY,
8690
),
91+
verbose: bool = typer.Option(
92+
False,
93+
"--verbose",
94+
"-v",
95+
help="Enable verbose output for this command",
96+
),
8797
) -> str:
8898
"""Configure an MCP app with the required params (e.g. user secrets).
8999
@@ -98,6 +108,9 @@ def configure_app(
98108
Returns:
99109
Configured app ID.
100110
"""
111+
if verbose:
112+
LOG_VERBOSE.set(True)
113+
101114
# Check what params the app requires (doubles as an access check)
102115
if not app_server_url:
103116
raise CLIError("You must provide a server URL to configure.")
@@ -110,8 +123,7 @@ def configure_app(
110123

111124
client: Union[MockMCPAppClient, MCPAppClient]
112125
if dry_run:
113-
# Use the mock api client in dry run mode
114-
print_info("Using MOCK API client for dry run")
126+
print_verbose("Using MOCK API client for dry run")
115127
client = MockMCPAppClient(
116128
api_url=api_url or DEFAULT_API_BASE_URL, api_key=effective_api_key
117129
)
@@ -162,22 +174,18 @@ def configure_app(
162174

163175
if requires_secrets:
164176
if not secrets_file and secrets_output_file is None:
165-
# Set default output file if not specified
166177
secrets_output_file = Path(MCP_CONFIGURED_SECRETS_FILENAME)
167-
print_info(f"Using default output path: {secrets_output_file}")
168-
169-
print_configuration_header(secrets_file, secrets_output_file, dry_run)
178+
print_verbose(f"Using default output path: {secrets_output_file}")
170179

171-
print_info(
180+
print_verbose(
172181
f"App {app_server_url} requires the following ({len(required_params)}) user secrets: {', '.join(required_params)}"
173182
)
174183

175184
try:
176-
print_info("Processing user secrets...")
185+
print_verbose("Processing user secrets...")
177186

178187
if dry_run:
179-
# Use the mock client in dry run mode
180-
print_info("Using MOCK Secrets API client for dry run")
188+
print_verbose("Using MOCK Secrets API client for dry run")
181189

182190
# Create the mock client
183191
mock_client = MockSecretsClient(
@@ -210,10 +218,10 @@ def configure_app(
210218
)
211219
)
212220

213-
print_success("User secrets processed successfully")
221+
print_verbose("User secrets processed successfully")
214222

215223
except Exception as e:
216-
if settings.VERBOSE:
224+
if LOG_VERBOSE.get():
217225
import traceback
218226

219227
typer.echo(traceback.format_exc())
@@ -226,14 +234,35 @@ def configure_app(
226234
f"App {app_server_url} does not require any parameters, but a secrets file was provided: {secrets_file}"
227235
)
228236

237+
print_configuration_header(
238+
app_server_url,
239+
required_params if requires_secrets else [],
240+
secrets_file,
241+
secrets_output_file,
242+
dry_run,
243+
)
244+
245+
if not dry_run:
246+
proceed = typer.confirm("Proceed with configuration?", default=True)
247+
if not proceed:
248+
print_info("Configuration cancelled.")
249+
return None
250+
else:
251+
print_info("Running in dry run mode.")
252+
253+
start_time = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
254+
print_info(f"[{start_time}] Starting configuration process...", highlight=False)
255+
229256
if dry_run:
230257
print_success("Configuration completed in dry run mode.")
231258
return "dry-run-app-configuration-id"
232259

233-
# Finally, configure the app for the user
260+
config = None
261+
spinner_column = SpinnerColumn(spinner_name="aesthetic")
234262
with Progress(
235-
SpinnerColumn(spinner_name="arrow3"),
236-
TextColumn("[progress.description]{task.description}"),
263+
"",
264+
spinner_column,
265+
TextColumn(" [progress.description]{task.description}"),
237266
) as progress:
238267
task = progress.add_task("Configuring MCP App...", total=None)
239268

@@ -243,18 +272,52 @@ def configure_app(
243272
app_server_url=app_server_url, config_params=configured_secrets
244273
)
245274
)
246-
progress.update(task, description="✅ MCP App configured successfully!")
247-
console.print(
248-
Panel(
249-
f"Configured App ID: [cyan]{config.appConfigurationId}[/cyan]\n"
250-
f"Configured App Server URL: [cyan]{config.appServerInfo.serverUrl if config.appServerInfo else ''}[/cyan]",
251-
title="Configuration Complete",
252-
border_style="green",
253-
)
254-
)
255-
256-
return config.appConfigurationId
275+
spinner_column.spinner.frames = spinner_column.spinner.frames[-2:-1]
276+
progress.update(task, description="MCP App configured successfully!")
257277

258278
except Exception as e:
259279
progress.update(task, description="❌ MCP App configuration failed")
260-
raise CLIError(f"Failed to configure app {app_server_url}: {str(e)}") from e
280+
end_time = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
281+
raise CLIError(
282+
f"[{end_time}] Failed to configure app {app_server_url}: {str(e)}"
283+
) from e
284+
285+
# Print results after progress context ends
286+
end_time = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
287+
if config.app:
288+
print_info(
289+
f"[{end_time}] Configuration of '{config.app.name}' succeeded. ID: {config.appConfigurationId}",
290+
highlight=False,
291+
)
292+
else:
293+
print_info(
294+
f"[{end_time}] Configuration succeeded. ID: {config.appConfigurationId}",
295+
highlight=False,
296+
)
297+
298+
if config.appServerInfo:
299+
server_url = config.appServerInfo.serverUrl
300+
print_info(f"App Server URL: [link={server_url}]{server_url}[/link]")
301+
print_info(
302+
f"Use this configured app as an MCP server at {server_url}/sse\n\nMCP configuration example:"
303+
)
304+
305+
# Use the app name if available, otherwise use a simple default
306+
app_name = config.app.name if config.app else "configured-app"
307+
308+
mcp_config = {
309+
"mcpServers": {
310+
app_name: {
311+
"url": f"{server_url}/sse",
312+
"transport": "sse",
313+
"headers": {"Authorization": f"Bearer {effective_api_key}"},
314+
}
315+
}
316+
}
317+
318+
console.print(
319+
f"[bright_black]{json.dumps(mcp_config, indent=2)}[/bright_black]",
320+
soft_wrap=True,
321+
)
322+
323+
return config.appConfigurationId

0 commit comments

Comments
 (0)