Skip to content

Commit cc2259a

Browse files
committed
tests passing
1 parent a60975b commit cc2259a

File tree

12 files changed

+117
-59
lines changed

12 files changed

+117
-59
lines changed

Makefile

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,9 @@ typecheck-py: ## Typecheck the code
5656
.PHONY: typecheck
5757
typecheck: typecheck-ts typecheck-py ## Typecheck all code
5858

59-
.PHONY: test-ts
60-
test-ts: ## Run TS tests
61-
CI=1 npm run test
62-
6359
.PHONY: test
64-
test: test-ts ## Run all tests
60+
test: ## Run tests
61+
uv run coverage run -m pytest
6562

6663
.PHONY: all
6764
all: format typecheck test ## run format, typecheck and test

build/build.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
root_dir = this_dir.parent
88

99
# Define source and destination paths
10-
src = this_dir / "prepare_env.py"
11-
dst = root_dir / "mcp_run_python" / "deno" / "prepareEnvCode.ts"
10+
src = this_dir / 'prepare_env.py'
11+
dst = root_dir / 'mcp_run_python' / 'deno' / 'prepareEnvCode.ts'
1212

1313
python_code = src.read_text()
1414

1515
# Escape backslashes for JavaScript string literal
16-
python_code = python_code.replace("\\", "\\\\")
16+
python_code = python_code.replace('\\', '\\\\')
1717

1818
# Create the JavaScript/TypeScript code
1919
ts_code = f"""// DO NOT EDIT THIS FILE DIRECTLY, INSTEAD RUN "make build"
@@ -22,4 +22,4 @@
2222

2323
dst.write_text(ts_code)
2424

25-
print(f"Successfully built {dst}")
25+
print(f'Successfully built {dst}')

build/stubs/pyodide/code.pyi

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
def find_imports(code: str) -> list[str]:
2-
...
1+
def find_imports(code: str) -> list[str]: ...

build/stubs/pyodide_js.pyi

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
class _ToPy:
2-
def to_py(self) -> dict[str, str]:
3-
...
4-
2+
def to_py(self) -> dict[str, str]: ...
53

64
class _Api:
75
_import_name_to_package_name: _ToPy

mcp_run_python/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from __future__ import annotations as _annotations
2+
3+
from importlib.metadata import version as _metadata_version
4+
5+
from .main import deno_args, run_deno_server
6+
7+
__version__ = _metadata_version('mcp_run_python')
8+
__all__ = '__version__', 'deno_args', 'run_deno_server'

mcp_run_python/__main__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"""This means `python -m mcp_run_python` should run the CLI."""
2+
3+
from ._cli import cli
4+
5+
if __name__ == '__main__':
6+
cli()

mcp_run_python/_cli.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from __future__ import annotations as _annotations
2+
3+
import argparse
4+
import sys
5+
from collections.abc import Sequence
6+
7+
from . import __version__
8+
from .main import run_deno_server
9+
10+
11+
def cli() -> int: # pragma: no cover
12+
"""Run the CLI."""
13+
sys.exit(cli_logic())
14+
15+
16+
def cli_logic(args_list: Sequence[str] | None = None) -> int:
17+
parser = argparse.ArgumentParser(
18+
prog='mcp-run-python',
19+
description=f'mcp-run-python CLI v{__version__}\n\nMCP server for running untrusted Python code.\n',
20+
formatter_class=argparse.RawTextHelpFormatter,
21+
)
22+
parser.add_argument('--version', action='store_true', help='Show version and exit')
23+
24+
parser.add_argument(
25+
'mode',
26+
choices=['stdio', 'streamable-http', 'http', 'warmup'],
27+
help='Mode to run in ("http" is an alias for "streamable-http")',
28+
)
29+
30+
args = parser.parse_args(args_list)
31+
if args.version:
32+
print(f'mcp-run-python {__version__}')
33+
return 0
34+
else:
35+
run_deno_server(args.mode.replace('-', '_'))
36+
return 0

mcp_run_python/deno.jsonc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
".": "./deno/main.ts"
77
},
88
"tasks": {
9-
"run": "deno run -N -R=node_modules -W=node_modules deno/main.ts",
9+
"dev": "deno run -N -R=node_modules -W=node_modules deno/main.ts",
1010
"lint": "deno lint",
1111
"typecheck": "deno check deno",
1212
"format": "deno fmt"

mcp_run_python/main.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import subprocess
2+
import sys
3+
from pathlib import Path
4+
from typing import Literal
5+
6+
Mode = Literal['stdio', 'streamable_http', 'warmup']
7+
THIS_DIR = Path(__file__).parent
8+
9+
10+
def run_deno_server(mode: Mode, *, port: int | None = None):
11+
print('Running mcp-run-python server...', file=sys.stderr)
12+
try:
13+
subprocess.run(('deno', *deno_args(mode, port=port)), cwd=THIS_DIR)
14+
except KeyboardInterrupt:
15+
print('Server stopped.', file=sys.stderr)
16+
17+
18+
def deno_args(mode: Mode, *, port: int | None = None) -> list[str]:
19+
args = [
20+
'run',
21+
'-N',
22+
f'-R={THIS_DIR / "node_modules"}',
23+
f'-W={THIS_DIR / "node_modules"}',
24+
'--node-modules-dir=auto',
25+
str(THIS_DIR / 'deno/main.ts'),
26+
mode,
27+
]
28+
if port is not None:
29+
args.append(f'--port={port}')
30+
return args

pyproject.toml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
[build-system]
2+
requires = ["uv_build>=0.8.10"]
3+
build-backend = "uv_build"
4+
15
[project]
26
name = "mcp-run-python"
37
version = "0.0.1"
@@ -25,7 +29,16 @@ classifiers = [
2529
"Topic :: Internet",
2630
]
2731
requires-python = ">=3.10"
28-
dependencies = ["mcp>=1.13.1"]
32+
33+
[project.urls]
34+
Homepage = "https://github.com/pydantic/mcp-run-python"
35+
Source = "https://github.com/pydantic/mcp-run-python"
36+
Changelog = "https://github.com/pydantic/mcp-run-python/releases"
37+
38+
[tool.uv.build-backend]
39+
module-name = "mcp_run_python"
40+
module-root = ""
41+
2942

3043
[dependency-groups]
3144
dev = [
@@ -34,11 +47,15 @@ dev = [
3447
"httpx>=0.28.1",
3548
"inline-snapshot>=0.19.3",
3649
"micropip>=0.9.0; python_version >= '3.12'",
50+
"mcp>=1.13.1",
3751
"pytest>=8.3.3",
3852
"pytest-pretty>=1.2.0",
3953
"ruff>=0.12.11",
4054
]
4155

56+
[project.scripts]
57+
mcp-run-python = "mcp_run_python._cli:cli"
58+
4259
[tool.ruff]
4360
line-length = 120
4461
target-version = "py310"

0 commit comments

Comments
 (0)