mle-kit-mcp 0.0.2__py3-none-any.whl → 0.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mle_kit_mcp/files.py +18 -5
- mle_kit_mcp/server.py +17 -13
- mle_kit_mcp/tools/bash.py +2 -2
- mle_kit_mcp/tools/remote_gpu.py +9 -9
- mle_kit_mcp/tools/text_editor.py +2 -2
- {mle_kit_mcp-0.0.2.dist-info → mle_kit_mcp-0.0.4.dist-info}/METADATA +1 -1
- mle_kit_mcp-0.0.4.dist-info/RECORD +16 -0
- mle_kit_mcp-0.0.2.dist-info/RECORD +0 -16
- {mle_kit_mcp-0.0.2.dist-info → mle_kit_mcp-0.0.4.dist-info}/WHEEL +0 -0
- {mle_kit_mcp-0.0.2.dist-info → mle_kit_mcp-0.0.4.dist-info}/entry_points.txt +0 -0
- {mle_kit_mcp-0.0.2.dist-info → mle_kit_mcp-0.0.4.dist-info}/licenses/LICENSE +0 -0
- {mle_kit_mcp-0.0.2.dist-info → mle_kit_mcp-0.0.4.dist-info}/top_level.txt +0 -0
mle_kit_mcp/files.py
CHANGED
@@ -1,12 +1,25 @@
|
|
1
|
+
import os
|
2
|
+
from typing import Optional
|
1
3
|
from pathlib import Path
|
2
4
|
|
3
5
|
DIR_PATH = Path(__file__).parent
|
4
6
|
ROOT_PATH = DIR_PATH.parent
|
7
|
+
DEFAULT_WORKSPACE_DIR_PATH: Path = DIR_PATH / "workdir"
|
5
8
|
|
6
|
-
WORKSPACE_DIR_PATH: Path = ROOT_PATH / "workdir"
|
7
9
|
|
10
|
+
class WorkspaceDirectory:
|
11
|
+
workspace_dir: Optional[Path] = None
|
8
12
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
+
@classmethod
|
14
|
+
def get_dir(cls) -> Path:
|
15
|
+
if cls.workspace_dir is None:
|
16
|
+
return Path(os.getenv("WORKSPACE_DIR", DEFAULT_WORKSPACE_DIR_PATH))
|
17
|
+
return cls.workspace_dir
|
18
|
+
|
19
|
+
@classmethod
|
20
|
+
def set_dir(cls, workspace_dir: Path) -> None:
|
21
|
+
cls.workspace_dir = workspace_dir
|
22
|
+
|
23
|
+
|
24
|
+
def get_workspace_dir() -> Path:
|
25
|
+
return WorkspaceDirectory.get_dir()
|
mle_kit_mcp/server.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
import fire # type: ignore
|
2
1
|
from pathlib import Path
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
import fire # type: ignore
|
3
5
|
import uvicorn
|
4
6
|
from mcp.server.fastmcp import FastMCP
|
5
7
|
|
6
|
-
from .files import set_workspace_dir
|
7
8
|
from .tools.bash import bash
|
8
9
|
from .tools.text_editor import text_editor
|
9
10
|
from .tools.remote_gpu import (
|
@@ -11,24 +12,27 @@ from .tools.remote_gpu import (
|
|
11
12
|
create_remote_text_editor,
|
12
13
|
remote_download,
|
13
14
|
)
|
15
|
+
from .files import get_workspace_dir, WorkspaceDirectory
|
14
16
|
|
15
17
|
|
16
|
-
|
18
|
+
def run(host: str = "0.0.0.0", port: int = 5050, workspace: Optional[str] = None) -> None:
|
19
|
+
if workspace:
|
20
|
+
WorkspaceDirectory.set_dir(Path(workspace))
|
21
|
+
workspace_path = get_workspace_dir()
|
22
|
+
workspace_path.mkdir(parents=True, exist_ok=True)
|
17
23
|
|
18
|
-
|
24
|
+
server = FastMCP("MLE kit MCP", stateless_http=True)
|
19
25
|
|
20
|
-
|
21
|
-
server.add_tool(text_editor)
|
22
|
-
server.add_tool(remote_bash)
|
23
|
-
server.add_tool(remote_text_editor)
|
24
|
-
server.add_tool(remote_download)
|
26
|
+
remote_text_editor = create_remote_text_editor(text_editor)
|
25
27
|
|
26
|
-
|
28
|
+
server.add_tool(bash)
|
29
|
+
server.add_tool(text_editor)
|
30
|
+
server.add_tool(remote_bash)
|
31
|
+
server.add_tool(remote_text_editor)
|
32
|
+
server.add_tool(remote_download)
|
27
33
|
|
34
|
+
http_app = server.streamable_http_app()
|
28
35
|
|
29
|
-
def run(host: str = "0.0.0.0", port: int = 5050, workspace: str = "workdir") -> None:
|
30
|
-
workspace_path = Path(workspace)
|
31
|
-
set_workspace_dir(workspace_path)
|
32
36
|
uvicorn.run(http_app, host=host, port=port)
|
33
37
|
|
34
38
|
|
mle_kit_mcp/tools/bash.py
CHANGED
@@ -3,7 +3,7 @@ import atexit
|
|
3
3
|
import signal
|
4
4
|
from typing import Optional, Any
|
5
5
|
|
6
|
-
from mle_kit_mcp.files import
|
6
|
+
from mle_kit_mcp.files import get_workspace_dir
|
7
7
|
|
8
8
|
|
9
9
|
_container = None
|
@@ -63,7 +63,7 @@ def bash(command: str) -> str:
|
|
63
63
|
tty=True,
|
64
64
|
stdin_open=True,
|
65
65
|
volumes={
|
66
|
-
|
66
|
+
get_workspace_dir(): {
|
67
67
|
"bind": DOCKER_WORKSPACE_DIR_PATH,
|
68
68
|
"mode": "rw",
|
69
69
|
}
|
mle_kit_mcp/tools/remote_gpu.py
CHANGED
@@ -12,7 +12,7 @@ from dataclasses import dataclass
|
|
12
12
|
from dotenv import load_dotenv
|
13
13
|
from vastai_sdk import VastAI # type: ignore
|
14
14
|
|
15
|
-
from mle_kit_mcp.files import
|
15
|
+
from mle_kit_mcp.files import get_workspace_dir
|
16
16
|
|
17
17
|
BASE_IMAGE = "phoenix120/holosophos_mle"
|
18
18
|
DEFAULT_GPU_TYPE = "RTX_3090"
|
@@ -94,7 +94,7 @@ def get_offers(vast_sdk: VastAI, gpu_name: str) -> List[int]:
|
|
94
94
|
|
95
95
|
|
96
96
|
def run_command(
|
97
|
-
instance: InstanceInfo, command: str, timeout: int = 60
|
97
|
+
instance: InstanceInfo, command: str, timeout: int = 60, raise_exc: bool = True
|
98
98
|
) -> subprocess.CompletedProcess[str]:
|
99
99
|
cmd = [
|
100
100
|
"ssh",
|
@@ -117,7 +117,7 @@ def run_command(
|
|
117
117
|
]
|
118
118
|
try:
|
119
119
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
|
120
|
-
if result.returncode != 0:
|
120
|
+
if result.returncode != 0 and raise_exc:
|
121
121
|
raise Exception(
|
122
122
|
f"Error running command: {command}; "
|
123
123
|
f"Output: {result.stdout}; "
|
@@ -257,9 +257,9 @@ def launch_instance(vast_sdk: VastAI, gpu_name: str) -> Optional[InstanceInfo]:
|
|
257
257
|
|
258
258
|
def send_scripts() -> None:
|
259
259
|
assert _instance_info
|
260
|
-
for name in os.listdir(
|
260
|
+
for name in os.listdir(get_workspace_dir()):
|
261
261
|
if name.endswith(".py"):
|
262
|
-
send_rsync(_instance_info, f"{
|
262
|
+
send_rsync(_instance_info, f"{get_workspace_dir()}/{name}", "/root")
|
263
263
|
|
264
264
|
|
265
265
|
def init_all() -> None:
|
@@ -301,7 +301,7 @@ def remote_bash(command: str, timeout: Optional[int] = 60) -> str:
|
|
301
301
|
init_all()
|
302
302
|
assert _instance_info
|
303
303
|
assert timeout
|
304
|
-
result = run_command(_instance_info, command, timeout=timeout)
|
304
|
+
result = run_command(_instance_info, command, timeout=timeout, raise_exc=False)
|
305
305
|
output = ("STDOUT: " + result.stdout + "\n") if result.stdout else ""
|
306
306
|
output += ("STDERR: " + result.stderr) if result.stderr else ""
|
307
307
|
return output.replace(VAST_AI_GREETING, "")
|
@@ -316,7 +316,7 @@ def remote_download(file_path: str) -> str:
|
|
316
316
|
"""
|
317
317
|
init_all()
|
318
318
|
assert _instance_info
|
319
|
-
recieve_rsync(_instance_info, f"/root/{file_path}", f"{
|
319
|
+
recieve_rsync(_instance_info, f"/root/{file_path}", f"{get_workspace_dir()}")
|
320
320
|
return f"File '{file_path}' downloaded!"
|
321
321
|
|
322
322
|
|
@@ -335,12 +335,12 @@ def create_remote_text_editor(
|
|
335
335
|
command = args_dict["command"]
|
336
336
|
|
337
337
|
if command != "write":
|
338
|
-
recieve_rsync(_instance_info, f"/root/{path}", f"{
|
338
|
+
recieve_rsync(_instance_info, f"/root/{path}", f"{get_workspace_dir()}")
|
339
339
|
|
340
340
|
result: str = text_editor_func(*args, **kwargs)
|
341
341
|
|
342
342
|
if command != "view":
|
343
|
-
send_rsync(_instance_info, f"{
|
343
|
+
send_rsync(_instance_info, f"{get_workspace_dir()}/{path}", "/root")
|
344
344
|
|
345
345
|
return result
|
346
346
|
|
mle_kit_mcp/tools/text_editor.py
CHANGED
@@ -2,7 +2,7 @@ from collections import defaultdict
|
|
2
2
|
from typing import Dict, List, Optional
|
3
3
|
from pathlib import Path
|
4
4
|
|
5
|
-
from mle_kit_mcp.files import
|
5
|
+
from mle_kit_mcp.files import get_workspace_dir
|
6
6
|
from mle_kit_mcp.utils import truncate_content
|
7
7
|
|
8
8
|
WRITE_MAX_OUTPUT_LENGTH = 500
|
@@ -174,7 +174,7 @@ def text_editor(
|
|
174
174
|
), "Absolute path is not supported, only relative to the work directory"
|
175
175
|
valid_commands = ("view", "write", "str_replace", "insert", "undo_edit", "append")
|
176
176
|
|
177
|
-
path_obj =
|
177
|
+
path_obj = get_workspace_dir() / path
|
178
178
|
|
179
179
|
if command == "view":
|
180
180
|
show_lines = show_lines if show_lines is not None else False
|
@@ -0,0 +1,16 @@
|
|
1
|
+
mle_kit_mcp/__init__.py,sha256=2Ru2I5u4cE7DrkkAsibDUEF1K6sYtqppb9VyFrRoQKI,94
|
2
|
+
mle_kit_mcp/__main__.py,sha256=rcmsOtJd3SA82exjrcGBuxuptcoxF8AXI7jNjiVq2BY,59
|
3
|
+
mle_kit_mcp/files.py,sha256=ux53kWw7hBAcOmS9qNI4gpQX8XcQPT2LICC--S5-TGI,635
|
4
|
+
mle_kit_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
+
mle_kit_mcp/server.py,sha256=E9cXdKwVBASBzKyrZGHCTvj6BIMN-EbVSQZDFNg0YnE,1062
|
6
|
+
mle_kit_mcp/utils.py,sha256=wd7wSyddHRHOYdxmXw8uoAOBxVZOL2_vjNomss07inc,1654
|
7
|
+
mle_kit_mcp/tools/__init__.py,sha256=0aLl0gD-JteSvOs2PgVhbv0Wnh6fodFySgQWQvoI1xI,215
|
8
|
+
mle_kit_mcp/tools/bash.py,sha256=9IIcely_J_fvNPLdJvHFOL72OG3rVIpNC3MB5S36pJI,2460
|
9
|
+
mle_kit_mcp/tools/remote_gpu.py,sha256=Rwy0vuPgBqZDonsJjhapbrBnw1dKViKUJonTC8AiPJE,11429
|
10
|
+
mle_kit_mcp/tools/text_editor.py,sha256=s9lPzqQWpZ2277f99TgMyKeOSTrv-PhX4HVtdXVeQ24,9228
|
11
|
+
mle_kit_mcp-0.0.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
12
|
+
mle_kit_mcp-0.0.4.dist-info/METADATA,sha256=-kG6R55hu0Ta3nyNMY87DLWETscN7rMnSelcIISh4SA,1126
|
13
|
+
mle_kit_mcp-0.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
14
|
+
mle_kit_mcp-0.0.4.dist-info/entry_points.txt,sha256=-iHSUVPN49jkBj1ySpc-P0rVF5-IPHw-KWNayNIiEsk,49
|
15
|
+
mle_kit_mcp-0.0.4.dist-info/top_level.txt,sha256=XeBtCq_CnVI0gh0Z_daZOLmGl5XPlkA8RgHaj5s5VQY,12
|
16
|
+
mle_kit_mcp-0.0.4.dist-info/RECORD,,
|
@@ -1,16 +0,0 @@
|
|
1
|
-
mle_kit_mcp/__init__.py,sha256=2Ru2I5u4cE7DrkkAsibDUEF1K6sYtqppb9VyFrRoQKI,94
|
2
|
-
mle_kit_mcp/__main__.py,sha256=rcmsOtJd3SA82exjrcGBuxuptcoxF8AXI7jNjiVq2BY,59
|
3
|
-
mle_kit_mcp/files.py,sha256=loZnpQ7ZLxjX8NgUq-hrvhwbQwmGw1F6gZ3xD3UQI9k,286
|
4
|
-
mle_kit_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
mle_kit_mcp/server.py,sha256=l81KAfyZ_G_0Suy9381qV40I_UAZtfT0FKim3_89pSI,886
|
6
|
-
mle_kit_mcp/utils.py,sha256=wd7wSyddHRHOYdxmXw8uoAOBxVZOL2_vjNomss07inc,1654
|
7
|
-
mle_kit_mcp/tools/__init__.py,sha256=0aLl0gD-JteSvOs2PgVhbv0Wnh6fodFySgQWQvoI1xI,215
|
8
|
-
mle_kit_mcp/tools/bash.py,sha256=QcPKQBjD6-LHvNGOAhyWXHuzkM70GATN0Vp85iykSXY,2460
|
9
|
-
mle_kit_mcp/tools/remote_gpu.py,sha256=Wh02B-hFUFdRRtZ0J4feLw9P8Hq0AW7xwZ3Q27LcdW4,11370
|
10
|
-
mle_kit_mcp/tools/text_editor.py,sha256=zwxyHvf8DdJwuUa7HOWfSbhaSTveaE_WMwsOdDnbq1w,9228
|
11
|
-
mle_kit_mcp-0.0.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
12
|
-
mle_kit_mcp-0.0.2.dist-info/METADATA,sha256=m68NZT-bBF4n1yvKeAfH1arVku2jpkG3juuOs0fQE_4,1126
|
13
|
-
mle_kit_mcp-0.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
14
|
-
mle_kit_mcp-0.0.2.dist-info/entry_points.txt,sha256=-iHSUVPN49jkBj1ySpc-P0rVF5-IPHw-KWNayNIiEsk,49
|
15
|
-
mle_kit_mcp-0.0.2.dist-info/top_level.txt,sha256=XeBtCq_CnVI0gh0Z_daZOLmGl5XPlkA8RgHaj5s5VQY,12
|
16
|
-
mle_kit_mcp-0.0.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|