Skip to content

Commit 6413fe3

Browse files
📝 Add docstrings to mcp-http-transport
Docstrings generation was requested by @Wangmerlyn. * #60 (comment) The following files were modified: * `src/keep_gpu/mcp/server.py`
1 parent 9e4b35b commit 6413fe3

1 file changed

Lines changed: 95 additions & 1 deletion

File tree

src/keep_gpu/mcp/server.py

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,22 @@ def start_keep(
5252
busy_threshold: int = -1,
5353
job_id: Optional[str] = None,
5454
) -> Dict[str, Any]:
55+
"""
56+
Start a KeepGPU session that periodically reserves the specified amount of VRAM on one or more GPUs.
57+
58+
Parameters:
59+
gpu_ids (Optional[List[int]]): List of GPU indices to target; if `None`, all available GPUs may be considered.
60+
vram (str): Amount of VRAM to reserve (human-readable, e.g. "1GiB").
61+
interval (int): Time in seconds between controller checks/actions.
62+
busy_threshold (int): Numeric threshold controlling what the controller treats as "busy" (semantics provided by the controller).
63+
job_id (Optional[str]): Identifier for the session; when `None`, a new UUID is generated.
64+
65+
Returns:
66+
dict: A dictionary with the started session's `job_id`, e.g. `{"job_id": "<id>"}`.
67+
68+
Raises:
69+
ValueError: If `job_id` is provided and already exists.
70+
"""
5571
job_id = job_id or str(uuid.uuid4())
5672
if job_id in self._sessions:
5773
raise ValueError(f"job_id {job_id} already exists")
@@ -78,6 +94,19 @@ def start_keep(
7894
def stop_keep(
7995
self, job_id: Optional[str] = None, quiet: bool = False
8096
) -> Dict[str, Any]:
97+
"""
98+
Stop one or all active keep sessions.
99+
100+
If `job_id` is provided, stops and removes that session if it exists; otherwise stops and removes all sessions. When `quiet` is True, informational logging about stopped sessions is suppressed.
101+
102+
Parameters:
103+
job_id (Optional[str]): Identifier of the session to stop. If omitted, all sessions are stopped.
104+
quiet (bool): If True, do not emit informational logs about stopped sessions.
105+
106+
Returns:
107+
result (Dict[str, Any]): A dictionary with a "stopped" key listing stopped job IDs. If a specific
108+
`job_id` was requested but not found, the dictionary also includes a "message" explaining that.
109+
"""
81110
if job_id:
82111
session = self._sessions.pop(job_id, None)
83112
if session:
@@ -118,6 +147,11 @@ def list_gpus(self) -> Dict[str, Any]:
118147
return {"gpus": infos}
119148

120149
def shutdown(self) -> None:
150+
"""
151+
Stop all active sessions and release resources, suppressing any errors that occur during interpreter teardown.
152+
153+
This attempts to stop every session (quietly) and ignores exceptions to avoid noisy errors when the interpreter is shutting down.
154+
"""
121155
try:
122156
self.stop_keep(None, quiet=True)
123157
except Exception: # pragma: no cover - defensive
@@ -126,6 +160,22 @@ def shutdown(self) -> None:
126160

127161

128162
def _handle_request(server: KeepGPUServer, payload: Dict[str, Any]) -> Dict[str, Any]:
163+
"""
164+
Dispatches a JSON-RPC-like request payload to the corresponding KeepGPUServer method and returns a JSON-RPC response object.
165+
166+
Parameters:
167+
server (KeepGPUServer): The server instance whose methods will be invoked.
168+
payload (dict): The incoming request object; expected keys:
169+
- "method" (str): RPC method name ("start_keep", "stop_keep", "status", "list_gpus").
170+
- "params" (dict, optional): Keyword arguments for the method.
171+
- "id" (any, optional): Caller-provided request identifier preserved in the response.
172+
173+
Returns:
174+
dict: A JSON-RPC-style response containing:
175+
- "id": the original request id (or None if not provided).
176+
- "result": the method's return value on success.
177+
- OR "error": an object with a "message" string describing the failure.
178+
"""
129179
method = payload.get("method")
130180
params = payload.get("params", {}) or {}
131181
req_id = payload.get("id")
@@ -150,6 +200,11 @@ class _JSONRPCHandler(BaseHTTPRequestHandler):
150200
server_version = "KeepGPU-MCP/0.1"
151201

152202
def do_POST(self): # noqa: N802
203+
"""
204+
Handle HTTP POST requests containing a JSON-RPC payload and send a JSON response.
205+
206+
Reads the request body using the Content-Length header, parses it as JSON, dispatches the payload to the internal JSON-RPC dispatcher, and writes the dispatcher result as an application/json response. If the request body cannot be decoded or parsed, responds with HTTP 400 and a JSON error object describing the parsing error.
207+
"""
153208
try:
154209
length = int(self.headers.get("content-length", "0"))
155210
body = self.rfile.read(length).decode("utf-8")
@@ -167,10 +222,28 @@ def do_POST(self): # noqa: N802
167222
self.wfile.write(data)
168223

169224
def log_message(self, format, *args): # noqa: A003
225+
"""
226+
Suppress the BaseHTTPRequestHandler's default request logging by overriding log_message to do nothing.
227+
228+
Parameters:
229+
format (str): The format string provided by BaseHTTPRequestHandler.
230+
*args: Values to interpolate into `format`.
231+
"""
170232
return
171233

172234

173235
def run_stdio(server: KeepGPUServer) -> None:
236+
"""
237+
Read line-delimited JSON-RPC requests from stdin, dispatch each request to the server, and write the JSON response to stdout.
238+
239+
Parameters:
240+
server (KeepGPUServer): Server instance used to handle JSON-RPC requests.
241+
242+
Description:
243+
- Processes each non-empty line from stdin as a JSON payload.
244+
- On successful handling, writes the JSON-RPC response followed by a newline to stdout and flushes.
245+
- If parsing or handling raises an exception, writes an error object with the exception message as the response.
246+
"""
174247
for line in sys.stdin:
175248
line = line.strip()
176249
if not line:
@@ -185,13 +258,29 @@ def run_stdio(server: KeepGPUServer) -> None:
185258

186259

187260
def run_http(server: KeepGPUServer, host: str = "127.0.0.1", port: int = 8765) -> None:
261+
"""
262+
Start a lightweight HTTP JSON-RPC server that exposes the given KeepGPUServer on the specified host and port.
263+
264+
Starts a TCP HTTP server serving _JSONRPCHandler in a background thread, logs the listening address, waits for the thread to finish, and on interruption or shutdown performs a clean shutdown of the HTTP server and calls server.shutdown() to release resources.
265+
266+
Parameters:
267+
server (KeepGPUServer): The KeepGPUServer instance whose RPC methods will be exposed over HTTP.
268+
host (str): Host address to bind the HTTP server to.
269+
port (int): TCP port to bind the HTTP server to.
270+
"""
188271
class _Server(TCPServer):
189272
allow_reuse_address = True
190273

191274
httpd = _Server((host, port), _JSONRPCHandler)
192275
httpd.keepgpu_server = server # type: ignore[attr-defined]
193276

194277
def _serve():
278+
"""
279+
Run the HTTP server's request loop until the server is shut down.
280+
281+
Blocks the current thread and processes incoming HTTP requests for the
282+
server instance until the server is stopped.
283+
"""
195284
httpd.serve_forever()
196285

197286
thread = threading.Thread(target=_serve)
@@ -210,6 +299,11 @@ def _serve():
210299

211300

212301
def main() -> None:
302+
"""
303+
Entry point for the KeepGPU MCP server that parses command-line arguments and starts the chosen transport.
304+
305+
Parses --mode (stdio or http), --host and --port (for http mode), instantiates a KeepGPUServer, and runs either the stdio loop or the HTTP server based on the selected mode.
306+
"""
213307
parser = argparse.ArgumentParser(description="KeepGPU MCP server")
214308
parser.add_argument(
215309
"--mode",
@@ -229,4 +323,4 @@ def main() -> None:
229323

230324

231325
if __name__ == "__main__":
232-
main()
326+
main()

0 commit comments

Comments
 (0)