prmcp
Watch any Python SDK, auto-synthesize FastMCP tools for new resources, validate each generated tool with an LLM, and open a PR on the target MCP repo.
prmcp is a self-contained pipeline. Give it four things — an LLM API key, a GitHub PAT, the SDK repo to watch, and the MCP repo to PR into — and it handles everything else: AST-walking the SDK, diffing against a snapshot, rendering FastMCP tool wrappers, calling an LLM to validate them, and opening PRs.
Install
pip install prmcp
Or from source:
git clone <this-repo>
cd <this-repo>
pip install -e .
Requirements: Python 3.11+, git on PATH (for cloning remote SDKs), and gh CLI on PATH if you enable the optional GitHub Actions watcher.
Quickstart
In a fresh directory:
prmcp init
You'll be prompted for four values:
| Prompt | Example |
|---|---|
| OpenAI API key | sk-… |
GitHub PAT (scopes: repo) |
ghp_… |
| SDK source | a local path like ./my-sdk or an owner/repo slug to clone |
| MCP target repo | myorg/my-mcp |
prmcp init writes:
prmcp.toml— the project config (committed; see template below).env—OPENAI_API_KEY+PAT_TOKEN(added to.gitignore).prmcp/— workspace dir for the cloned SDK and the snapshot baseline (gitignored)
It auto-detects the resource directory and base classes by sampling the SDK, and lets you confirm or edit each value.
Once initialized:
prmcp up # watcher in the foreground; Ctrl-C to stop
prmcp run # one-shot pass
prmcp tail # colored terminal view of the trace JSONL
The first prmcp run seeds .prmcp/sdk-snapshot.json as the baseline. Subsequent runs diff against it — any new (resource, method) pair triggers the render → validate → PR pipeline. prmcp run --reseed resets the baseline to the current SDK state.
How it works
SDK source MCP target repo
│ ▲
│ file change │ PR opens
▼ │
prmcp.daemon → prmcp.run orchestrator │
│ │
├─ diff_sdk (AST walk)
├─ synth_tool (Jinja2 render)
├─ shadow_agent (OpenAI function-calling: valid|invalid)
└─ open_pr (PyGithub) ┘
every step → /tmp/prmcp-trace.jsonl
(tailed by `prmcp tail`)
prmcp.toml reference
[sdk]
# Local path OR "owner/repo" GitHub slug (cloned into .prmcp/sdk-source/)
source = "stripe/stripe-python"
# Glob (relative to the resolved SDK root) for the resource modules
resources_glob = "stripe/api_resources/*.py"
# Class names that mark "this is a resource". Empty list ⇒ every public
# class with public methods is treated as a resource.
resource_base_classes = ["APIResource", "ListableAPIResource"]
# Python import name of the SDK package (used inside generated tools)
import_module = "stripe"
# The expression that builds a client inside each generated tool
client_expression = "stripe"
# Exception class to catch around each SDK call
exception_class = "stripe.error.StripeError"
# Optional: file inside the SDK whose Client.__init__ assigns each resource
# class to a `self.<attr>` — used to translate ClassName → client attribute.
# client_path = "stripe/stripe_client.py"
[mcp]
target_repo = "myorg/my-mcp"
base_branch = "main"
tool_dir = "tools"
[llm]
model = "gpt-4o-mini"
# base_url = "https://api.openai.com/v1" # set for OpenAI-compatible endpoints
[ci]
# watched_repo = "owner/repo" # optional: enable the CI watcher
workflow = "prmcp.yml"
poll_interval_seconds = 30
[daemon]
poll_interval_seconds = 2.0
debounce_seconds = 3.0
[pipeline]
trace_path = "/tmp/prmcp-trace.jsonl"
dry_run = true
dry_run = true (default) prints the PR that would be opened without touching GitHub. Flip to false when you're ready for live PRs.
Console scripts
| Command | What it does |
|---|---|
prmcp init |
Interactive bootstrap of prmcp.toml + .env. Auto-detects SDK conventions. |
prmcp up |
Daemon + (optional) CI watcher in one process. Ctrl-C tears all down. |
prmcp run |
Single pipeline pass. --reseed resets the snapshot baseline. |
prmcp daemon |
SDK file watcher only. |
prmcp ci-watcher |
GitHub-Actions → local-trace bridge only. Requires [ci] watched_repo. |
prmcp tail |
Real-time terminal view of the trace JSONL. ANSI-colored, groups runs by 30s gaps. |
Environment variables
| Variable | Purpose |
|---|---|
OPENAI_API_KEY |
Required. Used by the shadow validator. |
PAT_TOKEN |
Required for live PR mode. Personal access token with repo scope. |
PRMCP_DRY_RUN |
Overrides [pipeline] dry_run (1/0). |
PRMCP_TRACE_PATH |
Overrides [pipeline] trace_path. |
PRMCP_LOG_LEVEL |
Python logging level (default INFO). |
PRMCP_INJECT_429 |
1 → simulate a single 429 from the LLM to exercise the retry path. |
Layout
your-project/
├── prmcp.toml # config, committed
├── .env # secrets, gitignored
└── .prmcp/ # gitignored
├── sdk-source/ # cloned SDK (if `source` was a GitHub slug)
├── sdk-snapshot.json
└── ci-watcher.state
License
MIT.
Metadata
Release files for prmcp 0.1.0
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 | |
|---|---|---|---|---|
| prmcp-0.1.0.tar.gz | 34.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| prmcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 73.5 kB
Release files / prmcp-0.1.0.tar.gz
| Download URL | prmcp-0.1.0.tar.gz |
|---|---|
| Size | 34.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f7a44a4919c2fa7d3ea75daf5a1774ffcf7caa7b784fcfcf939ef613e722e680
|
|
BLAKE2b-256 checksum How to use checksums |
46c8d4211589df4242fc676f56a10ac35187de9fff9f82d80b0cf12115a1445b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / prmcp-0.1.0-py3-none-any.whl
| Download URL | prmcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 39.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d056818ba50521f248f5c9c7500830a2a153c0b7e120299f1844c268ef858e42
|
|
BLAKE2b-256 checksum How to use checksums |
55fb0367b368abf0793efbffd69b4f87ff9c1103b5b950d262f1a75f106db4dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Security for prmcp 0.1.0
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.