mseep-mcp-safe-local-python-executor 0.1.0__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.
- mseep_mcp_safe_local_python_executor-0.1.0/LICENSE +21 -0
- mseep_mcp_safe_local_python_executor-0.1.0/PKG-INFO +125 -0
- mseep_mcp_safe_local_python_executor-0.1.0/README.md +99 -0
- mseep_mcp_safe_local_python_executor-0.1.0/mseep_mcp_safe_local_python_executor.egg-info/PKG-INFO +125 -0
- mseep_mcp_safe_local_python_executor-0.1.0/mseep_mcp_safe_local_python_executor.egg-info/SOURCES.txt +11 -0
- mseep_mcp_safe_local_python_executor-0.1.0/mseep_mcp_safe_local_python_executor.egg-info/dependency_links.txt +1 -0
- mseep_mcp_safe_local_python_executor-0.1.0/mseep_mcp_safe_local_python_executor.egg-info/requires.txt +2 -0
- mseep_mcp_safe_local_python_executor-0.1.0/mseep_mcp_safe_local_python_executor.egg-info/top_level.txt +2 -0
- mseep_mcp_safe_local_python_executor-0.1.0/pyproject.toml +47 -0
- mseep_mcp_safe_local_python_executor-0.1.0/setup.cfg +4 -0
- mseep_mcp_safe_local_python_executor-0.1.0/setup.py +20 -0
- mseep_mcp_safe_local_python_executor-0.1.0/tests/test_local_python_executor.py +92 -0
- mseep_mcp_safe_local_python_executor-0.1.0/tests/test_mcp_server.py +46 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Maxim Saplin
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,125 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: mseep-mcp_safe_local_python_executor
|
3
|
+
Version: 0.1.0
|
4
|
+
Summary: MCP server exposing tool for a safe local Python code execution
|
5
|
+
Home-page:
|
6
|
+
Author: Maxim Saplin
|
7
|
+
Author-email: support@skydeck.ai
|
8
|
+
License: MIT
|
9
|
+
Project-URL: Homepage, https://github.com/maxim-saplin/mcp_safe_local_python_executor/tree/main
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
11
|
+
Classifier: Intended Audience :: Developers
|
12
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
17
|
+
Classifier: Operating System :: OS Independent
|
18
|
+
Requires-Python: >=3.6
|
19
|
+
Description-Content-Type: text/markdown
|
20
|
+
License-File: LICENSE
|
21
|
+
Requires-Dist: mcp[cli]>=1.5.0
|
22
|
+
Requires-Dist: smolagents==1.12.0
|
23
|
+
Dynamic: author-email
|
24
|
+
Dynamic: license-file
|
25
|
+
Dynamic: requires-python
|
26
|
+
|
27
|
+
# Safe Local Python Executor
|
28
|
+
|
29
|
+
An MCP server (stdio transport) that wraps Hugging Face's [`LocalPythonExecutor`](https://github.com/huggingface/smolagents/blob/main/src/smolagents/local_python_executor.py)
|
30
|
+
(from the [`smolagents`](https://huggingface.co/docs/smolagents/en/index) framework). It is a custom Python runtime that
|
31
|
+
provides basic isolation/security when running Python code generated by LLMs locally. It does not require Docker or VM.
|
32
|
+
This package allows to expose the Python executor via MCP (Model Context Protocol) as a tool for LLM apps like Claude Desktop, Cursor or any other MCP compatible client.
|
33
|
+
In case of Claude Desktop this tool is an easy way to add a missing Code Interpreter (available as a plugin in ChatGPT for quite a while already).
|
34
|
+
|
35
|
+
<img width="1032" alt="image" src="https://github.com/user-attachments/assets/3b820bfc-970a-4315-8f2d-970591c6fdae" />
|
36
|
+
|
37
|
+
## Features
|
38
|
+
|
39
|
+
- Exposes `run_python` tool
|
40
|
+
- Safer execution of Python code compared to direct use of Python `eva()l`
|
41
|
+
- Ran via uv in Python venv
|
42
|
+
- No file I/O ops are allowed
|
43
|
+
- Restricted list of imports
|
44
|
+
- collections
|
45
|
+
- datetime
|
46
|
+
- itertools
|
47
|
+
- math
|
48
|
+
- queue
|
49
|
+
- random
|
50
|
+
- re
|
51
|
+
- stat
|
52
|
+
- statistics
|
53
|
+
- time
|
54
|
+
- unicodedata
|
55
|
+
|
56
|
+
## Security
|
57
|
+
|
58
|
+
Be careful with execution of code produced by LLM on your machine, stay away from MCP servers that run Python via command line or using `eval()`. The safest option is using a VM or a docker container, though it requires some effort to set-up, consumes resources/slower. There're 3rd party servcices providing Python runtime, though they require registration, API keys etc.
|
59
|
+
|
60
|
+
`LocalPythonExecutor` provides a good balance between direct use of local Python environment (which is easier to set-up) AND remote execution in Dokcer container or a VM/3rd party service (which is safe). Hugginng Face team has invested time into creating a quick and safe option to run LLM generated code used by their code agents. This MCP server builds upon it:
|
61
|
+
|
62
|
+
>To add a first layer of security, code execution in smolagents is not performed by the vanilla Python interpreter. We have re-built a more secure LocalPythonExecutor from the ground up.
|
63
|
+
|
64
|
+
Read more [here](https://huggingface.co/docs/smolagents/en/tutorials/secure_code_execution#local-code-execution).
|
65
|
+
|
66
|
+
## Installation and Execution
|
67
|
+
|
68
|
+
1. Install `uv` (e.h. `brew install uv` on macOS or use [official docs](https://docs.astral.sh/uv/getting-started/installation/#__tabbed_1_2))
|
69
|
+
2. Clone the repo, change the directory `cd mcp_safe_local_python_executor`
|
70
|
+
3. The server can be started via command line `uv run mcp_server.py`, venv will be created automatically, depedencies (smollagents, mcp) will be installed
|
71
|
+
|
72
|
+
|
73
|
+
## Configuring Claude Desktop
|
74
|
+
|
75
|
+
1. Make sure you have Claude for Desktop installed (download from [claude.ai](https://claude.ai/desktop))
|
76
|
+
2. Edit your Claude for Desktop configuration file:
|
77
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
78
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
79
|
+
- Or open Claude Desktop -> Settings -> Developer -> click "Edit Config" button
|
80
|
+
|
81
|
+
3. Add the following configuration:
|
82
|
+
|
83
|
+
```json
|
84
|
+
{
|
85
|
+
"mcpServers": {
|
86
|
+
"safe-local-python-executor": {
|
87
|
+
"command": "uv",
|
88
|
+
"args": [
|
89
|
+
"--directory",
|
90
|
+
"/path/to/mcp_local_python_executor/",
|
91
|
+
"run",
|
92
|
+
"mcp_server.py"
|
93
|
+
]
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
```
|
98
|
+
|
99
|
+
4. Restart Claude for Desktop
|
100
|
+
5. The Python executor tool will now be available in Claude (you'll see hammer icon in the message input field)
|
101
|
+
|
102
|
+
## Example Prompts
|
103
|
+
|
104
|
+
Once configured, you can use prompts like:
|
105
|
+
|
106
|
+
- "Calculate the factorial of 5 using Python"
|
107
|
+
- "Create a list of prime numbers up to 100"
|
108
|
+
- "Solve this equation (use Python): x^2 + 5x + 6 = 0"
|
109
|
+
|
110
|
+
|
111
|
+
## Development
|
112
|
+
|
113
|
+
Clone the repo. Use `uv` to create venv, install dev dependencies, run tests:
|
114
|
+
|
115
|
+
```
|
116
|
+
uv venv .venv
|
117
|
+
uv sync --group dev
|
118
|
+
python -m pytest tests/
|
119
|
+
```
|
120
|
+
|
121
|
+
-----------------------
|
122
|
+
|
123
|
+
<a href="https://glama.ai/mcp/servers/@maxim-saplin/mcp_safe_local_python_executor">
|
124
|
+
<img width="380" height="200" src="https://glama.ai/mcp/servers/@maxim-saplin/mcp_safe_local_python_executor/badge" />
|
125
|
+
</a>
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Safe Local Python Executor
|
2
|
+
|
3
|
+
An MCP server (stdio transport) that wraps Hugging Face's [`LocalPythonExecutor`](https://github.com/huggingface/smolagents/blob/main/src/smolagents/local_python_executor.py)
|
4
|
+
(from the [`smolagents`](https://huggingface.co/docs/smolagents/en/index) framework). It is a custom Python runtime that
|
5
|
+
provides basic isolation/security when running Python code generated by LLMs locally. It does not require Docker or VM.
|
6
|
+
This package allows to expose the Python executor via MCP (Model Context Protocol) as a tool for LLM apps like Claude Desktop, Cursor or any other MCP compatible client.
|
7
|
+
In case of Claude Desktop this tool is an easy way to add a missing Code Interpreter (available as a plugin in ChatGPT for quite a while already).
|
8
|
+
|
9
|
+
<img width="1032" alt="image" src="https://github.com/user-attachments/assets/3b820bfc-970a-4315-8f2d-970591c6fdae" />
|
10
|
+
|
11
|
+
## Features
|
12
|
+
|
13
|
+
- Exposes `run_python` tool
|
14
|
+
- Safer execution of Python code compared to direct use of Python `eva()l`
|
15
|
+
- Ran via uv in Python venv
|
16
|
+
- No file I/O ops are allowed
|
17
|
+
- Restricted list of imports
|
18
|
+
- collections
|
19
|
+
- datetime
|
20
|
+
- itertools
|
21
|
+
- math
|
22
|
+
- queue
|
23
|
+
- random
|
24
|
+
- re
|
25
|
+
- stat
|
26
|
+
- statistics
|
27
|
+
- time
|
28
|
+
- unicodedata
|
29
|
+
|
30
|
+
## Security
|
31
|
+
|
32
|
+
Be careful with execution of code produced by LLM on your machine, stay away from MCP servers that run Python via command line or using `eval()`. The safest option is using a VM or a docker container, though it requires some effort to set-up, consumes resources/slower. There're 3rd party servcices providing Python runtime, though they require registration, API keys etc.
|
33
|
+
|
34
|
+
`LocalPythonExecutor` provides a good balance between direct use of local Python environment (which is easier to set-up) AND remote execution in Dokcer container or a VM/3rd party service (which is safe). Hugginng Face team has invested time into creating a quick and safe option to run LLM generated code used by their code agents. This MCP server builds upon it:
|
35
|
+
|
36
|
+
>To add a first layer of security, code execution in smolagents is not performed by the vanilla Python interpreter. We have re-built a more secure LocalPythonExecutor from the ground up.
|
37
|
+
|
38
|
+
Read more [here](https://huggingface.co/docs/smolagents/en/tutorials/secure_code_execution#local-code-execution).
|
39
|
+
|
40
|
+
## Installation and Execution
|
41
|
+
|
42
|
+
1. Install `uv` (e.h. `brew install uv` on macOS or use [official docs](https://docs.astral.sh/uv/getting-started/installation/#__tabbed_1_2))
|
43
|
+
2. Clone the repo, change the directory `cd mcp_safe_local_python_executor`
|
44
|
+
3. The server can be started via command line `uv run mcp_server.py`, venv will be created automatically, depedencies (smollagents, mcp) will be installed
|
45
|
+
|
46
|
+
|
47
|
+
## Configuring Claude Desktop
|
48
|
+
|
49
|
+
1. Make sure you have Claude for Desktop installed (download from [claude.ai](https://claude.ai/desktop))
|
50
|
+
2. Edit your Claude for Desktop configuration file:
|
51
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
52
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
53
|
+
- Or open Claude Desktop -> Settings -> Developer -> click "Edit Config" button
|
54
|
+
|
55
|
+
3. Add the following configuration:
|
56
|
+
|
57
|
+
```json
|
58
|
+
{
|
59
|
+
"mcpServers": {
|
60
|
+
"safe-local-python-executor": {
|
61
|
+
"command": "uv",
|
62
|
+
"args": [
|
63
|
+
"--directory",
|
64
|
+
"/path/to/mcp_local_python_executor/",
|
65
|
+
"run",
|
66
|
+
"mcp_server.py"
|
67
|
+
]
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
```
|
72
|
+
|
73
|
+
4. Restart Claude for Desktop
|
74
|
+
5. The Python executor tool will now be available in Claude (you'll see hammer icon in the message input field)
|
75
|
+
|
76
|
+
## Example Prompts
|
77
|
+
|
78
|
+
Once configured, you can use prompts like:
|
79
|
+
|
80
|
+
- "Calculate the factorial of 5 using Python"
|
81
|
+
- "Create a list of prime numbers up to 100"
|
82
|
+
- "Solve this equation (use Python): x^2 + 5x + 6 = 0"
|
83
|
+
|
84
|
+
|
85
|
+
## Development
|
86
|
+
|
87
|
+
Clone the repo. Use `uv` to create venv, install dev dependencies, run tests:
|
88
|
+
|
89
|
+
```
|
90
|
+
uv venv .venv
|
91
|
+
uv sync --group dev
|
92
|
+
python -m pytest tests/
|
93
|
+
```
|
94
|
+
|
95
|
+
-----------------------
|
96
|
+
|
97
|
+
<a href="https://glama.ai/mcp/servers/@maxim-saplin/mcp_safe_local_python_executor">
|
98
|
+
<img width="380" height="200" src="https://glama.ai/mcp/servers/@maxim-saplin/mcp_safe_local_python_executor/badge" />
|
99
|
+
</a>
|
mseep_mcp_safe_local_python_executor-0.1.0/mseep_mcp_safe_local_python_executor.egg-info/PKG-INFO
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: mseep-mcp_safe_local_python_executor
|
3
|
+
Version: 0.1.0
|
4
|
+
Summary: MCP server exposing tool for a safe local Python code execution
|
5
|
+
Home-page:
|
6
|
+
Author: Maxim Saplin
|
7
|
+
Author-email: support@skydeck.ai
|
8
|
+
License: MIT
|
9
|
+
Project-URL: Homepage, https://github.com/maxim-saplin/mcp_safe_local_python_executor/tree/main
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
11
|
+
Classifier: Intended Audience :: Developers
|
12
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
17
|
+
Classifier: Operating System :: OS Independent
|
18
|
+
Requires-Python: >=3.6
|
19
|
+
Description-Content-Type: text/markdown
|
20
|
+
License-File: LICENSE
|
21
|
+
Requires-Dist: mcp[cli]>=1.5.0
|
22
|
+
Requires-Dist: smolagents==1.12.0
|
23
|
+
Dynamic: author-email
|
24
|
+
Dynamic: license-file
|
25
|
+
Dynamic: requires-python
|
26
|
+
|
27
|
+
# Safe Local Python Executor
|
28
|
+
|
29
|
+
An MCP server (stdio transport) that wraps Hugging Face's [`LocalPythonExecutor`](https://github.com/huggingface/smolagents/blob/main/src/smolagents/local_python_executor.py)
|
30
|
+
(from the [`smolagents`](https://huggingface.co/docs/smolagents/en/index) framework). It is a custom Python runtime that
|
31
|
+
provides basic isolation/security when running Python code generated by LLMs locally. It does not require Docker or VM.
|
32
|
+
This package allows to expose the Python executor via MCP (Model Context Protocol) as a tool for LLM apps like Claude Desktop, Cursor or any other MCP compatible client.
|
33
|
+
In case of Claude Desktop this tool is an easy way to add a missing Code Interpreter (available as a plugin in ChatGPT for quite a while already).
|
34
|
+
|
35
|
+
<img width="1032" alt="image" src="https://github.com/user-attachments/assets/3b820bfc-970a-4315-8f2d-970591c6fdae" />
|
36
|
+
|
37
|
+
## Features
|
38
|
+
|
39
|
+
- Exposes `run_python` tool
|
40
|
+
- Safer execution of Python code compared to direct use of Python `eva()l`
|
41
|
+
- Ran via uv in Python venv
|
42
|
+
- No file I/O ops are allowed
|
43
|
+
- Restricted list of imports
|
44
|
+
- collections
|
45
|
+
- datetime
|
46
|
+
- itertools
|
47
|
+
- math
|
48
|
+
- queue
|
49
|
+
- random
|
50
|
+
- re
|
51
|
+
- stat
|
52
|
+
- statistics
|
53
|
+
- time
|
54
|
+
- unicodedata
|
55
|
+
|
56
|
+
## Security
|
57
|
+
|
58
|
+
Be careful with execution of code produced by LLM on your machine, stay away from MCP servers that run Python via command line or using `eval()`. The safest option is using a VM or a docker container, though it requires some effort to set-up, consumes resources/slower. There're 3rd party servcices providing Python runtime, though they require registration, API keys etc.
|
59
|
+
|
60
|
+
`LocalPythonExecutor` provides a good balance between direct use of local Python environment (which is easier to set-up) AND remote execution in Dokcer container or a VM/3rd party service (which is safe). Hugginng Face team has invested time into creating a quick and safe option to run LLM generated code used by their code agents. This MCP server builds upon it:
|
61
|
+
|
62
|
+
>To add a first layer of security, code execution in smolagents is not performed by the vanilla Python interpreter. We have re-built a more secure LocalPythonExecutor from the ground up.
|
63
|
+
|
64
|
+
Read more [here](https://huggingface.co/docs/smolagents/en/tutorials/secure_code_execution#local-code-execution).
|
65
|
+
|
66
|
+
## Installation and Execution
|
67
|
+
|
68
|
+
1. Install `uv` (e.h. `brew install uv` on macOS or use [official docs](https://docs.astral.sh/uv/getting-started/installation/#__tabbed_1_2))
|
69
|
+
2. Clone the repo, change the directory `cd mcp_safe_local_python_executor`
|
70
|
+
3. The server can be started via command line `uv run mcp_server.py`, venv will be created automatically, depedencies (smollagents, mcp) will be installed
|
71
|
+
|
72
|
+
|
73
|
+
## Configuring Claude Desktop
|
74
|
+
|
75
|
+
1. Make sure you have Claude for Desktop installed (download from [claude.ai](https://claude.ai/desktop))
|
76
|
+
2. Edit your Claude for Desktop configuration file:
|
77
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
78
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
79
|
+
- Or open Claude Desktop -> Settings -> Developer -> click "Edit Config" button
|
80
|
+
|
81
|
+
3. Add the following configuration:
|
82
|
+
|
83
|
+
```json
|
84
|
+
{
|
85
|
+
"mcpServers": {
|
86
|
+
"safe-local-python-executor": {
|
87
|
+
"command": "uv",
|
88
|
+
"args": [
|
89
|
+
"--directory",
|
90
|
+
"/path/to/mcp_local_python_executor/",
|
91
|
+
"run",
|
92
|
+
"mcp_server.py"
|
93
|
+
]
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
```
|
98
|
+
|
99
|
+
4. Restart Claude for Desktop
|
100
|
+
5. The Python executor tool will now be available in Claude (you'll see hammer icon in the message input field)
|
101
|
+
|
102
|
+
## Example Prompts
|
103
|
+
|
104
|
+
Once configured, you can use prompts like:
|
105
|
+
|
106
|
+
- "Calculate the factorial of 5 using Python"
|
107
|
+
- "Create a list of prime numbers up to 100"
|
108
|
+
- "Solve this equation (use Python): x^2 + 5x + 6 = 0"
|
109
|
+
|
110
|
+
|
111
|
+
## Development
|
112
|
+
|
113
|
+
Clone the repo. Use `uv` to create venv, install dev dependencies, run tests:
|
114
|
+
|
115
|
+
```
|
116
|
+
uv venv .venv
|
117
|
+
uv sync --group dev
|
118
|
+
python -m pytest tests/
|
119
|
+
```
|
120
|
+
|
121
|
+
-----------------------
|
122
|
+
|
123
|
+
<a href="https://glama.ai/mcp/servers/@maxim-saplin/mcp_safe_local_python_executor">
|
124
|
+
<img width="380" height="200" src="https://glama.ai/mcp/servers/@maxim-saplin/mcp_safe_local_python_executor/badge" />
|
125
|
+
</a>
|
mseep_mcp_safe_local_python_executor-0.1.0/mseep_mcp_safe_local_python_executor.egg-info/SOURCES.txt
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
LICENSE
|
2
|
+
README.md
|
3
|
+
pyproject.toml
|
4
|
+
setup.py
|
5
|
+
mseep_mcp_safe_local_python_executor.egg-info/PKG-INFO
|
6
|
+
mseep_mcp_safe_local_python_executor.egg-info/SOURCES.txt
|
7
|
+
mseep_mcp_safe_local_python_executor.egg-info/dependency_links.txt
|
8
|
+
mseep_mcp_safe_local_python_executor.egg-info/requires.txt
|
9
|
+
mseep_mcp_safe_local_python_executor.egg-info/top_level.txt
|
10
|
+
tests/test_local_python_executor.py
|
11
|
+
tests/test_mcp_server.py
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
[build-system]
|
2
|
+
requires = [
|
3
|
+
"setuptools>=42",
|
4
|
+
"wheel",
|
5
|
+
]
|
6
|
+
build-backend = "setuptools.build_meta"
|
7
|
+
|
8
|
+
[project]
|
9
|
+
name = "mseep-mcp_safe_local_python_executor"
|
10
|
+
version = "0.1.0"
|
11
|
+
description = "MCP server exposing tool for a safe local Python code execution"
|
12
|
+
readme = "README.md"
|
13
|
+
authors = [
|
14
|
+
{ name = "Maxim Saplin" },
|
15
|
+
]
|
16
|
+
requires-python = ">=3.10"
|
17
|
+
classifiers = [
|
18
|
+
"Development Status :: 3 - Alpha",
|
19
|
+
"Intended Audience :: Developers",
|
20
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
21
|
+
"Programming Language :: Python :: 3.10",
|
22
|
+
"Programming Language :: Python :: 3.11",
|
23
|
+
"Programming Language :: Python :: 3.12",
|
24
|
+
"Programming Language :: Python :: 3.13",
|
25
|
+
"Operating System :: OS Independent",
|
26
|
+
]
|
27
|
+
dependencies = [
|
28
|
+
"mcp[cli]>=1.5.0",
|
29
|
+
"smolagents==1.12.0",
|
30
|
+
]
|
31
|
+
|
32
|
+
[project.license]
|
33
|
+
text = "MIT"
|
34
|
+
|
35
|
+
[project.urls]
|
36
|
+
Homepage = "https://github.com/maxim-saplin/mcp_safe_local_python_executor/tree/main"
|
37
|
+
|
38
|
+
[dependency-groups]
|
39
|
+
dev = [
|
40
|
+
"pytest>=7.0.0",
|
41
|
+
"pytest-asyncio>=0.21.0",
|
42
|
+
]
|
43
|
+
|
44
|
+
[tool.setuptools.packages.find]
|
45
|
+
where = [
|
46
|
+
".",
|
47
|
+
]
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
from setuptools import setup, find_packages
|
3
|
+
|
4
|
+
setup(
|
5
|
+
name="mseep-mcp_safe_local_python_executor",
|
6
|
+
version="0.1.0",
|
7
|
+
description="MCP server exposing tool for a safe local Python code execution",
|
8
|
+
author="mseep",
|
9
|
+
author_email="support@skydeck.ai",
|
10
|
+
url="",
|
11
|
+
packages=find_packages(),
|
12
|
+
classifiers=[
|
13
|
+
"Programming Language :: Python :: 3",
|
14
|
+
"License :: OSI Approved :: MIT License",
|
15
|
+
"Operating System :: OS Independent",
|
16
|
+
],
|
17
|
+
python_requires=">=3.6",
|
18
|
+
install_requires=['mcp[cli]>=1.5.0', 'smolagents==1.12.0'],
|
19
|
+
keywords=["mseep"] + [],
|
20
|
+
)
|
@@ -0,0 +1,92 @@
|
|
1
|
+
"""
|
2
|
+
Smoke tests for the LocalPythonExecutor.
|
3
|
+
"""
|
4
|
+
|
5
|
+
import os
|
6
|
+
import sys
|
7
|
+
import pytest
|
8
|
+
|
9
|
+
# Add the parent directory to the path
|
10
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
11
|
+
|
12
|
+
# Import the executor
|
13
|
+
from smolagents.local_python_executor import LocalPythonExecutor
|
14
|
+
|
15
|
+
|
16
|
+
def test_simple_arithmetic():
|
17
|
+
"""Test that simple arithmetic works correctly."""
|
18
|
+
executor = LocalPythonExecutor(additional_authorized_imports=[])
|
19
|
+
|
20
|
+
code = "2 + 2"
|
21
|
+
result, logs, _ = executor(code)
|
22
|
+
|
23
|
+
assert result == 4
|
24
|
+
assert logs == ""
|
25
|
+
|
26
|
+
|
27
|
+
def test_variable_assignment():
|
28
|
+
"""Test that variable assignment works correctly."""
|
29
|
+
executor = LocalPythonExecutor(additional_authorized_imports=[])
|
30
|
+
|
31
|
+
code = """
|
32
|
+
x = 10
|
33
|
+
y = 20
|
34
|
+
result = x + y
|
35
|
+
"""
|
36
|
+
result, logs, _ = executor(code)
|
37
|
+
|
38
|
+
assert result == 30
|
39
|
+
assert logs == ""
|
40
|
+
|
41
|
+
|
42
|
+
def test_expression_result():
|
43
|
+
"""Test that the last expression is returned as result."""
|
44
|
+
executor = LocalPythonExecutor(additional_authorized_imports=[])
|
45
|
+
|
46
|
+
code = """
|
47
|
+
x = 5
|
48
|
+
x * 2
|
49
|
+
"""
|
50
|
+
result, logs, _ = executor(code)
|
51
|
+
|
52
|
+
assert result == 10
|
53
|
+
assert logs == ""
|
54
|
+
|
55
|
+
|
56
|
+
def test_array_operations():
|
57
|
+
"""Test that array operations work correctly."""
|
58
|
+
executor = LocalPythonExecutor(additional_authorized_imports=[])
|
59
|
+
|
60
|
+
code = """
|
61
|
+
numbers = [1, 2, 3, 4, 5]
|
62
|
+
total = 0
|
63
|
+
for num in numbers:
|
64
|
+
total += num
|
65
|
+
total
|
66
|
+
"""
|
67
|
+
result, logs, _ = executor(code)
|
68
|
+
|
69
|
+
assert result == 15
|
70
|
+
assert logs == ""
|
71
|
+
|
72
|
+
|
73
|
+
def test_filesystem_access_fails():
|
74
|
+
"""Test that filesystem access is blocked"""
|
75
|
+
print("\nTest: Filesystem access attempt")
|
76
|
+
code = """
|
77
|
+
import os
|
78
|
+
files = os.listdir('.')
|
79
|
+
files
|
80
|
+
"""
|
81
|
+
executor = LocalPythonExecutor(additional_authorized_imports=[])
|
82
|
+
with pytest.raises(Exception) as exc_info:
|
83
|
+
executor(code)
|
84
|
+
assert 'InterpreterError: Import of os is not allowed' in str(exc_info.value)
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
if __name__ == "__main__":
|
89
|
+
if len(sys.argv) > 1 and sys.argv[1] == "--smoke":
|
90
|
+
run_smoke_tests()
|
91
|
+
else:
|
92
|
+
pytest.main(["-v", __file__])
|
@@ -0,0 +1,46 @@
|
|
1
|
+
"""
|
2
|
+
Tests for the MCP server.
|
3
|
+
"""
|
4
|
+
|
5
|
+
import os
|
6
|
+
import sys
|
7
|
+
import pytest
|
8
|
+
|
9
|
+
# Add the parent directory to the path
|
10
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
11
|
+
|
12
|
+
# Import the MCP server module
|
13
|
+
import mcp_server
|
14
|
+
|
15
|
+
|
16
|
+
@pytest.mark.asyncio
|
17
|
+
async def test_run_python():
|
18
|
+
"""Test that the run_python tool works correctly."""
|
19
|
+
# Test basic arithmetic
|
20
|
+
result = await mcp_server.run_python("result = 2 + 2")
|
21
|
+
assert result["result"] == 4
|
22
|
+
|
23
|
+
# Test math module functionality
|
24
|
+
result = await mcp_server.run_python("import math\nresult = math.sqrt(16)")
|
25
|
+
assert result["result"] == 4.0
|
26
|
+
|
27
|
+
|
28
|
+
@pytest.mark.asyncio
|
29
|
+
async def test_prime_numbers():
|
30
|
+
"""Test generating a list of prime numbers."""
|
31
|
+
code = """
|
32
|
+
def is_prime(n):
|
33
|
+
if n < 2:
|
34
|
+
return False
|
35
|
+
for i in range(2, int(n**0.5) + 1):
|
36
|
+
if n % i == 0:
|
37
|
+
return False
|
38
|
+
return True
|
39
|
+
|
40
|
+
primes = [num for num in range(2, 101) if is_prime(num)]
|
41
|
+
result = primes"""
|
42
|
+
|
43
|
+
result = await mcp_server.run_python(code)
|
44
|
+
expected_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
|
45
|
+
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
|
46
|
+
assert result["result"] == expected_primes
|