A Python debugging tool that exposes breakpoint-based debugging capabilities through a clean API and CLI, designed for integration with AI assistants and development tools.
English | 日本語
- Advanced Debugging via DAP: Production-ready debugging using Microsoft's debugpy
- Breakpoint Debugging: Set breakpoints and inspect local variables at runtime
- Step Execution: True step-in, step-over, step-out operations
- No Corruption: Isolated process execution prevents sys.modules issues
- Environment-aware: Automatically uses target project's Python interpreter
- Session Management: Isolated debug sessions with timeout protection
- Dual Interface:
- CLI: Interactive debugging with beautiful table output
- MCP Server: Official MCP SDK-based integration for AI assistants
- Safe Execution: Sandboxed subprocess execution with configurable limits
- Type Safety: Pydantic v2 schemas for request/response validation
- Async Support: Built on MCP SDK with full async/await support
- Comprehensive Testing: 254 tests (119 unit + 122 integration + 13 exploration) covering DAP workflows, session management, and edge cases
- Legacy Compatibility: Optional bdb mode for backward compatibility
# Clone repository
git clone https://github.com/your-org/Debug-MCP.git
cd Debug-MCP
# Create virtual environment
uv venv
# Install with CLI support
uv pip install -e ".[cli]"To use this tool with GitHub Copilot in VS Code, set up the MCP server configuration.
See VS Code Setup Guide for detailed instructions.
Quick Setup (Using from Debug-MCP repository):
-
Create MCP config directory (macOS/Linux):
mkdir -p ~/Library/Application\ Support/Code/User/globalStorage/github.copilot-chat
-
Edit
mcp.jsonfile:{ "mcpServers": { "python-debug": { "command": "uv", "args": ["run", "mcp-debug-server", "--workspace", "${workspaceFolder}"], "env": {"PYTHONUNBUFFERED": "1"} } } } -
Restart VS Code
Using from Another Repository:
When using this tool from a different repository, specify the Debug-MCP installation path:
{
"mcpServers": {
"python-debug": {
"command": "uv",
"args": [
"--directory",
"/absolute/path/to/Debug-MCP",
"run",
"mcp-debug-server",
"--workspace",
"${workspaceFolder}"
],
"env": {
"PYTHONUNBUFFERED": "1"
}
}
}
}Replace /absolute/path/to/Debug-MCP with the actual path to your Debug-MCP installation.
Using Copilot Chat:
@workspace Set a breakpoint at line 42 in src/main.py and
show me the local variables at that point.
See mcp-config-example.json for a complete configuration example.
# Start a debug session
SESSION_ID=$(uv run mcp-debug start-session src/app.py | jq -r .sessionId)
# Run to breakpoint and inspect locals
uv run mcp-debug run-to-breakpoint $SESSION_ID src/app.py 42 --format table
# Continue to next breakpoint
uv run mcp-debug continue $SESSION_ID src/app.py 100 --format table
# Check session state
uv run mcp-debug state $SESSION_ID --format table
# End session
uv run mcp-debug end $SESSION_IDSee Quickstart Guide for more CLI examples.
from pathlib import Path
from mcp_debug_tool.sessions import SessionManager
from mcp_debug_tool.schemas import StartSessionRequest, BreakpointRequest
# Initialize
workspace = Path.cwd()
manager = SessionManager(workspace)
# Create session
req = StartSessionRequest(entry="src/main.py", args=["--verbose"])
session = manager.create_session(req)
# Run to breakpoint
bp_req = BreakpointRequest(file="src/main.py", line=15)
result = manager.run_to_breakpoint(session.sessionId, bp_req)
if result.hit:
print(f"Paused at {result.frameInfo.file}:{result.frameInfo.line}")
print(f"Locals: {result.locals}")
# Continue execution
continue_result = manager.continue_execution(
session.sessionId,
BreakpointRequest(file="src/main.py", line=42)
)
# Cleanup
manager.end_session(session.sessionId)- Timeout: 20 seconds per breakpoint operation (configurable)
- Output Capture: 10MB maximum per session
- Variable Depth: Max 2 levels of nesting in local variable inspection
- Collection Size: Max 50 items shown in lists/dicts
- String Length: Max 256 characters before truncation
- Path Validation: Only project-relative paths allowed (no
..traversal) - Subprocess Isolation: Debuggee runs in isolated subprocess
- Working Directory: Locked to workspace root
- No Network: Debuggee has no special network access (app code may still use network)
Debug-MCP now uses DAP (Debug Adapter Protocol) via debugpy for production debugging:
┌─────────────────────────────────────────────────┐
│ MCP Server (server.py) │
│ - Official MCP SDK (async) │
│ - Tool registration & routing │
└────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Session Manager (sessions.py) │
│ - Lifecycle management │
│ - DAP/bdb mode selection │
└────────────────┬────────────────────────────────┘
│
▼ (DAP mode - default)
┌─────────────────────────────────────────────────┐
│ DAPSyncWrapper (dap_wrapper.py) │
│ - Synchronous DAP interface │
│ - Event queue management │
│ - Timeout handling │
└────────────────┬────────────────────────────────┘
│ DAP Protocol (JSON-RPC)
▼
┌─────────────────────────────────────────────────┐
│ debugpy Server (separate process) │
│ - Microsoft's official DAP implementation │
│ - Handles breakpoints, stepping, variables │
│ - Manages target script execution │
└────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Target Python Script │
│ - Runs in isolated process │
│ - Full access to target dependencies │
│ - No sys.modules corruption │
└─────────────────────────────────────────────────┘
Why DAP (debugpy)?
- ✅ No sys.modules corruption - Runs in separate process
- ✅ True step execution - Maintains execution state across steps
- ✅ Automatic environment handling - Uses target Python interpreter
- ✅ Industry standard - Microsoft's battle-tested implementation
- ✅ Rich features - Step in/over/out, conditional breakpoints, watch expressions
- ✅ Future-proof - Easy to extend with advanced debugging features
Communication Flow:
- MCP Client (VS Code Copilot) → MCP Server (tool call)
- Server → SessionManager (sync method via async wrapper)
- SessionManager → DAPSyncWrapper (manages DAP session)
- DAPSyncWrapper ↔ debugpy Server (DAP protocol over socket)
- debugpy captures locals → DAPSyncWrapper → SessionManager → Server → Client
The bdb-based implementation is still available for compatibility (useDap=false):
SessionManager → runner_main.py (subprocess) → DebugController (bdb)
However, DAP is now the default and recommended for all use cases. The bdb mode has known issues:
- sys.modules corruption with multiple runs
- No true step execution (replay-based)
- Complex PYTHONPATH management
Active Files (Production):
- ✅
server.py- MCP SDK server - ✅
sessions.py- Session lifecycle management - ✅
dap_wrapper.py- DAP synchronous wrapper (PRIMARY) - ✅
dap_client.py- Low-level DAP protocol client (PRIMARY) - ✅
schemas.py- Pydantic models - ✅
utils.py- Variable repr helpers and path utilities
Legacy Files (Compatibility):
⚠️ debugger.py- bdb-based engine (legacy, useuseDap=false)⚠️ runner_main.py- bdb subprocess runner (legacy)
Removed Files:
- Old multiprocessing approach (removed 2025-10-30)runner.py
See docs/development.md for detailed setup instructions.
Quick commands:
# Run all tests (254 tests: 119 unit + 122 integration + 13 exploration)
uv run pytest
# Run only unit tests
uv run pytest tests/unit/
# Run only integration tests
uv run pytest tests/integration/
# Run tests with coverage
uv run pytest --cov=src/mcp_debug_tool --cov-report=html
# Lint
uv run ruff check .
# Format
uv run ruff format .
# Auto-fix lint issues
uv run ruff check --fix .Debug-MCP/
├── src/
│ ├── mcp_debug_tool/ # Core debugging engine
│ │ ├── server.py # MCP SDK-based server (v2.0+)
│ │ ├── sessions.py # Session management (DAP/bdb mode selection)
│ │ ├── dap_wrapper.py # DAP synchronous wrapper (PRIMARY)
│ │ ├── dap_client.py # DAP protocol client (PRIMARY)
│ │ ├── debugger.py # bdb-based debugger (LEGACY, use useDap=false)
│ │ ├── runner_main.py # bdb subprocess runner (LEGACY)
│ │ ├── schemas.py # Pydantic models
│ │ └── utils.py # Variable repr helpers
│ └── cli/
│ └── main.py # Typer CLI
├── tests/
│ ├── unit/ # Unit tests (debugger, schemas, DAP, sessions)
│ └── integration/ # Integration tests (DAP workflows, bdb compat)
├── specs/
│ └── 001-python-debug-tool/ # Specification documents
└── docs/ # Additional documentation
├── dap-phase*-*.md # DAP integration documentation
└── roadmap.md # Future enhancements
- VS Code Setup Guide - How to use MCP tool with VS Code Copilot ⭐
- Quickstart Guide - CLI and API usage examples
- Specification - Complete feature specification
- Data Model - Entity schemas and validation rules
- Research - Design decisions and rationale
- Development Guide - Setup and contribution guide
- Performance Tuning - Timeout and resource configuration
- Roadmap - Planned v2 features
v2.0 Released! DAP Integration Complete 🎉
- ✅ Phase 1: Foundation (Complete - 6/6 tests passing)
- ✅ Phase 2: Core Logic (Complete - 28/28 tests passing)
- ✅ Phase 3: Session Lifecycle (Complete - 29/29 tests passing)
- ✅ Phase 4: Breakpoint Operations (Complete - 41/41 tests passing)
- ✅ Phase 5: Error Visibility (Complete - 71/71 tests passing)
- ✅ Phase 6: MCP SDK Migration (Complete - SDK-based server with async support)
- ✅ Phase 7: DAP Integration (Complete - Production-ready debugpy integration)
What's New in v2.0:
- DAP (debugpy) is now the default - No more sys.modules corruption!
- True step execution - Step in, step over, step out all working
- Automatic environment handling - Uses target project's Python interpreter
- Industry-standard protocol - Microsoft's battle-tested implementation
- Enhanced reliability - Isolated process execution prevents crashes
- Backward compatible - Legacy bdb mode still available with
useDap=false
Migration from v1.x:
- Existing code works as-is (DAP is opt-in by default)
- To explicitly use bdb:
StartSessionRequest(entry="...", useDap=False) - Recommended: Let it default to DAP for best results
- Script entry only: No module (
python -m) or pytest target support (planned for v2.1) - Single-threaded: No support for multi-threaded debugging (planned for v2.1)
- Line breakpoints: Conditional breakpoints not yet exposed via MCP (DAP supports it)
✅ Resolved from v1:
No stepping→ Now available: Step in, step over, step outsys.modules corruption→ Fixed: DAP uses isolated processesPython environment mismatch→ Fixed: Uses target interpreter
See docs/roadmap.md for planned v2.1+ enhancements.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes with tests
- Run tests and linting (
uv run pytest && uv run ruff check .) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see LICENSE file for details
Built with:
- debugpy - Microsoft's Python debugger (DAP implementation)
- MCP SDK - Model Context Protocol Python SDK
- bdb/pdb - Python's standard debugger framework (legacy mode)
- Pydantic - Data validation using Python type annotations
- Typer - CLI framework built on Click
- Rich - Beautiful terminal formatting
- pytest - Testing framework