mle-kit-mcp 0.1.0__tar.gz → 0.1.1__tar.gz

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.
Files changed (27) hide show
  1. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/PKG-INFO +1 -1
  2. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/tools/bash.py +6 -2
  3. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/tools/text_editor.py +14 -5
  4. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp.egg-info/PKG-INFO +1 -1
  5. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/pyproject.toml +1 -1
  6. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/tests/test_bash.py +6 -0
  7. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/tests/test_text_editor.py +12 -0
  8. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/LICENSE +0 -0
  9. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/README.md +0 -0
  10. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/__init__.py +0 -0
  11. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/__main__.py +0 -0
  12. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/files.py +0 -0
  13. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/llm_proxy_source.py +0 -0
  14. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/py.typed +0 -0
  15. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/server.py +0 -0
  16. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/tools/__init__.py +0 -0
  17. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/tools/llm_proxy.py +0 -0
  18. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/tools/remote_gpu.py +0 -0
  19. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp/utils.py +0 -0
  20. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp.egg-info/SOURCES.txt +0 -0
  21. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp.egg-info/dependency_links.txt +0 -0
  22. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp.egg-info/entry_points.txt +0 -0
  23. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp.egg-info/requires.txt +0 -0
  24. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/mle_kit_mcp.egg-info/top_level.txt +0 -0
  25. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/setup.cfg +0 -0
  26. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/tests/test_llm_proxy.py +0 -0
  27. {mle_kit_mcp-0.1.0 → mle_kit_mcp-0.1.1}/tests/test_truncate_context.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mle-kit-mcp
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: MCP server that provides different tools for MLE
5
5
  Author-email: Ilya Gusev <phoenixilya@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/IlyaGusev/mle_kit_mcp
@@ -67,7 +67,7 @@ signal.signal(signal.SIGINT, cleanup_container)
67
67
  signal.signal(signal.SIGTERM, cleanup_container)
68
68
 
69
69
 
70
- def bash(command: str) -> str:
70
+ def bash(command: str, cwd: Optional[str] = None) -> str:
71
71
  """
72
72
  Run commands in a bash shell.
73
73
  When invoking this tool, the contents of the "command" parameter does NOT need to be XML-escaped.
@@ -80,12 +80,16 @@ def bash(command: str) -> str:
80
80
 
81
81
  Args:
82
82
  command: The bash command to run.
83
+ cwd: The working directory to run the command in. Relative to the workspace directory.
83
84
  """
84
85
 
85
86
  container = get_container()
87
+ workdir = DOCKER_WORKSPACE_DIR_PATH
88
+ if cwd:
89
+ workdir = DOCKER_WORKSPACE_DIR_PATH + "/" + cwd
86
90
  result = container.exec_run(
87
91
  ["bash", "-c", command],
88
- workdir=DOCKER_WORKSPACE_DIR_PATH,
92
+ workdir=workdir,
89
93
  stdout=True,
90
94
  stderr=True,
91
95
  )
@@ -50,17 +50,23 @@ def _insert(path: Path, insert_line: int, new_str: str) -> str:
50
50
  return truncate_content(new_content, WRITE_MAX_OUTPUT_LENGTH, target_line=insert_line)
51
51
 
52
52
 
53
- def _str_replace(path: Path, old_str: str, new_str: str) -> str:
53
+ def _str_replace(path: Path, old_str: str, new_str: str, dry_run: bool = False) -> str:
54
54
  assert path.is_file(), f"File not found: {path}"
55
55
  content = path.open().read()
56
56
  count = content.count(old_str)
57
57
  assert count != 0, "old_str not found in file"
58
58
  assert count == 1, "old_str is not unique in file"
59
59
  target_line = content[: content.find(old_str) + len(old_str)].count("\n")
60
- _save_file_state(path, content.splitlines(True))
61
60
  new_content = content.replace(old_str, new_str)
62
- path.write_text(new_content)
63
- return truncate_content(new_content, WRITE_MAX_OUTPUT_LENGTH, target_line=target_line)
61
+ if not dry_run:
62
+ _save_file_state(path, content.splitlines(True))
63
+ path.write_text(new_content)
64
+ display_content = truncate_content(
65
+ new_content, WRITE_MAX_OUTPUT_LENGTH, target_line=target_line
66
+ )
67
+ if dry_run:
68
+ display_content = f"Dry run:\n{display_content}"
69
+ return display_content
64
70
 
65
71
 
66
72
  def _undo_edit(path: Path) -> str:
@@ -129,6 +135,7 @@ def text_editor(
129
135
  view_start_line: Optional[int] = None,
130
136
  view_end_line: Optional[int] = None,
131
137
  show_lines: Optional[bool] = False,
138
+ dry_run: Optional[bool] = False,
132
139
  ) -> str:
133
140
  """
134
141
  Custom editing tool for viewing, creating and editing files.
@@ -167,6 +174,7 @@ def text_editor(
167
174
  new_str: Required for `str_replace`, `insert` and `append`.
168
175
  old_str: Required for `str_replace` containing the string in `path` to replace.
169
176
  show_lines: Optional for view command. If True, the command will also output line numbers.
177
+ dry_run: Optional for `str_replace` command. If True, the command won't modify the file but will display the result.
170
178
  """
171
179
  assert not path.startswith(
172
180
  "/"
@@ -191,7 +199,8 @@ def text_editor(
191
199
  if command == "str_replace":
192
200
  assert old_str is not None, "'old_str' is required for 'str_replace' command"
193
201
  assert new_str is not None, "'new_str' is required for 'str_replace' command"
194
- return _str_replace(path_obj, old_str, new_str)
202
+ assert dry_run is not None
203
+ return _str_replace(path_obj, old_str, new_str, dry_run=dry_run)
195
204
  if command == "undo_edit":
196
205
  return _undo_edit(path_obj)
197
206
  assert False, f"Not a valid command! List of commands: {valid_commands}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mle-kit-mcp
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: MCP server that provides different tools for MLE
5
5
  Author-email: Ilya Gusev <phoenixilya@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/IlyaGusev/mle_kit_mcp
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mle-kit-mcp"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "MCP server that provides different tools for MLE"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -16,3 +16,9 @@ def test_bash() -> None:
16
16
 
17
17
  result = bash("fddafad")
18
18
  assert "fddafad: command not found" in result
19
+
20
+
21
+ def test_bash_cwd() -> None:
22
+ bash("mkdir -p dummy_dir")
23
+ bash("touch dummy", cwd="dummy_dir")
24
+ assert os.path.exists(get_workspace_dir() / "dummy_dir" / "dummy")
@@ -87,6 +87,18 @@ def test_text_editor_str_replace() -> None:
87
87
  assert "41.9" in new_content and "41.8" not in new_content
88
88
 
89
89
 
90
+ def test_text_editor_str_replace_dry_run() -> None:
91
+ with tempfile.NamedTemporaryFile(dir=get_workspace_dir(), mode="w+") as f:
92
+ name = os.path.basename(f.name)
93
+ test_file = get_workspace_dir() / name
94
+ test_file.write_text(DOCUMENT1)
95
+
96
+ result = text_editor("str_replace", name, old_str="41.8", new_str="41.9", dry_run=True)
97
+ new_content = test_file.open().read()
98
+ assert "41.9" not in new_content and "41.8" in new_content
99
+ assert "Dry run" in result
100
+
101
+
90
102
  def test_text_editor_undo_edit() -> None:
91
103
  with tempfile.NamedTemporaryFile(dir=get_workspace_dir(), mode="w+") as f:
92
104
  name = os.path.basename(f.name)
File without changes
File without changes
File without changes