-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathshell_utils.py
More file actions
44 lines (33 loc) · 1.52 KB
/
shell_utils.py
File metadata and controls
44 lines (33 loc) · 1.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# SPDX-FileCopyrightText: GitHub, Inc.
# SPDX-License-Identifier: MIT
"""Shell command execution utilities."""
import logging
import subprocess
import tempfile
from mcp.types import CallToolResult, TextContent
__all__ = ["shell_command_to_string", "shell_exec_with_temporary_file", "shell_tool_call"]
def shell_command_to_string(cmd: list[str]) -> str:
"""Execute a shell command and return its stdout.
Raises:
RuntimeError: If the command exits with a non-zero return code.
"""
logging.info("Executing: %s", cmd)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8")
stdout, stderr = p.communicate()
p.wait()
if p.returncode:
raise RuntimeError(f"Command {cmd} failed: {stderr}")
return stdout
def shell_exec_with_temporary_file(script: str, shell: str = "bash") -> str:
"""Write *script* to a temp file and execute it with the given shell."""
with tempfile.NamedTemporaryFile(mode="w+", delete=True) as temp_file:
temp_file.write(script)
temp_file.flush()
result = shell_command_to_string([shell, temp_file.name])
return result
def shell_tool_call(run: str) -> CallToolResult:
"""Execute a shell script and return the output as a CallToolResult."""
stdout = shell_exec_with_temporary_file(run)
# this allows e.g. shell based jq output to become available for repeat prompts
result = CallToolResult(content=[TextContent(type="text", text=stdout, annotations=None, meta=None)])
return result