modern-python-guidance
Stop your AI from writing typing.List, @validator, and setup.py. 41 version-aware BAD/GOOD pattern guides that teach AI coding agents to write modern Python — delivered via MCP, CLI, or Agent Skills.
Highlights
- Evidence status: Historical V5 content-efficacy evidence is documented with its model, prompt, sample, metric, and delivery scope; it is not a product-wide effectiveness claim (V5 benchmark details)
- 41 guides across stdlib, Pydantic, FastAPI, Django, SQLAlchemy, pytest, and toolchain
- Version- and dependency-aware: filters Python-version-incompatible guidance and qualifies framework/tool guidance from project evidence
- 4 delivery methods: MCP server, CLI, Agent Skills, and Rules (auto-injects on
.pyfile touch) - Not Ruff: Ruff auto-fixes syntax (
List→list). mpg guides design decisions that Ruff can't touch —TaskGroupovergather, Pydantic V2 migration, SQLAlchemy 2.0 style
Benchmark evidence status: historical V5 cells remain documented for audit, but no traceable numeric product claim is currently promoted. Default mpg setup end-to-end effectiveness has not yet been measured.
Note: The tool itself requires Python 3.11+ to run. Guides cover patterns from Python 3.9 onward, and
--python-versionfilters guides for your target environment.
Quick start
Claude Code (recommended)
pip install modern-python-guidance
mpg setup
This registers the MCP server, links Agent Skills, creates a Rules file (.claude/rules/modern-python.md), and registers a PostToolUse hook in one command. The Rules file auto-injects modern Python guidance whenever you touch Python-related files, and the hook checks each edited .py file against the guides with a detector applicable to the target project (see PostToolUse hook below). Advisory-only gaps are disclosed through CLI/MCP metadata. Start a new Claude Code session afterwards — newly registered MCP servers, skills, rules, and hooks take effect on the next launch.
CLI
pip install modern-python-guidance
mpg search "pydantic validator"
mpg retrieve pydantic-v2-validators
mpg is the short alias for modern-python-guidance. Both work.
Manual setup / other agents
MCP registration (Claude Code):
# uv tool / pipx installs (mpg is on PATH):
claude mcp add mpg -- mpg mcp
# venv installs — Claude Code spawns MCP servers outside your venv, so register
# the interpreter's absolute path (`mpg setup` does this automatically):
claude mcp add mpg -- "$(python -c 'import sys; print(sys.executable)')" -m modern_python_guidance mcp
Other MCP-compatible agents (Cursor, Windsurf, etc.) — add to your MCP config:
{
"mcpServers": {
"mpg": {
"command": "mpg",
"args": ["mcp"]
}
}
}
For venv installs, set "command" to your interpreter's absolute path and "args" to ["-m", "modern_python_guidance", "mcp"] for the same reason as above.
Agent Skills + Rules only (Claude Code):
mpg setup --skills-only
mpg setup flags:
| Flag | Purpose |
|---|---|
--mcp-only |
MCP registration only |
--skills-only |
Project-local artifacts only (Skills + Rules) |
--scope {user,local} |
MCP scope (default: user) |
--project-dir PATH |
Target project for local MCP and project artifacts |
--dry-run |
Show what would be done |
--no-hook |
Don't register the PostToolUse hook (removes it if already present) |
--with-hook |
Register the hook even if this project already has mpg artifacts |
If this project already has mpg's Skills or Rules symlinks from a previous mpg setup, the hook is not silently enabled — you'll see a note instead (New: mpg can auto-check Python files after every edit. / Enable: mpg setup --with-hook). A fresh project gets the hook by default.
After registering, mpg setup checks whether a same-name registration in a higher-precedence scope (local > project > user) would shadow the one it just wrote, and prints a warning with the exact claude mcp remove command if so.
Uninstall — reverse mpg setup (deregister the MCP server and unlink Agent Skills + Rules):
mpg uninstall # remove all
mpg uninstall --dry-run # preview what would be removed
| Flag | Purpose |
|---|---|
--mcp-only |
MCP deregistration only |
--skills-only |
Project-local artifacts only (Skills + Rules) |
--project-dir PATH |
Target project for local MCP and project artifacts |
--dry-run |
Show what would be done |
mpg uninstall clears the MCP registration from every scope setup can write to (user and local), removes only the symlinks mpg created (never their targets or other files), removes mpg's PostToolUse hook entry from .claude/settings.local.json (leaving any other tools' hooks untouched), and is idempotent — running it on an already-clean state is a harmless no-op.
When --scope local is used, --project-dir is also the cwd for every MCP add, replacement, health-check, and removal operation. A missing target is created before local setup; uninstall fails closed for a missing explicit target instead of touching the caller's local registration. User-scope MCP operations remain global and do not use this path.
CLI usage
# Search guides by keyword
mpg search "pydantic validator"
# Retrieve a specific guide (full BAD/GOOD content)
mpg retrieve use-builtin-generics
# List all guides compatible with your Python version
mpg list --python-version 3.11
# Auto-detect project Python version from pyproject.toml / .python-version
mpg detect-version
# Filter by category
mpg search "timeout" --category async
# Scan a file for outdated patterns
mpg check app.py
mpg check app.py --format json | jq '.summary.guide_ids'
mpg check app.py --exit-zero # always exit 0
# JSON output (default when piped, explicit with --format)
mpg search "typing" --format json | jq '.[0].id'
# Read dependency evidence from another project; hide proven-incompatible guides by default
mpg search "pydantic validator" --project-dir ../my-app
# Supply an exact target-environment override when files cannot prove it
mpg search "pydantic validator" --dependency-version package:pydantic=2.7.4
Guide coverage
41 guides across 3 layers:
| Layer | Categories | Count | Examples |
|---|---|---|---|
| 1 — stdlib | typing, async, stdlib, data-structures | 18 | list over List, match/case, TaskGroup, deferred annotations, t-strings |
| 2 — frameworks | pydantic, fastapi, httpx, django, sqlalchemy, pytest | 18 | Pydantic V2 migration, SQLAlchemy 2.0 style, Annotated[Depends] |
| 3 — toolchain | toolchain | 5 | uv over pip, ruff over flake8, pickle avoidance |
Run mpg list to see the 41-guide catalog, or browse it on GitHub.
Version-aware filtering
Guides specify their minimum Python version. Every guidance command resolves the target
Python from the nearest project context (and discloses the result as
target_python: {version, source}) using this precedence:
--python-versionflagpyproject.tomlrequires-pythonpyproject.tomlPoetrypythonconstraint (^3.10,~3.11,>=3.10,<3.14).python-versionfile- Default: 3.11
The same resolver is used by CLI search/retrieve/list/check, the MCP guidance tools,
and the PostToolUse hook. An explicit CLI/MCP version always wins. mpg detect-version
keeps its plain output for scripts; use mpg detect-version --format json to audit the
resolved version and stable source label, including when a JSON search or list result is empty.
# Only shows guides compatible with Python 3.9 (explicit override)
mpg list --python-version 3.9
# Excludes: TaskGroup (3.11+), match/case (3.10+), etc.
Dependency-aware applicability
Framework and toolchain guides declare machine-readable applies-to-packages and/or
applies-to-tools metadata. Every declared requirement must be proven (AND
semantics). mpg search and mpg list hide guidance that is proven
incompatible by default; use --include-incompatible to inspect it. retrieve
always returns an explicitly requested guide so migration work can be reviewed.
Use --project-dir PATH to read the nearest project evidence, and repeat
--dependency-version KIND:NAME=VERSION for an exact target-environment override.
The MCP search_guides, retrieve_guides, and list_guides tools expose the same
project_dir (relative to the MCP server), dependency_versions object, and
include_incompatible option where filtering applies.
Results contain additive dependency_requirements and dependency_compatibility
objects. Status is deliberately conservative:
- confirmed: all requirements are proven compatible;
- incompatible: at least one requirement is proven incompatible;
- unknown: evidence is absent, ambiguous, conditional, or cannot safely prove a range.
Unknown is not confirmation. Do not infer the target environment from the interpreter
running mpg, a [tool.uv]/[tool.ruff] table, optional or dependency-group entries,
or an unrooted/ambiguous lockfile. The PostToolUse hook suppresses known-incompatible
findings and asks for verification when status is unknown; mpg check follows the
same rule and annotates remaining unknown findings in JSON/human output.
PostToolUse hook
mpg setup registers a PostToolUse hook by default (see Quick start above) — no manual .claude/settings.local.json editing needed. It checks every .py file Claude edits or writes against the detector-capable guides applicable to the target project and surfaces findings via hookSpecificOutput.additionalContext, so Claude receives them as part of its own context rather than as a raw stderr error.
mpg check and the PostToolUse hook automatically check only guides with a detector for the target Python/dependency context. The current catalog has 26 detectable guides out of 41; 15 are advisory-only and are not claimed as actively checked.
Advisory-only guides: dataclass-modern, dict-merge-operator, django-check-constraints, exception-groups, fastapi-typed-state, httpx-streaming, match-case-patterns, override-decorator, pytest-parametrize, pytest-raises-match, removeprefix-removesuffix, ruff-over-flake8, sqlalchemy-async-session, template-strings, uv-over-pip.
A clean automatic check does not certify advisory-only guidance. Use mpg list --format json or MCP metadata to inspect each guide's detection status.
This capability contract is distinct from #152: #181 describes which guides can produce automatic findings after activation, while #152 measures whether an organic development session reaches the catalog at all.
A few things worth knowing about how it behaves:
- It scans the whole edited file, not just your diff. An edit anywhere in a file can resurface pre-existing outdated patterns you didn't touch this time, not only the lines you just wrote.
- Findings are capped at 5 per edit, plus a
+N moresummary line, to bound how much context gets injected. - Only the guide ID and line number are surfaced — never the matching source line itself. Echoing arbitrary file content back as an authoritative-looking hook message would be an indirect prompt-injection channel;
guide_id+ line number is enough for Claude to look up the modern form. - The project's target Python version is auto-detected the same way as
mpg detect-version(nearestpyproject.tomlrequires-python/ Poetrypythonconstraint, or.python-version, walking up from the edited file), so patterns that require a newer Python than your project targets are not flagged. The resolved target and source are shown in the summary ([target: py3.X; source: SOURCE]). - Non-Python files and clean files produce no output.
- An existing project (Skills/Rules already linked from a previous
mpg setup) is never silently opted in — see the--with-hook/--no-hookflags above.
Verify with /hooks in Claude Code to confirm it's active.
For manual CLI use, mpg check --quiet <file> uses the same automatic resolver. Pass
--python-version X.Y when you intentionally want an explicit override; the JSON output
contains the same top-level target_python object.
Manual hook setup (advanced)
If you'd rather manage the hook entry yourself instead of mpg setup, add it to .claude/settings.local.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "/path/to/python",
"args": ["-m", "modern_python_guidance", "hook", "claude-post-tool-use"]
}
]
}
]
}
}
Use the interpreter's absolute path (command), not a bare mpg/python — Claude Code spawns hooks from its own environment, where a venv-only interpreter is not on PATH. mpg setup resolves and pins this for you automatically.
Development
git clone https://github.com/yottayoshida/modern-python-guidance.git
cd modern-python-guidance
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
pytest
See CONTRIBUTING.md for project structure and guide authoring details.
License
Apache-2.0 OR MIT — see LICENSE and LICENSE-MIT.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file modern_python_guidance-0.5.11.tar.gz.
File metadata
- Download URL: modern_python_guidance-0.5.11.tar.gz
- Upload date:
- Size: 259.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
635541bb43f57c84628128a8f2dc7263cb5147371cafb1c7fb1e351d710d18b2
|
|
| MD5 |
689e8123c2dca32c296c536698a17817
|
|
| BLAKE2b-256 |
4d6fd7e9b1992e5d940f76e58585ec27bb5c08bb47162fad0dc346434b18ffd1
|
Provenance
The following attestation bundles were made for modern_python_guidance-0.5.11.tar.gz:
Publisher:
ci.yml on yottayoshida/modern-python-guidance
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
modern_python_guidance-0.5.11.tar.gz -
Subject digest:
635541bb43f57c84628128a8f2dc7263cb5147371cafb1c7fb1e351d710d18b2 - Sigstore transparency entry: 2357167330
- Sigstore integration time:
-
Permalink:
yottayoshida/modern-python-guidance@4a80890d0977487bbc247597bbe1e71ab6e2fc7c -
Branch / Tag:
refs/tags/v0.5.11 - Owner: https://github.com/yottayoshida
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@4a80890d0977487bbc247597bbe1e71ab6e2fc7c -
Trigger Event:
release
-
Statement type:
File details
Details for the file modern_python_guidance-0.5.11-py3-none-any.whl.
File metadata
- Download URL: modern_python_guidance-0.5.11-py3-none-any.whl
- Upload date:
- Size: 115.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f8947856955edc12d1431b3b3e5b9337cbf197470e4cd7cee2e1632aada0b07
|
|
| MD5 |
d57cdff939243400f6e13b982944acad
|
|
| BLAKE2b-256 |
4651fc35f9a9cb3dfba93347a7f05144c62ff54d778ac5493dfc099efb561238
|
Provenance
The following attestation bundles were made for modern_python_guidance-0.5.11-py3-none-any.whl:
Publisher:
ci.yml on yottayoshida/modern-python-guidance
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
modern_python_guidance-0.5.11-py3-none-any.whl -
Subject digest:
4f8947856955edc12d1431b3b3e5b9337cbf197470e4cd7cee2e1632aada0b07 - Sigstore transparency entry: 2357167381
- Sigstore integration time:
-
Permalink:
yottayoshida/modern-python-guidance@4a80890d0977487bbc247597bbe1e71ab6e2fc7c -
Branch / Tag:
refs/tags/v0.5.11 - Owner: https://github.com/yottayoshida
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@4a80890d0977487bbc247597bbe1e71ab6e2fc7c -
Trigger Event:
release
-
Statement type: