|
| 1 | +For gpt expected container tool, here's an incomplete example |
| 2 | +Note that the SweRexManager or swe_rex are dummies, you need to implement your own container tool with session management |
| 3 | +``` |
| 4 | +from mcp.server.fastmcp import fastmcp |
| 5 | +# dummy showing how to import container tool |
| 6 | +from swe_rex import SweRexManager |
| 7 | +
|
| 8 | +# Pass lifespan to server |
| 9 | +mcp = FastMCP( |
| 10 | + name="container", |
| 11 | + instructions=r""" |
| 12 | +Utilities for interacting with a container, for example, a Docker container.\n |
| 13 | +(container_tool, version 1.X.X)\n |
| 14 | +(lean_terminal, version 1.X.X) |
| 15 | +""".strip(), |
| 16 | +) |
| 17 | +
|
| 18 | +swe_rex_manager = SweRexManager() |
| 19 | +
|
| 20 | +def _get_session_id(ctx: Context) -> str: |
| 21 | + """Extract session ID from headers, URL query parameter or fallback to client_id""" |
| 22 | + request = ctx.request_context.request |
| 23 | + return request.headers.get("session_id") or request.query_params.get( |
| 24 | + "session_id" |
| 25 | + ) or ctx.client_id |
| 26 | +
|
| 27 | +@mcp.tool( |
| 28 | + name="exec", |
| 29 | + title="container exec", |
| 30 | + description=""" |
| 31 | +Returns the output of the command. |
| 32 | +Allocates an interactive pseudo-TTY if (and only if) 'session_name' is set. |
| 33 | + """, |
| 34 | + ) |
| 35 | +async def exec( |
| 36 | + ctx: Context, |
| 37 | + cmd: list[str], |
| 38 | + session_name: Optional[str] = None, |
| 39 | + workdir: Optional[str] = None, |
| 40 | + timeout: Optional[int] = None, |
| 41 | + env: Optional[dict[str, str]] = None, |
| 42 | + user: Optional[str] = None, |
| 43 | +) -> str: |
| 44 | + session_id = _get_session_id(ctx) |
| 45 | + try: |
| 46 | + logger.debug(f"cmd for container exec: {cmd}") |
| 47 | +
|
| 48 | + res = await swe_rex_manager.execute_in_session( |
| 49 | + session_id, |
| 50 | + cmd=cmd, |
| 51 | + workdir=workdir, |
| 52 | + env=env, |
| 53 | + execution_timeout=360 if timeout is None else timeout, |
| 54 | + # Below fields are not used right now |
| 55 | + session_name=session_name, # This could be overriding session_id |
| 56 | + user=user, |
| 57 | + ) |
| 58 | + logger.info(f"container execution result: {res}") |
| 59 | + return res |
| 60 | +
|
| 61 | +@mcp.tool( |
| 62 | + name="cleanup_session", |
| 63 | + title="clean container session", |
| 64 | + description="cleanup a specific session", |
| 65 | + annotations={ |
| 66 | + "include_in_prompt": False, |
| 67 | + }) |
| 68 | +async def cleanup_session(ctx: Context) -> None: |
| 69 | + """Cleanup a specific session""" |
| 70 | + session_id = _get_session_id(ctx) |
| 71 | + logger.info(f"Cleaning up session: {session_id}") |
| 72 | + await swe_rex_manager.cleanup_session(session_id) |
| 73 | +``` |
0 commit comments