import sys
import pexpect
from fastmcp import FastMCP
mcp = FastMCP("GDB-MCP-Server")
class GDBManager:
def __init__(self):
self.child = None
self.timeout_message = "[MCP Info] Execution timed out (likely running)."
def start(self, command="gdb"):
if self.child and self.child.isalive():
self.child.close()
try:
self.child = pexpect.spawn(command, encoding='utf-8', timeout=5)
try:
self.child.expect([r'\(gdb\)', r'pwndbg>', r'gef>', r'gdb-peda\$', r'\$'], timeout=5)
startup_msg = self.child.before
except pexpect.TIMEOUT:
startup_msg = self.child.before if self.child.before else "GDB started (no prompt detected yet)"
init_cmds = [
"set pagination off",
"set confirm off",
"set width 0",
"set height 0"
]
for cmd in init_cmds:
self.child.sendline(cmd)
try:
self.child.expect([r'\(gdb\)', r'pwndbg>', r'gef>', r'gdb-peda\$', r'\$'], timeout=1)
except pexpect.TIMEOUT:
pass
return f"GDB Started successfully.\nCommand: {command}\n\nInitial Output:\n{startup_msg}"
except Exception as e:
if self.child:
self.child.close()
self.child = None
return f"Failed to start GDB: {str(e)}"
def execute(self, cmd, timeout=10):
if not self.child or not self.child.isalive():
return "Error: GDB is not running. Please use start_debugging first."
self.child.sendline(cmd)
try:
index = self.child.expect([r'\(gdb\)', r'pwndbg>', r'gef>', r'gdb-peda\$', r'\$'], timeout=timeout)
output = self.child.before
return output
except pexpect.TIMEOUT:
current_output = self.child.before if self.child.before else ""
return f"{current_output}\n\n{self.timeout_message}"
except Exception as e:
return f"Error executing command: {str(e)}"
def interrupt(self):
if not self.child or not self.child.isalive():
return "Error: GDB not running"
self.child.sendintr()
try:
self.child.expect([r'\(gdb\)', r'pwndbg>', r'gef>', r'gdb-peda\$', r'\$'], timeout=2)
return f"Interrupted.\n{self.child.before}"
except pexpect.TIMEOUT:
return "Signal sent, but GDB prompt did not appear immediately."
def stop(self):
if self.child:
self.child.close()
self.child = None
return "GDB Session ended."
gdb = GDBManager()
@mcp.tool()
def run_shell_command(command: str, timeout: int = 10):
try:
import subprocess
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True,
timeout=timeout
)
output = f"Command: {command}\n"
output += f"Exit Code: {result.returncode}\n\n"
if result.stdout:
output += f"STDOUT:\n{result.stdout}\n"
if result.stderr:
output += f"STDERR:\n{result.stderr}\n"
return output.strip()
except subprocess.TimeoutExpired as e:
output = f"Command: {command}\n"
output += f"Error: Execution timed out after {timeout} seconds.\n"
if e.stdout:
output += f"\nPartial STDOUT:\n{e.stdout.decode('utf-8', errors='ignore')}\n"
if e.stderr:
output += f"\nPartial STDERR:\n{e.stderr.decode('utf-8', errors='ignore')}\n"
return output
except Exception as e:
return f"Error executing shell command: {str(e)}"
@mcp.tool()
def start_debugging(command: str = "gdb"):
return gdb.start(command)
@mcp.tool()
def send_gdb_command(command: str, timeout: int = 10):
return gdb.execute(command, timeout)
@mcp.tool()
def interrupt():
return gdb.interrupt()
@mcp.tool()
def stop_debugging():
return gdb.stop()
if __name__ == "__main__":
mcp.run(transport="sse")