MCP-compatible client that routes tool calls through `docker exec`. Subclasses MCPClient with connect=False to skip HTTP connection, then overrides invoke, list_tools, close, and get_session_id to use docker exec against an official SWE-bench container.
| 21 | |
| 22 | |
| 23 | class DockerExecClient(MCPClient): |
| 24 | """MCP-compatible client that routes tool calls through `docker exec`. |
| 25 | |
| 26 | Subclasses MCPClient with connect=False to skip HTTP connection, |
| 27 | then overrides invoke, list_tools, close, and get_session_id to |
| 28 | use docker exec against an official SWE-bench container. |
| 29 | """ |
| 30 | |
| 31 | def __init__( |
| 32 | self, |
| 33 | image: str, |
| 34 | container_id: Optional[str] = None, |
| 35 | ): |
| 36 | """Initialize DockerExecClient. |
| 37 | |
| 38 | Args: |
| 39 | image: SWE-bench Docker image name (e.g. swebench/sweb.eval.x86_64.django_1776_django-10880:latest) |
| 40 | container_id: Optional existing container ID for resume. |
| 41 | """ |
| 42 | # Initialize parent without connecting to MCP server |
| 43 | super().__init__(connect=False) |
| 44 | |
| 45 | self.image = image |
| 46 | |
| 47 | if container_id: |
| 48 | self._container_id = container_id |
| 49 | else: |
| 50 | # Start a new container from the image |
| 51 | # -w /testbed sets the default working directory (matches mini-swe-agent) |
| 52 | result = subprocess.run( |
| 53 | [ |
| 54 | "docker", |
| 55 | "run", |
| 56 | "-d", |
| 57 | "--rm", |
| 58 | "-w", |
| 59 | "/testbed", |
| 60 | image, |
| 61 | "sleep", |
| 62 | "7200", |
| 63 | ], |
| 64 | capture_output=True, |
| 65 | text=True, |
| 66 | timeout=120, |
| 67 | ) |
| 68 | if result.returncode != 0: |
| 69 | raise RuntimeError( |
| 70 | f"Failed to start container from {image}: {result.stderr}" |
| 71 | ) |
| 72 | self._container_id = result.stdout.strip() |
| 73 | |
| 74 | self._session_id = self._container_id |
| 75 | print(f"[DockerExecClient] Container started: {self._container_id[:12]}") |
| 76 | |
| 77 | # Run eval-compatible setup (matches the SWE-bench eval harness script) |
| 78 | if not container_id: |
| 79 | self._setup_container() |
| 80 |
no outgoing calls
no test coverage detected