# Directory Structure
```
├── .gitattributes
├── .gitignore
├── .VSCodeCounter
│ ├── 2025-03-28_08-28-01
│ │ ├── details.md
│ │ ├── diff-details.md
│ │ ├── diff.csv
│ │ ├── diff.md
│ │ ├── diff.txt
│ │ ├── results.csv
│ │ ├── results.json
│ │ ├── results.md
│ │ └── results.txt
│ └── 2025-05-01_18-42-30
│ ├── details.md
│ ├── diff-details.md
│ ├── diff.csv
│ ├── diff.md
│ ├── diff.txt
│ ├── results.csv
│ ├── results.json
│ ├── results.md
│ └── results.txt
├── Dockerfile
├── LICENSE
├── mcp_server.py
├── pyproject.toml
├── README.md
├── smithery.yaml
└── tests
├── test_local_python_executor.py
└── test_mcp_server.py
```
# Files
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
```
# Auto detect text files and perform LF normalization
* text=auto
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Virtual Environment
.env
.venv
env/
venv/
ENV/
# IDE
.idea/
.vscode/
*.swp
*.swo
# Testing
.coverage
htmlcov/
.pytest_cache/
.mypy_cache/
# Distribution
dist/
build/
*.egg-info/
uv.lock
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
# Safe Local Python Executor
An MCP server (stdio transport) that wraps Hugging Face's [`LocalPythonExecutor`](https://github.com/huggingface/smolagents/blob/main/src/smolagents/local_python_executor.py)
(from the [`smolagents`](https://huggingface.co/docs/smolagents/en/index) framework). It is a custom Python runtime that
provides basic isolation/security when running Python code generated by LLMs locally. It does not require Docker or VM.
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.
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).
<img width="1032" alt="image" src="https://github.com/user-attachments/assets/3b820bfc-970a-4315-8f2d-970591c6fdae" />
## Features
- Exposes `run_python` tool
- Safer execution of Python code compared to direct use of Python `eva()l`
- Ran via uv in Python venv
- No file I/O ops are allowed
- Restricted list of imports
- collections
- datetime
- itertools
- math
- queue
- random
- re
- stat
- statistics
- time
- unicodedata
## Security
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.
`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:
>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.
Read more [here](https://huggingface.co/docs/smolagents/en/tutorials/secure_code_execution#local-code-execution).
## Installation and Execution
### Installing via Smithery
To install Safe Local Python Executor for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@maxim-saplin/mcp_safe_local_python_executor):
```bash
npx -y @smithery/cli install @maxim-saplin/mcp_safe_local_python_executor --client claude
```
### Installing Manually
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))
2. Clone the repo, change the directory `cd mcp_safe_local_python_executor`
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
## Configuring Claude Desktop
1. Make sure you have Claude for Desktop installed (download from [claude.ai](https://claude.ai/desktop))
2. Edit your Claude for Desktop configuration file:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
- Or open Claude Desktop -> Settings -> Developer -> click "Edit Config" button
3. Add the following configuration:
```json
{
"mcpServers": {
"safe-local-python-executor": {
"command": "uv",
"args": [
"--directory",
"/path/to/mcp_local_python_executor/",
"run",
"mcp_server.py"
]
}
}
}
```
4. Restart Claude for Desktop
5. The Python executor tool will now be available in Claude (you'll see hammer icon in the message input field)
## Example Prompts
Once configured, you can use prompts like:
- "Calculate the factorial of 5 using Python"
- "Create a list of prime numbers up to 100"
- "Solve this equation (use Python): x^2 + 5x + 6 = 0"
## Development
Clone the repo. Use `uv` to create venv, install dev dependencies, run tests:
```
uv venv .venv
uv sync --group dev
python -m pytest tests/
```
-----------------------
<a href="https://glama.ai/mcp/servers/@maxim-saplin/mcp_safe_local_python_executor">
<img width="380" height="200" src="https://glama.ai/mcp/servers/@maxim-saplin/mcp_safe_local_python_executor/badge" />
</a>
[](https://smithery.ai/server/@maxim-saplin/mcp_safe_local_python_executor)
[](https://mseep.ai/app/maxim-saplin-mcp-safe-local-python-executor)
```
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
# Generated by https://smithery.ai. See: https://smithery.ai/docs/build/project-config
FROM ghcr.io/astral-sh/uv:alpine
# Install build dependencies
WORKDIR /app
# Copy project files
COPY . .
# Pre-create virtual environment and install dependencies to avoid runtime downloads
RUN uv venv .venv \
&& uv sync --no-dev
# Default command to run the MCP server
CMD ["uv", "run", "mcp_server.py"]
```
--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------
```yaml
# Smithery configuration file: https://smithery.ai/docs/build/project-config
startCommand:
type: stdio
commandFunction:
# A JS function that produces the CLI command based on the given config to start the MCP on stdio.
|-
(config) => ({ command: 'uv', args: ['run', 'mcp_server.py'], env: {} })
configSchema:
# JSON Schema defining the configuration options for the MCP.
type: object
properties: {}
exampleConfig: {}
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-05-01_18-42-30/results.csv:
--------------------------------------------------------------------------------
```
"filename", "language", "Markdown", "Python", "comment", "blank", "total"
"/Users/admin/src/mcp_safe_local_python_executor/README.md", "Markdown", 73, 0, 0, 27, 100
"/Users/admin/src/mcp_safe_local_python_executor/mcp_server.py", "Python", 0, 59, 3, 18, 80
"/Users/admin/src/mcp_safe_local_python_executor/tests/test_local_python_executor.py", "Python", 0, 66, 2, 24, 92
"/Users/admin/src/mcp_safe_local_python_executor/tests/test_mcp_server.py", "Python", 0, 32, 4, 10, 46
"Total", "-", 73, 157, 9, 79, 318
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-05-01_18-42-30/results.json:
--------------------------------------------------------------------------------
```json
{"file:///Users/admin/src/mcp_safe_local_python_executor/README.md":{"language":"Markdown","code":73,"comment":0,"blank":27},"file:///Users/admin/src/mcp_safe_local_python_executor/mcp_server.py":{"language":"Python","code":59,"comment":3,"blank":18},"file:///Users/admin/src/mcp_safe_local_python_executor/tests/test_local_python_executor.py":{"language":"Python","code":66,"comment":2,"blank":24},"file:///Users/admin/src/mcp_safe_local_python_executor/tests/test_mcp_server.py":{"language":"Python","code":32,"comment":4,"blank":10}}
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-05-01_18-42-30/results.md:
--------------------------------------------------------------------------------
```markdown
# Summary
Date : 2025-05-01 18:42:30
Directory /Users/admin/src/mcp_safe_local_python_executor
Total : 4 files, 230 codes, 9 comments, 79 blanks, all 318 lines
Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
## Languages
| language | files | code | comment | blank | total |
| :--- | ---: | ---: | ---: | ---: | ---: |
| Python | 3 | 157 | 9 | 52 | 218 |
| Markdown | 1 | 73 | 0 | 27 | 100 |
## Directories
| path | files | code | comment | blank | total |
| :--- | ---: | ---: | ---: | ---: | ---: |
| . | 4 | 230 | 9 | 79 | 318 |
| . (Files) | 2 | 132 | 3 | 45 | 180 |
| tests | 2 | 98 | 6 | 34 | 138 |
Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-05-01_18-42-30/details.md:
--------------------------------------------------------------------------------
```markdown
# Details
Date : 2025-05-01 18:42:30
Directory /Users/admin/src/mcp_safe_local_python_executor
Total : 4 files, 230 codes, 9 comments, 79 blanks, all 318 lines
[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
## Files
| filename | language | code | comment | blank | total |
| :--- | :--- | ---: | ---: | ---: | ---: |
| [README.md](/README.md) | Markdown | 73 | 0 | 27 | 100 |
| [mcp\_server.py](/mcp_server.py) | Python | 59 | 3 | 18 | 80 |
| [tests/test\_local\_python\_executor.py](/tests/test_local_python_executor.py) | Python | 66 | 2 | 24 | 92 |
| [tests/test\_mcp\_server.py](/tests/test_mcp_server.py) | Python | 32 | 4 | 10 | 46 |
[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-03-28_08-28-01/results.md:
--------------------------------------------------------------------------------
```markdown
# Summary
Date : 2025-03-28 08:28:01
Directory /Users/admin/src/mcp_safe_local_python_executor
Total : 9 files, 859 codes, 45 comments, 158 blanks, all 1062 lines
Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
## Languages
| language | files | code | comment | blank | total |
| :--- | ---: | ---: | ---: | ---: | ---: |
| Python | 7 | 753 | 45 | 122 | 920 |
| Markdown | 1 | 99 | 0 | 36 | 135 |
| pip requirements | 1 | 7 | 0 | 0 | 7 |
## Directories
| path | files | code | comment | blank | total |
| :--- | ---: | ---: | ---: | ---: | ---: |
| . | 9 | 859 | 45 | 158 | 1,062 |
| . (Files) | 5 | 677 | 13 | 110 | 800 |
| examples | 3 | 163 | 24 | 37 | 224 |
| tests | 1 | 19 | 8 | 11 | 38 |
Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-03-28_08-28-01/diff.md:
--------------------------------------------------------------------------------
```markdown
# Diff Summary
Date : 2025-03-28 08:28:01
Directory /Users/admin/src/mcp_safe_local_python_executor
Total : 11 files, 583 codes, 27 comments, 76 blanks, all 686 lines
[Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md)
## Languages
| language | files | code | comment | blank | total |
| :--- | ---: | ---: | ---: | ---: | ---: |
| Python | 9 | 540 | 27 | 60 | 627 |
| Markdown | 1 | 36 | 0 | 16 | 52 |
| pip requirements | 1 | 7 | 0 | 0 | 7 |
## Directories
| path | files | code | comment | blank | total |
| :--- | ---: | ---: | ---: | ---: | ---: |
| . | 11 | 583 | 27 | 76 | 686 |
| . (Files) | 5 | 555 | 10 | 72 | 637 |
| examples | 3 | 163 | 24 | 37 | 224 |
| tests | 3 | -135 | -7 | -33 | -175 |
[Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md)
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-05-01_18-42-30/diff.md:
--------------------------------------------------------------------------------
```markdown
# Diff Summary
Date : 2025-05-01 18:42:30
Directory /Users/admin/src/mcp_safe_local_python_executor
Total : 10 files, -629 codes, -36 comments, -79 blanks, all -744 lines
[Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md)
## Languages
| language | files | code | comment | blank | total |
| :--- | ---: | ---: | ---: | ---: | ---: |
| pip requirements | 1 | -7 | 0 | 0 | -7 |
| Markdown | 1 | -26 | 0 | -9 | -35 |
| Python | 8 | -596 | -36 | -70 | -702 |
## Directories
| path | files | code | comment | blank | total |
| :--- | ---: | ---: | ---: | ---: | ---: |
| . | 10 | -629 | -36 | -79 | -744 |
| . (Files) | 5 | -545 | -10 | -65 | -620 |
| examples | 3 | -163 | -24 | -37 | -224 |
| tests | 2 | 79 | -2 | 23 | 100 |
[Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md)
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-03-28_08-28-01/results.csv:
--------------------------------------------------------------------------------
```
"filename", "language", "Python", "Markdown", "pip requirements", "comment", "blank", "total"
"/Users/admin/src/mcp_safe_local_python_executor/README.md", "Markdown", 0, 99, 0, 0, 36, 135
"/Users/admin/src/mcp_safe_local_python_executor/examples/run_executor.py", "Python", 24, 0, 0, 4, 7, 35
"/Users/admin/src/mcp_safe_local_python_executor/examples/run_mcp_server.py", "Python", 58, 0, 0, 6, 11, 75
"/Users/admin/src/mcp_safe_local_python_executor/examples/test_mcp_client.py", "Python", 81, 0, 0, 14, 19, 114
"/Users/admin/src/mcp_safe_local_python_executor/executor.py", "Python", 486, 0, 0, 1, 51, 538
"/Users/admin/src/mcp_safe_local_python_executor/mcp_server.py", "Python", 56, 0, 0, 12, 21, 89
"/Users/admin/src/mcp_safe_local_python_executor/requirements.txt", "pip requirements", 0, 0, 7, 0, 0, 7
"/Users/admin/src/mcp_safe_local_python_executor/setup.py", "Python", 29, 0, 0, 0, 2, 31
"/Users/admin/src/mcp_safe_local_python_executor/tests/test_mcp_server.py", "Python", 19, 0, 0, 8, 11, 38
"Total", "-", 753, 99, 7, 45, 158, 1062
```
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
```toml
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "mcp_safe_local_python_executor"
version = "0.1.0"
description = "MCP server exposing tool for a safe local Python code execution"
readme = "README.md"
authors = [
{name = "Maxim Saplin"}
]
license = {text = "MIT"}
requires-python = ">=3.10"
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Operating System :: OS Independent",
]
dependencies = [
"mcp[cli]>=1.5.0",
"smolagents==1.12.0",
]
[dependency-groups]
dev = [
"pytest>=7.0.0",
"pytest-asyncio>=0.21.0",
]
[project.urls]
"Homepage" = "https://github.com/maxim-saplin/mcp_safe_local_python_executor/tree/main"
[tool.setuptools.packages.find]
where = ["."]
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-03-28_08-28-01/details.md:
--------------------------------------------------------------------------------
```markdown
# Details
Date : 2025-03-28 08:28:01
Directory /Users/admin/src/mcp_safe_local_python_executor
Total : 9 files, 859 codes, 45 comments, 158 blanks, all 1062 lines
[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
## Files
| filename | language | code | comment | blank | total |
| :--- | :--- | ---: | ---: | ---: | ---: |
| [README.md](/README.md) | Markdown | 99 | 0 | 36 | 135 |
| [examples/run\_executor.py](/examples/run_executor.py) | Python | 24 | 4 | 7 | 35 |
| [examples/run\_mcp\_server.py](/examples/run_mcp_server.py) | Python | 58 | 6 | 11 | 75 |
| [examples/test\_mcp\_client.py](/examples/test_mcp_client.py) | Python | 81 | 14 | 19 | 114 |
| [executor.py](/executor.py) | Python | 486 | 1 | 51 | 538 |
| [mcp\_server.py](/mcp_server.py) | Python | 56 | 12 | 21 | 89 |
| [requirements.txt](/requirements.txt) | pip requirements | 7 | 0 | 0 | 7 |
| [setup.py](/setup.py) | Python | 29 | 0 | 2 | 31 |
| [tests/test\_mcp\_server.py](/tests/test_mcp_server.py) | Python | 19 | 8 | 11 | 38 |
[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-05-01_18-42-30/diff.csv:
--------------------------------------------------------------------------------
```
"filename", "language", "Markdown", "Python", "pip requirements", "comment", "blank", "total"
"/Users/admin/src/mcp_safe_local_python_executor/README.md", "Markdown", -26, 0, 0, 0, -9, -35
"/Users/admin/src/mcp_safe_local_python_executor/examples/run_executor.py", "Python", 0, -24, 0, -4, -7, -35
"/Users/admin/src/mcp_safe_local_python_executor/examples/run_mcp_server.py", "Python", 0, -58, 0, -6, -11, -75
"/Users/admin/src/mcp_safe_local_python_executor/examples/test_mcp_client.py", "Python", 0, -81, 0, -14, -19, -114
"/Users/admin/src/mcp_safe_local_python_executor/executor.py", "Python", 0, -486, 0, -1, -51, -538
"/Users/admin/src/mcp_safe_local_python_executor/mcp_server.py", "Python", 0, 3, 0, -9, -3, -9
"/Users/admin/src/mcp_safe_local_python_executor/requirements.txt", "pip requirements", 0, 0, -7, 0, 0, -7
"/Users/admin/src/mcp_safe_local_python_executor/setup.py", "Python", 0, -29, 0, 0, -2, -31
"/Users/admin/src/mcp_safe_local_python_executor/tests/test_local_python_executor.py", "Python", 0, 66, 0, 2, 24, 92
"/Users/admin/src/mcp_safe_local_python_executor/tests/test_mcp_server.py", "Python", 0, 13, 0, -4, -1, 8
"Total", "-", -26, -596, -7, -36, -79, -744
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-03-28_08-28-01/results.json:
--------------------------------------------------------------------------------
```json
{"file:///Users/admin/src/mcp_safe_local_python_executor/mcp_server.py":{"language":"Python","code":56,"comment":12,"blank":21},"file:///Users/admin/src/mcp_safe_local_python_executor/executor.py":{"language":"Python","code":486,"comment":1,"blank":51},"file:///Users/admin/src/mcp_safe_local_python_executor/examples/run_executor.py":{"language":"Python","code":24,"comment":4,"blank":7},"file:///Users/admin/src/mcp_safe_local_python_executor/examples/run_mcp_server.py":{"language":"Python","code":58,"comment":6,"blank":11},"file:///Users/admin/src/mcp_safe_local_python_executor/examples/test_mcp_client.py":{"language":"Python","code":81,"comment":14,"blank":19},"file:///Users/admin/src/mcp_safe_local_python_executor/setup.py":{"language":"Python","code":29,"comment":0,"blank":2},"file:///Users/admin/src/mcp_safe_local_python_executor/README.md":{"language":"Markdown","code":99,"comment":0,"blank":36},"file:///Users/admin/src/mcp_safe_local_python_executor/requirements.txt":{"language":"pip requirements","code":7,"comment":0,"blank":0},"file:///Users/admin/src/mcp_safe_local_python_executor/tests/test_mcp_server.py":{"language":"Python","code":19,"comment":8,"blank":11}}
```
--------------------------------------------------------------------------------
/tests/test_mcp_server.py:
--------------------------------------------------------------------------------
```python
"""
Tests for the MCP server.
"""
import os
import sys
import pytest
# Add the parent directory to the path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
# Import the MCP server module
import mcp_server
@pytest.mark.asyncio
async def test_run_python():
"""Test that the run_python tool works correctly."""
# Test basic arithmetic
result = await mcp_server.run_python("result = 2 + 2")
assert result["result"] == 4
# Test math module functionality
result = await mcp_server.run_python("import math\nresult = math.sqrt(16)")
assert result["result"] == 4.0
@pytest.mark.asyncio
async def test_prime_numbers():
"""Test generating a list of prime numbers."""
code = """
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
primes = [num for num in range(2, 101) if is_prime(num)]
result = primes"""
result = await mcp_server.run_python(code)
expected_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
assert result["result"] == expected_primes
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-03-28_08-28-01/diff.csv:
--------------------------------------------------------------------------------
```
"filename", "language", "Python", "Markdown", "pip requirements", "comment", "blank", "total"
"/Users/admin/src/mcp_safe_local_python_executor/README.md", "Markdown", 0, 36, 0, 0, 16, 52
"/Users/admin/src/mcp_safe_local_python_executor/examples/run_executor.py", "Python", 24, 0, 0, 4, 7, 35
"/Users/admin/src/mcp_safe_local_python_executor/examples/run_mcp_server.py", "Python", 58, 0, 0, 6, 11, 75
"/Users/admin/src/mcp_safe_local_python_executor/examples/test_mcp_client.py", "Python", 81, 0, 0, 14, 19, 114
"/Users/admin/src/mcp_safe_local_python_executor/executor.py", "Python", 486, 0, 0, 1, 51, 538
"/Users/admin/src/mcp_safe_local_python_executor/mcp_server.py", "Python", -3, 0, 0, 9, 3, 9
"/Users/admin/src/mcp_safe_local_python_executor/requirements.txt", "pip requirements", 0, 0, 7, 0, 0, 7
"/Users/admin/src/mcp_safe_local_python_executor/setup.py", "Python", 29, 0, 0, 0, 2, 31
"/Users/admin/src/mcp_safe_local_python_executor/tests/run_executor.py", "Python", -24, 0, 0, -4, -7, -35
"/Users/admin/src/mcp_safe_local_python_executor/tests/test_local_python_executor.py", "Python", -98, 0, 0, -7, -27, -132
"/Users/admin/src/mcp_safe_local_python_executor/tests/test_mcp_server.py", "Python", -13, 0, 0, 4, 1, -8
"Total", "-", 540, 36, 7, 27, 76, 686
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-05-01_18-42-30/diff-details.md:
--------------------------------------------------------------------------------
```markdown
# Diff Details
Date : 2025-05-01 18:42:30
Directory /Users/admin/src/mcp_safe_local_python_executor
Total : 10 files, -629 codes, -36 comments, -79 blanks, all -744 lines
[Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details
## Files
| filename | language | code | comment | blank | total |
| :--- | :--- | ---: | ---: | ---: | ---: |
| [README.md](/README.md) | Markdown | -26 | 0 | -9 | -35 |
| [examples/run\_executor.py](/examples/run_executor.py) | Python | -24 | -4 | -7 | -35 |
| [examples/run\_mcp\_server.py](/examples/run_mcp_server.py) | Python | -58 | -6 | -11 | -75 |
| [examples/test\_mcp\_client.py](/examples/test_mcp_client.py) | Python | -81 | -14 | -19 | -114 |
| [executor.py](/executor.py) | Python | -486 | -1 | -51 | -538 |
| [mcp\_server.py](/mcp_server.py) | Python | 3 | -9 | -3 | -9 |
| [requirements.txt](/requirements.txt) | pip requirements | -7 | 0 | 0 | -7 |
| [setup.py](/setup.py) | Python | -29 | 0 | -2 | -31 |
| [tests/test\_local\_python\_executor.py](/tests/test_local_python_executor.py) | Python | 66 | 2 | 24 | 92 |
| [tests/test\_mcp\_server.py](/tests/test_mcp_server.py) | Python | 13 | -4 | -1 | 8 |
[Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-03-28_08-28-01/diff-details.md:
--------------------------------------------------------------------------------
```markdown
# Diff Details
Date : 2025-03-28 08:28:01
Directory /Users/admin/src/mcp_safe_local_python_executor
Total : 11 files, 583 codes, 27 comments, 76 blanks, all 686 lines
[Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details
## Files
| filename | language | code | comment | blank | total |
| :--- | :--- | ---: | ---: | ---: | ---: |
| [README.md](/README.md) | Markdown | 36 | 0 | 16 | 52 |
| [examples/run\_executor.py](/examples/run_executor.py) | Python | 24 | 4 | 7 | 35 |
| [examples/run\_mcp\_server.py](/examples/run_mcp_server.py) | Python | 58 | 6 | 11 | 75 |
| [examples/test\_mcp\_client.py](/examples/test_mcp_client.py) | Python | 81 | 14 | 19 | 114 |
| [executor.py](/executor.py) | Python | 486 | 1 | 51 | 538 |
| [mcp\_server.py](/mcp_server.py) | Python | -3 | 9 | 3 | 9 |
| [requirements.txt](/requirements.txt) | pip requirements | 7 | 0 | 0 | 7 |
| [setup.py](/setup.py) | Python | 29 | 0 | 2 | 31 |
| [tests/run\_executor.py](/tests/run_executor.py) | Python | -24 | -4 | -7 | -35 |
| [tests/test\_local\_python\_executor.py](/tests/test_local_python_executor.py) | Python | -98 | -7 | -27 | -132 |
| [tests/test\_mcp\_server.py](/tests/test_mcp_server.py) | Python | -13 | 4 | 1 | -8 |
[Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details
```
--------------------------------------------------------------------------------
/mcp_server.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""
MCP Server for LocalPythonExecutor
This module implements a Model Context Protocol (MCP) server that exposes
the LocalPythonExecutor as a tool for AI assistants.
"""
import logging
from typing import Dict, Any
from mcp.server.fastmcp import FastMCP
# from executor import LocalPythonExecutor
from smolagents.local_python_executor import LocalPythonExecutor
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
mcp = FastMCP("python-executor")
executor = LocalPythonExecutor(additional_authorized_imports=[])
executor.send_tools({})
@mcp.tool()
async def run_python(
code: str
) -> Dict[str, Any]:
"""Execute Python code in a secure sandbox environment.
This tool allows running simple Python code for calculations and data manipulations.
The execution environment is restricted for security purposes. Make sure you create a single file
that can be executed in one go and it returns a result.
Default allowed imports:
- math
- random
- datetime
- time
- json
- re
- string
- collections
- itertools
- functools
- operator
Args:
code: The Python code to execute. Must be valid Python 3 code. The result must be stored in a variable called `result`. E.g.:
```python
import math
result = math.sqrt(16)
```
Returns:
A dictionary with execution results containing:
- result: The final value or None if no value is returned
- logs: Any output from print statements
"""
logger.info(f"Executing Python code: {code}")
result, logs, _ = executor(code)
response = {
"result": result,
"logs": logs
}
logger.info(f"Execution result: {result}")
return response
if __name__ == "__main__":
logger.info("Starting MCP server for Python executor")
mcp.run(transport='stdio')
```
--------------------------------------------------------------------------------
/tests/test_local_python_executor.py:
--------------------------------------------------------------------------------
```python
"""
Smoke tests for the LocalPythonExecutor.
"""
import os
import sys
import pytest
# Add the parent directory to the path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
# Import the executor
from smolagents.local_python_executor import LocalPythonExecutor
def test_simple_arithmetic():
"""Test that simple arithmetic works correctly."""
executor = LocalPythonExecutor(additional_authorized_imports=[])
code = "2 + 2"
result, logs, _ = executor(code)
assert result == 4
assert logs == ""
def test_variable_assignment():
"""Test that variable assignment works correctly."""
executor = LocalPythonExecutor(additional_authorized_imports=[])
code = """
x = 10
y = 20
result = x + y
"""
result, logs, _ = executor(code)
assert result == 30
assert logs == ""
def test_expression_result():
"""Test that the last expression is returned as result."""
executor = LocalPythonExecutor(additional_authorized_imports=[])
code = """
x = 5
x * 2
"""
result, logs, _ = executor(code)
assert result == 10
assert logs == ""
def test_array_operations():
"""Test that array operations work correctly."""
executor = LocalPythonExecutor(additional_authorized_imports=[])
code = """
numbers = [1, 2, 3, 4, 5]
total = 0
for num in numbers:
total += num
total
"""
result, logs, _ = executor(code)
assert result == 15
assert logs == ""
def test_filesystem_access_fails():
"""Test that filesystem access is blocked"""
print("\nTest: Filesystem access attempt")
code = """
import os
files = os.listdir('.')
files
"""
executor = LocalPythonExecutor(additional_authorized_imports=[])
with pytest.raises(Exception) as exc_info:
executor(code)
assert 'InterpreterError: Import of os is not allowed' in str(exc_info.value)
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == "--smoke":
run_smoke_tests()
else:
pytest.main(["-v", __file__])
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-05-01_18-42-30/results.txt:
--------------------------------------------------------------------------------
```
Date : 2025-05-01 18:42:30
Directory : /Users/admin/src/mcp_safe_local_python_executor
Total : 4 files, 230 codes, 9 comments, 79 blanks, all 318 lines
Languages
+----------+------------+------------+------------+------------+------------+
| language | files | code | comment | blank | total |
+----------+------------+------------+------------+------------+------------+
| Python | 3 | 157 | 9 | 52 | 218 |
| Markdown | 1 | 73 | 0 | 27 | 100 |
+----------+------------+------------+------------+------------+------------+
Directories
+-------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+
| path | files | code | comment | blank | total |
+-------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+
| . | 4 | 230 | 9 | 79 | 318 |
| . (Files) | 2 | 132 | 3 | 45 | 180 |
| tests | 2 | 98 | 6 | 34 | 138 |
+-------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+
Files
+-------------------------------------------------------------------------------------+----------+------------+------------+------------+------------+
| filename | language | code | comment | blank | total |
+-------------------------------------------------------------------------------------+----------+------------+------------+------------+------------+
| /Users/admin/src/mcp_safe_local_python_executor/README.md | Markdown | 73 | 0 | 27 | 100 |
| /Users/admin/src/mcp_safe_local_python_executor/mcp_server.py | Python | 59 | 3 | 18 | 80 |
| /Users/admin/src/mcp_safe_local_python_executor/tests/test_local_python_executor.py | Python | 66 | 2 | 24 | 92 |
| /Users/admin/src/mcp_safe_local_python_executor/tests/test_mcp_server.py | Python | 32 | 4 | 10 | 46 |
| Total | | 230 | 9 | 79 | 318 |
+-------------------------------------------------------------------------------------+----------+------------+------------+------------+------------+
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-03-28_08-28-01/results.txt:
--------------------------------------------------------------------------------
```
Date : 2025-03-28 08:28:01
Directory : /Users/admin/src/mcp_safe_local_python_executor
Total : 9 files, 859 codes, 45 comments, 158 blanks, all 1062 lines
Languages
+------------------+------------+------------+------------+------------+------------+
| language | files | code | comment | blank | total |
+------------------+------------+------------+------------+------------+------------+
| Python | 7 | 753 | 45 | 122 | 920 |
| Markdown | 1 | 99 | 0 | 36 | 135 |
| pip requirements | 1 | 7 | 0 | 0 | 7 |
+------------------+------------+------------+------------+------------+------------+
Directories
+-----------------------------------------------------------------------------+------------+------------+------------+------------+------------+
| path | files | code | comment | blank | total |
+-----------------------------------------------------------------------------+------------+------------+------------+------------+------------+
| . | 9 | 859 | 45 | 158 | 1,062 |
| . (Files) | 5 | 677 | 13 | 110 | 800 |
| examples | 3 | 163 | 24 | 37 | 224 |
| tests | 1 | 19 | 8 | 11 | 38 |
+-----------------------------------------------------------------------------+------------+------------+------------+------------+------------+
Files
+-----------------------------------------------------------------------------+------------------+------------+------------+------------+------------+
| filename | language | code | comment | blank | total |
+-----------------------------------------------------------------------------+------------------+------------+------------+------------+------------+
| /Users/admin/src/mcp_safe_local_python_executor/README.md | Markdown | 99 | 0 | 36 | 135 |
| /Users/admin/src/mcp_safe_local_python_executor/examples/run_executor.py | Python | 24 | 4 | 7 | 35 |
| /Users/admin/src/mcp_safe_local_python_executor/examples/run_mcp_server.py | Python | 58 | 6 | 11 | 75 |
| /Users/admin/src/mcp_safe_local_python_executor/examples/test_mcp_client.py | Python | 81 | 14 | 19 | 114 |
| /Users/admin/src/mcp_safe_local_python_executor/executor.py | Python | 486 | 1 | 51 | 538 |
| /Users/admin/src/mcp_safe_local_python_executor/mcp_server.py | Python | 56 | 12 | 21 | 89 |
| /Users/admin/src/mcp_safe_local_python_executor/requirements.txt | pip requirements | 7 | 0 | 0 | 7 |
| /Users/admin/src/mcp_safe_local_python_executor/setup.py | Python | 29 | 0 | 2 | 31 |
| /Users/admin/src/mcp_safe_local_python_executor/tests/test_mcp_server.py | Python | 19 | 8 | 11 | 38 |
| Total | | 859 | 45 | 158 | 1,062 |
+-----------------------------------------------------------------------------+------------------+------------+------------+------------+------------+
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-05-01_18-42-30/diff.txt:
--------------------------------------------------------------------------------
```
Date : 2025-05-01 18:42:30
Directory : /Users/admin/src/mcp_safe_local_python_executor
Total : 10 files, -629 codes, -36 comments, -79 blanks, all -744 lines
Languages
+------------------+------------+------------+------------+------------+------------+
| language | files | code | comment | blank | total |
+------------------+------------+------------+------------+------------+------------+
| pip requirements | 1 | -7 | 0 | 0 | -7 |
| Markdown | 1 | -26 | 0 | -9 | -35 |
| Python | 8 | -596 | -36 | -70 | -702 |
+------------------+------------+------------+------------+------------+------------+
Directories
+-------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+
| path | files | code | comment | blank | total |
+-------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+
| . | 10 | -629 | -36 | -79 | -744 |
| . (Files) | 5 | -545 | -10 | -65 | -620 |
| examples | 3 | -163 | -24 | -37 | -224 |
| tests | 2 | 79 | -2 | 23 | 100 |
+-------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+
Files
+-------------------------------------------------------------------------------------+------------------+------------+------------+------------+------------+
| filename | language | code | comment | blank | total |
+-------------------------------------------------------------------------------------+------------------+------------+------------+------------+------------+
| /Users/admin/src/mcp_safe_local_python_executor/README.md | Markdown | -26 | 0 | -9 | -35 |
| /Users/admin/src/mcp_safe_local_python_executor/examples/run_executor.py | Python | -24 | -4 | -7 | -35 |
| /Users/admin/src/mcp_safe_local_python_executor/examples/run_mcp_server.py | Python | -58 | -6 | -11 | -75 |
| /Users/admin/src/mcp_safe_local_python_executor/examples/test_mcp_client.py | Python | -81 | -14 | -19 | -114 |
| /Users/admin/src/mcp_safe_local_python_executor/executor.py | Python | -486 | -1 | -51 | -538 |
| /Users/admin/src/mcp_safe_local_python_executor/mcp_server.py | Python | 3 | -9 | -3 | -9 |
| /Users/admin/src/mcp_safe_local_python_executor/requirements.txt | pip requirements | -7 | 0 | 0 | -7 |
| /Users/admin/src/mcp_safe_local_python_executor/setup.py | Python | -29 | 0 | -2 | -31 |
| /Users/admin/src/mcp_safe_local_python_executor/tests/test_local_python_executor.py | Python | 66 | 2 | 24 | 92 |
| /Users/admin/src/mcp_safe_local_python_executor/tests/test_mcp_server.py | Python | 13 | -4 | -1 | 8 |
| Total | | -629 | -36 | -79 | -744 |
+-------------------------------------------------------------------------------------+------------------+------------+------------+------------+------------+
```
--------------------------------------------------------------------------------
/.VSCodeCounter/2025-03-28_08-28-01/diff.txt:
--------------------------------------------------------------------------------
```
Date : 2025-03-28 08:28:01
Directory : /Users/admin/src/mcp_safe_local_python_executor
Total : 11 files, 583 codes, 27 comments, 76 blanks, all 686 lines
Languages
+------------------+------------+------------+------------+------------+------------+
| language | files | code | comment | blank | total |
+------------------+------------+------------+------------+------------+------------+
| Python | 9 | 540 | 27 | 60 | 627 |
| Markdown | 1 | 36 | 0 | 16 | 52 |
| pip requirements | 1 | 7 | 0 | 0 | 7 |
+------------------+------------+------------+------------+------------+------------+
Directories
+-------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+
| path | files | code | comment | blank | total |
+-------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+
| . | 11 | 583 | 27 | 76 | 686 |
| . (Files) | 5 | 555 | 10 | 72 | 637 |
| examples | 3 | 163 | 24 | 37 | 224 |
| tests | 3 | -135 | -7 | -33 | -175 |
+-------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+
Files
+-------------------------------------------------------------------------------------+------------------+------------+------------+------------+------------+
| filename | language | code | comment | blank | total |
+-------------------------------------------------------------------------------------+------------------+------------+------------+------------+------------+
| /Users/admin/src/mcp_safe_local_python_executor/README.md | Markdown | 36 | 0 | 16 | 52 |
| /Users/admin/src/mcp_safe_local_python_executor/examples/run_executor.py | Python | 24 | 4 | 7 | 35 |
| /Users/admin/src/mcp_safe_local_python_executor/examples/run_mcp_server.py | Python | 58 | 6 | 11 | 75 |
| /Users/admin/src/mcp_safe_local_python_executor/examples/test_mcp_client.py | Python | 81 | 14 | 19 | 114 |
| /Users/admin/src/mcp_safe_local_python_executor/executor.py | Python | 486 | 1 | 51 | 538 |
| /Users/admin/src/mcp_safe_local_python_executor/mcp_server.py | Python | -3 | 9 | 3 | 9 |
| /Users/admin/src/mcp_safe_local_python_executor/requirements.txt | pip requirements | 7 | 0 | 0 | 7 |
| /Users/admin/src/mcp_safe_local_python_executor/setup.py | Python | 29 | 0 | 2 | 31 |
| /Users/admin/src/mcp_safe_local_python_executor/tests/run_executor.py | Python | -24 | -4 | -7 | -35 |
| /Users/admin/src/mcp_safe_local_python_executor/tests/test_local_python_executor.py | Python | -98 | -7 | -27 | -132 |
| /Users/admin/src/mcp_safe_local_python_executor/tests/test_mcp_server.py | Python | -13 | 4 | 1 | -8 |
| Total | | 583 | 27 | 76 | 686 |
+-------------------------------------------------------------------------------------+------------------+------------+------------+------------+------------+
```