Skip to main content
Glama
attach.py4.29 kB
import logging from typing import List, Optional, Dict, Any from fastapi import FastAPI from pydantic import BaseModel, Field # Reuse the already-initialized runtime context from the MCP router from pwnomcp.router import mcp as mcp_router logger = logging.getLogger(__name__) class AttachRequest(BaseModel): """ Request body for /attach - pre: list of GDB commands to execute before attaching - pid: target process id to attach - after: list of GDB commands to execute after successful attach - where: optional binary path to set as debug target before pre (can be skipped if pre-setted) """ pre: Optional[List[str]] = Field(default=None) pid: int after: Optional[List[str]] = Field(default=None) where: Optional[str] = Field(default=None) script_pid: Optional[int] = Field(default=None) class AttachResponse(BaseModel): """Response body for /attach""" successful: bool attach: Optional[Dict[str, Any]] = None result: Dict[str, Any] app = FastAPI(title="pwno-mcp attach", version="0.1.0") def _get_tools(): """Obtain the shared PwndbgTools instance from the MCP router.""" tools = mcp_router.pwndbg_tools if tools is None: raise RuntimeError("pwndbg_tools not initialized; ensure server set_runtime_context was called") return tools @app.get("/") async def root(): return {"message": "Pwno MCP Attach"} @app.post("/attach", response_model=AttachResponse) async def attach_endpoint(body: AttachRequest) -> AttachResponse: """ Attach to a running process and execute optional pre/after commands. Returns: - successful: whether attaching to the pid succeeded - result: mapping {command: command_result_dict} for all executed commands """ tools = _get_tools() command_results: Dict[str, Any] = {} # Optionally set the binary file prior to pre-commands if body.where: try: logger.info("[attach] set-file: %s", body.where) set_res = tools.set_file(body.where) command_results["set-file"] = set_res except Exception as e: logger.exception("Error setting file: %s", body.where) command_results["set-file"] = {"success": False, "error": str(e)} # Execute pre-attachment commands for cmd in body.pre or []: try: logger.info("[attach] pre: %s", cmd) res = tools.execute(cmd) logger.info("[attach] pre command result: %s", res) command_results[cmd] = res except Exception as e: logger.exception("Error executing pre command: %s", cmd) command_results[cmd] = {"success": False, "error": str(e)} # Perform attach attach_info: Optional[Dict[str, Any]] = None try: logger.info("[attach] attaching to pid=%s", body.pid) attach_result, _ = tools.attach(body.pid) logger.info("[attach] attach result: %s", attach_result) attach_success = bool(attach_result.get("success")) # Selectively expose key fields only attach_info = { "command": attach_result.get("command"), "success": attach_success, "state": attach_result.get("state"), "pid": attach_result.get("pid"), "script_pid": body.script_pid, } except Exception: logger.exception("Error attaching to pid %s", body.pid) attach_success = False attach_info = {"success": False, "error": f"failed to attach to pid {body.pid}"} # Execute after-attachment commands only if attach succeeded if attach_success: for cmd in body.after or []: try: logger.info("[attach] after: %s", cmd) res = tools.execute(cmd) logger.info("[attach] after command result: %s", res) command_results[cmd] = res except Exception as e: logger.exception("Error executing after command: %s", cmd) command_results[cmd] = {"success": False, "error": str(e)} return AttachResponse(successful=attach_success, attach=attach_info, result=command_results) def get_attach_app() -> FastAPI: """Expose the attach FastAPI app for mounting/serving under loopback.""" return 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/0xSensei/pwno-mcp'

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