Skip to main content
Glama
main.py10.4 kB
""" Command-line interface for the Python Debugging MCP Tool. Provides commands to interact with debug sessions, set breakpoints, and inspect local variables. """ import json import sys from pathlib import Path from typing import Optional import typer from rich.console import Console from rich.table import Table app = typer.Typer( name="mcp-debug", help="Python Debugging MCP Tool - Debug Python code via breakpoints", ) console = Console() @app.command("start-session") def start_session( entry: str = typer.Argument(..., help="Project-relative path to Python script"), args: Optional[list[str]] = typer.Option( None, "--arg", help="Command-line arguments for the script" ), env: Optional[list[str]] = typer.Option( None, "--env", help="Environment variables (KEY=VALUE format)" ), python_path: Optional[str] = typer.Option( None, "--python-path", help="Path to Python interpreter" ), output_format: str = typer.Option( "json", "--format", "-f", help="Output format: json or table" ), ) -> None: """ Start a new debug session. Example: mcp-debug start-session src/main.py mcp-debug start-session tests/test.py --arg --verbose --env DEBUG=true """ from mcp_debug_tool.schemas import StartSessionRequest from mcp_debug_tool.sessions import SessionManager # Parse environment variables env_dict = {} if env: for env_var in env: if "=" in env_var: key, value = env_var.split("=", 1) env_dict[key] = value else: console.print(f"[red]Invalid env format: {env_var}. Use KEY=VALUE[/red]") raise typer.Exit(1) # Create request request = StartSessionRequest( entry=entry, args=args or None, env=env_dict if env_dict else None, pythonPath=python_path, ) # Create session manager workspace_root = Path.cwd() session_manager = SessionManager(workspace_root) try: response = session_manager.create_session(request) if output_format == "json": console.print_json(data={"sessionId": response.sessionId}) else: table = Table(title="Session Created") table.add_column("Session ID", style="cyan") table.add_row(response.sessionId) console.print(table) except Exception as e: console.print(f"[red]Error: {e}[/red]") raise typer.Exit(1) @app.command("run-to-breakpoint") def run_to_breakpoint( session_id: str = typer.Argument(..., help="Session ID"), file: str = typer.Argument(..., help="Project-relative file path"), line: int = typer.Argument(..., help="Line number (1-based)"), output_format: str = typer.Option( "json", "--format", "-f", help="Output format: json or table" ), ) -> None: """ Run to a breakpoint and capture local variables. Example: mcp-debug run-to-breakpoint session-123 src/main.py 15 mcp-debug run-to-breakpoint session-123 src/main.py 15 --format table """ from mcp_debug_tool.schemas import BreakpointRequest from mcp_debug_tool.sessions import SessionManager workspace_root = Path.cwd() session_manager = SessionManager(workspace_root) request = BreakpointRequest(file=file, line=line) try: response = session_manager.run_to_breakpoint(session_id, request) if output_format == "json": console.print_json(data=response.model_dump()) else: _print_breakpoint_table(response) except Exception as e: console.print(f"[red]Error: {e}[/red]") raise typer.Exit(1) @app.command("continue") def continue_execution( session_id: str = typer.Argument(..., help="Session ID"), file: str = typer.Argument(..., help="Project-relative file path"), line: int = typer.Argument(..., help="Line number (1-based)"), output_format: str = typer.Option( "json", "--format", "-f", help="Output format: json or table" ), ) -> None: """ Continue execution to the next breakpoint. Example: mcp-debug continue session-123 src/main.py 25 mcp-debug continue session-123 src/main.py 25 --format table """ from mcp_debug_tool.schemas import BreakpointRequest from mcp_debug_tool.sessions import SessionManager workspace_root = Path.cwd() session_manager = SessionManager(workspace_root) request = BreakpointRequest(file=file, line=line) try: response = session_manager.continue_execution(session_id, request) if output_format == "json": console.print_json(data=response.model_dump()) else: _print_continue_table(response) except Exception as e: console.print(f"[red]Error: {e}[/red]") raise typer.Exit(1) @app.command("state") def get_state( session_id: str = typer.Argument(..., help="Session ID"), output_format: str = typer.Option( "json", "--format", "-f", help="Output format: json or table" ), ) -> None: """ Get the current state of a debug session. Example: mcp-debug state session-123 mcp-debug state session-123 --format table """ from mcp_debug_tool.sessions import SessionManager workspace_root = Path.cwd() session_manager = SessionManager(workspace_root) try: response = session_manager.get_state(session_id) if output_format == "json": console.print_json(data=response.model_dump()) else: _print_state_table(response) except Exception as e: console.print(f"[red]Error: {e}[/red]") raise typer.Exit(1) @app.command("end") def end_session( session_id: str = typer.Argument(..., help="Session ID"), output_format: str = typer.Option( "json", "--format", "-f", help="Output format: json or table" ), ) -> None: """ End a debug session. Example: mcp-debug end session-123 """ from mcp_debug_tool.sessions import SessionManager workspace_root = Path.cwd() session_manager = SessionManager(workspace_root) try: response = session_manager.end_session(session_id) if output_format == "json": console.print_json(data={"ended": response.ended}) else: if response.ended: console.print("[green]✓ Session ended successfully[/green]") else: console.print("[yellow]Session end status unclear[/yellow]") except Exception as e: console.print(f"[red]Error: {e}[/red]") raise typer.Exit(1) def _print_breakpoint_table(response) -> None: """Print breakpoint response as a table.""" table = Table(title="Breakpoint Result") # Status table.add_column("Field", style="cyan") table.add_column("Value", style="magenta") table.add_row("Hit", "✓ Yes" if response.hit else "✗ No") table.add_row("Completed", "✓ Yes" if response.completed else "✗ No") if response.frameInfo: table.add_row("Frame File", response.frameInfo.file) table.add_row("Frame Line", str(response.frameInfo.line)) if response.error: table.add_row("Error Type", response.error.type) table.add_row("Error Message", response.error.message) console.print(table) # Print locals if available if response.locals: locals_table = Table(title="Local Variables") locals_table.add_column("Name", style="cyan") locals_table.add_column("Type", style="green") locals_table.add_column("Value", style="yellow") locals_table.add_column("Truncated", style="red") for name, value in response.locals.items(): locals_table.add_row( name, value.get("type", "unknown"), value.get("repr", ""), "✓" if value.get("isTruncated", False) else "✗", ) console.print(locals_table) def _print_continue_table(response) -> None: """Print continue response as a table.""" table = Table(title="Continue Result") table.add_column("Field", style="cyan") table.add_column("Value", style="magenta") table.add_row("Hit", "✓ Yes" if response.hit else "✗ No") table.add_row("Completed", "✓ Yes" if response.completed else "✗ No") if response.frameInfo: table.add_row("Frame File", response.frameInfo.file) table.add_row("Frame Line", str(response.frameInfo.line)) if response.error: table.add_row("Error Type", response.error.type) table.add_row("Error Message", response.error.message) console.print(table) # Print locals if available if response.locals: locals_table = Table(title="Local Variables") locals_table.add_column("Name", style="cyan") locals_table.add_column("Type", style="green") locals_table.add_column("Value", style="yellow") for name, value in response.locals.items(): locals_table.add_row( name, value.get("type", "unknown"), value.get("repr", ""), ) console.print(locals_table) def _print_state_table(response) -> None: """Print state response as a table.""" table = Table(title="Session State") table.add_column("Field", style="cyan") table.add_column("Value", style="magenta") table.add_row("Status", response.status) if response.lastBreakpoint: table.add_row("Last BP File", response.lastBreakpoint.file) table.add_row("Last BP Line", str(response.lastBreakpoint.line)) table.add_row("Last BP Hit Count", str(response.lastBreakpoint.hitCount)) if response.timings: if response.timings.lastRunMs is not None: table.add_row("Last Run (ms)", f"{response.timings.lastRunMs:.2f}") table.add_row("Total CPU Time (ms)", f"{response.timings.totalCpuTimeMs:.2f}") console.print(table) if __name__ == "__main__": app()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Kaina3/Debug-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server