Evolution MCP
Modal-backed MCP server for evaluating multiple agent-generated code variants in parallel.
Codex runs locally and generates candidate patches or full-file writes. Modal only evaluates those variants:
- Sync the dirty local repo into a Modal image with
Image.add_local_dir. - Start a setup sandbox and run setup commands once.
- Snapshot the prepared filesystem with
Sandbox.snapshot_filesystem. - Start
run_experiment; it returns immediately withstatus: running. - Enqueue a durable Redis Stream job.
- A worker process claims the job and forks one Modal sandbox per variant.
- Apply each patch or full-file write inside its sandbox.
- Run the same eval command in each sandbox.
- Persist result metadata and artifacts to Redis.
- Poll
get_experimentuntil completed. - Optionally call
apply_winnerto apply the winning diff locally.
Install
uv sync
For a published package, the intended install shape is:
uvx --from evolution-mcp evolution-mcp-doctor
Configure Modal
uv run modal setup
The controller uses your local Modal credentials to create images, sandboxes,
and snapshots. Eval sandboxes do not need OpenAI credentials. Only pass
secret_names when the repo's own setup or tests need secrets.
Configure Redis
V2 uses Redis for durable workspace records, experiment records, statuses, and small artifacts.
export REDIS_URL=redis://localhost:6379/0
Redis must be running before normal use:
brew install redis
brew services start redis
For dev-only local JSON persistence:
export EVOLUTION_MCP_STORAGE=local
Doctor
uv run evolution-mcp-doctor
This checks storage, checks the active Modal profile, and prints a Codex MCP config snippet.
Run The MCP Server
uvx --from evolution-mcp evolution-mcp
Run A Worker
Run at least one worker process alongside the MCP server:
uvx --from evolution-mcp evolution-mcp-worker
Workers consume Redis Stream jobs. They acknowledge a job only after writing the
completed or failed experiment record, so unacked jobs can be reclaimed by
another worker after --reclaim-after-ms.
Add To Codex
Example MCP config:
{
"mcpServers": {
"evolution-mcp": {
"command": "uvx",
"args": ["--from", "evolution-mcp", "evolution-mcp"],
"env": {
"REDIS_URL": "redis://localhost:6379/0"
}
}
}
}
Tool Flow
Prepare once:
{
"repo_path": "/Users/me/project",
"setup_commands": ["pytest --version"]
}
Start async experiment:
{
"workspace_id": "ws_...",
"variants": [
{
"name": "minimal-fix",
"patch": "diff --git a/app.py b/app.py\n..."
},
{
"name": "boundary-fix",
"files": [
{"path": "app.py", "content": "...full file content..."}
]
}
],
"eval_command": "pytest -q",
"parallelism": 2
}
run_experiment returns immediately:
{
"experiment_id": "exp_...",
"status": "running"
}
Poll:
{
"experiment_id": "exp_..."
}
Completed result:
{
"status": "completed",
"winner": "minimal-fix",
"results": []
}
Example Agent Prompt
Generate 2-3 meaningfully different candidate fixes as unified diffs or
full-file variants. Call prepare_workspace once, then call run_experiment with
those variants and the exact eval command. Poll get_experiment until the status
is completed, failed, or no_passing_variant. Do not call apply_winner unless the
user explicitly asks to apply the selected diff.
Smoke Run
EVOLUTION_MCP_STORAGE=local uv run evolution-modal-smoke /path/to/repo "pytest -q"
The smoke command runs a local worker loop for the queued smoke job. In normal
usage, keep evolution-mcp-worker running separately.
Tests
PYTHONPATH=src python3 -m unittest discover -s tests
uv run --extra dev ruff check .
Known Limitations
- Full logs/diffs are stored in Redis for V2. Large artifacts should move to blob storage or Modal Volume later.
- Modal SDK
1.4.3does not expose snapshot image deletion; cleanup removes local/Redis records and tracks the snapshot ID. apply_winnerapplies a stored diff to the local repo withgit apply; if the repo changed since the experiment, the patch can fail.
Metadata
Release files for evolution-mcp 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| evolution_mcp-0.1.1.tar.gz | 21.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| evolution_mcp-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.2 kB
Release files / evolution_mcp-0.1.1.tar.gz
| Download URL | evolution_mcp-0.1.1.tar.gz |
|---|---|
| Size | 21.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
50d890d5c88aafbce45dcf0727da6662a399b6b5dbb100cbee046d4ea47fbaed
|
|
BLAKE2b-256 checksum How to use checksums |
b66a9f9171a74168ad9a4f8a6fba0b3eeef8a775b976a49a0a09268032a8d45c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / evolution_mcp-0.1.1-py3-none-any.whl
| Download URL | evolution_mcp-0.1.1-py3-none-any.whl |
|---|---|
| Size | 21.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0fa75467c3e48a9c58b34c23b7e417c0f37ef4eb1a41fd1b0e0a112fc6cfa216
|
|
BLAKE2b-256 checksum How to use checksums |
4db4605dfbda62f5853295ec848626ff7dde7e74fe26801417db0fbf13c2f455
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for evolution-mcp 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.