# 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 | +-------------------------------------------------------------------------------------+------------------+------------+------------+------------+------------+ ```