Apache-2.0 MCP-native

Upgrade Python. Keep the behavior.

PyMolt maps what changed, rewrites the code it can prove safe, and compares real behavior before and after the upgrade. Run it yourself or let your agent drive the same workflow.

$uv tool install "pymolt[mcp] @ git+https://github.com/zeelexes/pymolt"
then pymolt migrate .installs from source — not on PyPI yet
~/projects/analytics-api — zsh
$pymolt migrate . --target-python 3.11
Rich CLI
Autonomous migration3.8 → 3.11
Interpreter: .venv/bin/python (pyvenv.cfg)
detectpyproject.toml, 14 dependencies
assessresolved for 3.11, risk MEDIUM
resolvewrote requirements-target.txt
codemods12 rules across 4 packages
rewrite3 files rewritten in place
verifycomparing behavior…
every phase is also a standalone command — and an MCP tool
What you end up with

One page you can put in the ticket.

Not a wall of terminal output. A report that says what changed, what was checked, and — the part most tools leave out — what wasn't.

analytics-api
Python 3.8 3.11
2 actions for you
not calledcalled14 dependencies8 unaffected6 changed4 fixed2 leftband width = number ofpackages, to scale
Most of a migration is packages that turn out not to matter. The report's job is to shrink 14 down to the 2 that actually need you.
How much of it was actually watched running1,204 call sites reached by your tests
68% verified
32% never ran

Verified — ran under both versions and returned the same thing.

Never ran — your tests don't reach it, so nothing is claimed. Better coverage moves this bar.

The 6 that needed changes8 unaffected, not listed
pandas
1.5.3 2.2.0
rewritten
6 rewrites
pydantic
1.10.8 2.7.1
rewritten
3 rewrites
SQLAlchemy
1.4 2.0
rewritten
2 rewrites
Flask
2.0 3.0
rewritten
1 rewrite
airflow
2.8 3.0
left for you
provider split
elasticsearch
7.17 8.13
left for you
31 calls never run
Left for you — 2 items
  • airflow 2.8 → 3.0 moves operators into separate provider packages. That is a dependency decision, not a rewrite — nothing was changed automatically.
  • elasticsearch 7.17 → 8.13 has 31 call sites your tests never execute. Add coverage there, or review them by hand.
pymolt contract report . --format htmlwritten to .pymolt/report.html
Where this actually lives

On the dependency-bump pull request.

Every phase emits JSON, so the report is a build artifact like any other. Point it at the PR your bot opened, and let the “never ran” share be the thing that blocks a merge — you pick the threshold, because only you know how much unverified surface you are willing to ship.

This is the expensive phase — it runs your suite twice — so it belongs on the upgrade branch, not on every commit.

.github/workflows/upgrade.yml
- run: pymolt migrate . --target-python 3.11
- run: pymolt contract report . --json > report.json
- run: |
    jq -e '.unverified_pct < 40' report.json       || echo "::warning::too much unverified surface"
Choose your starting point

One engine. Three ways in.

PyMolt is useful before it is impressive: start with the surface that matches how you work, then follow the same evidence-backed workflow underneath.

For engineers

Run the CLI

Scan a repository, name the Python you need, and get a diff before anything touches your files.

$ pymolt migrate . --target-python 3.11
Read the CLI guide
For agents

Connect over MCP

Give Claude, Cursor, or Copilot the same workflow with bounded tools and an explicit next step at every phase.

$ pymolt mcp
See the method
For the change itself

Browse the catalog

Inspect the version-pair rules Axiom already knows, from mechanical renames to behavior-aware rewrites.

$ pymolt codemods . --package pandas
Open the catalog

Three lines to the Python you need.

Not whatever released last week. Whichever version your platform team already supports — PyMolt plans the jump to that one.

3.93.103.113.123.13— your call, not ours
01Install it
$ uv tool install "pymolt[mcp] @ git+https://github.com/zeelexes/pymolt"
02Name your target
$ pymolt migrate . --target-python 3.11
03Or hand it to your agent
$ claude mcp add pymolt -- pymolt mcp