Skip to main content

prompt-to-mcp

tests PyPI Python License: MIT

Describe the MCP server you want. Point at an OpenAPI spec. Get a small, curated FastMCP server as editable code.

pip install prompt-to-mcp        # or run it without installing: uvx prompt-to-mcp

Big APIs make bad MCP servers when converted one tool per endpoint: Stripe's spec becomes 587 tools and ~463,000 tokens of definitions, more than 14 times a 32k context window. prompt-to-mcp compiles the server you describe instead, with just the tools that serve your use case, and ships an eval harness that measures the result.

Contents

Quick start

You need Python 3.12+ and one LLM. A local Ollama model works; so does any key that speaks the Anthropic or OpenAI protocol. Nothing to clone.

# grab a small example spec
curl -o petstore.yaml https://raw.githubusercontent.com/KnaniOussama/prompt-to-mcp/master/tests/fixtures/petstore.yaml

# 1. see what a naive 1:1 conversion would cost (free, no LLM involved)
uvx prompt-to-mcp inspect petstore.yaml

# 2. describe the server you want (the one step that calls an LLM)
uvx prompt-to-mcp plan petstore.yaml "a server for looking up pets and their orders" \
    -o pets.toolplan.yaml --provider ollama --model qwen2.5:7b

# 3. compile it into a runnable server (free, deterministic)
uvx prompt-to-mcp build pets.toolplan.yaml --spec petstore.yaml -o pets-server/

Step 2 writes pets.toolplan.yaml, a plain YAML plan of the tools. Open it, edit anything you disagree with, and rerun step 3. Rebuilding is free; only plan and eval call a model. p2m is a short alias for the same CLI.

Prefer automatic curation of the whole API instead of a description? Pass --auto in step 2.

Example: 587 Stripe operations, 6 tools

One sentence turned the full Stripe spec into a server scoped to a single job:

prompt-to-mcp plan stripe-spec.json \
    "a server for support agents to manage customers, invoices and refunds" \
    -o stripe-support.toolplan.yaml --max-tools 8

The description drove the curation. The model kept the customer, invoice, and refund surface and left the rest of the API (subscriptions, products, connect, webhooks, reporting) out:

Tool Read-only What it does
customer_lookup yes Find or retrieve customer information
customer_manage no Create, update, or delete a customer
invoice_lookup yes Find or retrieve invoice information
invoice_manage no Create, update, finalize, pay, void, or send an invoice
refund_lookup yes List or retrieve refunds
refund_manage no Create, update, or cancel a refund

Six tools, ~956 tokens of definitions, from an API whose naive conversion needs ~463,000. The committed artifacts: stripe-support.toolplan.yaml and generated/stripe-support/.

The same spec with --auto and no description produces a broader 11-tool general server (stripe.toolplan.yaml). Same machinery, two shapes: one fits your task, one fits the API.

How it works

flowchart LR
    S["OpenAPI spec"] --> I["inspect<br/><i>damage report</i>"]
    I --> P["plan<br/><i>1 LLM pass</i>"]
    P --> Y[["ToolPlan YAML<br/>editable, diff-friendly"]]
    Y --> B["build<br/><i>deterministic codegen</i>"]
    B --> M["FastMCP server"]
    M --> E["eval<br/><i>measure it</i>"]
    style Y fill:#fde68a,stroke:#b45309,color:#000
    style P fill:#bfdbfe,stroke:#1e40af,color:#000
Command Cost What it does
inspect free Parse the spec, report what a naive conversion costs.
plan 1 LLM pass Curate tools for your description (or --auto) into a ToolPlan YAML.
build free Compile the ToolPlan into a runnable FastMCP package.
eval LLM per trial Run task scenarios against the server, emit a report.

The ToolPlan YAML is the load-bearing design decision. The model proposes; you review and edit plain YAML; build compiles it with no model in the loop. Nothing the LLM produces is a black box. A tool in the plan looks like this:

- name: refund_lookup
  intent: List or retrieve refunds
  read_only: true
  endpoints: [GET /v1/refunds, GET /v1/refunds/{refund}]
  dispatch: { mode: select, selector: mode }   # "list" or "get" picks the endpoint
  response_filter:
    fields: [id, amount, currency, status, reason, created, charge]

Generated servers filter API responses to the fields the agent needs, inject auth from an environment variable at runtime (never baked into code), and turn API errors into plain messages an agent can act on.

Use the generated server

Each generated package is self-contained (needs only fastmcp and httpx) and comes with its own README naming its auth variable.

cd pets-server
PETSTORE_API_KEY=... fastmcp run server.py

Claude Code:

claude mcp add pets -e PETSTORE_API_KEY=... -- uv run --with fastmcp fastmcp run /path/to/pets-server/server.py

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "pets": {
      "command": "uv",
      "args": ["run", "--with", "fastmcp", "fastmcp", "run", "/path/to/pets-server/server.py"],
      "env": { "PETSTORE_API_KEY": "..." }
    }
  }
}

Models and providers

The LLM layer speaks both wire protocols, so any model works: hosted or local. This repo's own artifacts were made with a hosted model for curation and a local 7B for the evals, with zero code changes between them.

Preset (--provider) Protocol Base URL
anthropic anthropic SDK default
glm anthropic api.z.ai/api/anthropic
kimi anthropic api.moonshot.ai/anthropic
openrouter openai openrouter.ai/api/v1
ollama openai localhost:11434/v1

Anything else: --base-url <url> --api-protocol openai|anthropic. Configuration resolves flags first, then environment variables (P2M_API_KEY, P2M_MODEL, P2M_BASE_URL, P2M_API_PROTOCOL, P2M_MAX_OUTPUT_TOKENS; bare ANTHROPIC_API_KEY or OPENAI_API_KEY work as key fallbacks), then a .env in the working directory, then preset defaults. prompt-to-mcp providers prints the full picture.

Two provider quirks are handled for you: Gemini 3 requires its per-call thought_signature echoed back on multi-turn tool use, and some gateways count hidden reasoning tokens against max_tokens (the output budget is configurable, with a truncation-aware retry).

Evidence

Every request an agent makes carries the full tool list. Drawn to scale against a 32k-token window, for GitHub's API:

naive      1,206 tools │ ████████████████████████████████████████  414,263 tok   12.6× over ✗
32k window   (ceiling) │ ███                                         32,768 tok
distilled      9 tools │ ▏                                            1,758 tok   18.6× under ✓

A naive tool list this size cannot fit before the agent reads a word of the task. Strict providers reject it; lenient ones (Ollama) silently truncate it. The eval harness records the former as provider_error and refuses the latter up front with a pre-flight --model-context guard, so a mangled run is never reported as a real one.

The benchmarks below used --auto (no description), which makes them a fair, description-free comparison: naive one-tool-per-endpoint versus automatic curation, same agent (qwen2.5:7b, local), same scenarios, live APIs.

API Operations Naive tool defs Curated (--auto) Ratio Eval result
GitHub 1,206 ~414,263 tok 9 tools / ~1,758 tok 236× 13/15 correct (87%)
Stripe (test mode) 587 ~462,960 tok 11 tools / ~1,793 tok 258× 12/15 correct (80%)

The naive side was refused by the context guard in every trial; it does not fit a 32k model. Full artifacts: eval_runs/headline/ and eval_runs/stripe/.

xychart-beta
    title "Curated GitHub server: trials passed per scenario (3 trials each)"
    x-axis ["repo-overview", "repo-metadata", "list-branches", "repo-language", "search-repo"]
    y-axis "trials passed" 0 --> 3
    bar [3, 3, 3, 3, 1]

The weak scenario is also the expensive one: search-repo passed 1 of 3 and consumed about 2.7 times the input tokens of any other task. A small model that cannot decide between similar options flails, and flailing costs tokens:

xychart-beta
    title "Mean input tokens per task, by scenario"
    x-axis ["repo-overview", "repo-metadata", "list-branches", "repo-language", "search-repo"]
    y-axis "input tokens" 0 --> 10000
    bar [3582, 4062, 3448, 3401, 9569]

What this shows: the context problem is decisive, and the pipeline works end to end on live APIs with a small local agent. What it does not show yet: a comparison against a naive server that fits (cap it with --naive-max-tools on a large-context model), or a no-tools control. Both are supported by the harness and are the next experiments worth running.

Known limits:

Limitation Effect
chars/4 token estimator context figures are order-of-magnitude, not a tokenizer
Small N, one local model success rates are noisy and model-specific
No no-tools control some scenarios are partly answerable from model memory
Naive never run fitted the win leans on the context ceiling, not proven tool quality
One write scenario, missed by the 7B mutating paths are generated but not yet passed by this agent
LLM-as-judge fallback can misjudge open-ended answers

Coverage tradeoff

Curation drops long-tail endpoints on purpose. The Stripe support server above cannot touch subscriptions or payouts, because the description did not ask for them. That is the point: you decide what is covered, and the tool surface stays small enough to fit and cheap enough to reason over.

Nothing is locked in. A missing capability is one YAML edit and a free rebuild away: add the endpoint to a tool (or add a tool) in the ToolPlan, run build, done.

CLI reference

Command Purpose
prompt-to-mcp inspect SPEC Damage report for a naive conversion of SPEC (file or URL).
prompt-to-mcp plan SPEC "DESCRIPTION" Curate tools for the description. Key flags: --auto, --max-tools, --include-clusters, --intent-file, -o.
prompt-to-mcp build PLAN --spec SPEC -o DIR Compile a ToolPlan into a server package. --base-url overrides the API host.
prompt-to-mcp eval SPEC --server-dir DIR Run scenarios against the server (and the naive baseline). Key flags: --scenarios, --trials, --only, --model-context, --pace.
prompt-to-mcp providers List provider presets and configuration resolution.

Provider selection flags (--provider, --model, --base-url, --api-protocol, --max-output-tokens) work on plan and eval alike. On Windows, set PYTHONUTF8=1 for live runs.

Development

git clone https://github.com/KnaniOussama/prompt-to-mcp && cd prompt-to-mcp
uv sync
uv run pytest    # offline, no keys needed

See CONTRIBUTING.md for ground rules (determinism of build is enforced by tests) and SECURITY.md for what to know before running against real accounts. The design document is DESIGN.md.

License

MIT. See LICENSE.

Metadata

Release files for prompt-to-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)

Source distribution for prompt-to-mcp 0.1.1
File Size Uploaded Provenance Actions
prompt_to_mcp-0.1.1.tar.gz 192.4 kB With provenance Details for prompt_to_mcp-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for prompt-to-mcp 0.1.1
File Interpreter ABI Platform Actions
prompt_to_mcp-0.1.1-py3-none-any.whl Python 3 none any Details for prompt_to_mcp-0.1.1-py3-none-any.whl

Total release size: 259.9 kB

Release files / prompt_to_mcp-0.1.1.tar.gz

Download URL prompt_to_mcp-0.1.1.tar.gz
Size 192.4 kB
Tags Source
SHA-256 checksum
How to use checksums
6f713748aa00884801d584310a7ef0bb99908e30ec302d2378b66626fb70c6b2
BLAKE2b-256 checksum
How to use checksums
ba12e6e91ca0e8a8f820496ff4960bdf3d1fc115a69c2fa3fc688a638fe45383
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.

Transparency log

Release files / prompt_to_mcp-0.1.1-py3-none-any.whl

Download URL prompt_to_mcp-0.1.1-py3-none-any.whl
Size 67.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
512bb06f317b5e8b1b29b00724cbf9eb9dc4155a828aa686181b75e4445abca6
BLAKE2b-256 checksum
How to use checksums
845a34cffb90d3b359918d50d30b0b65c53aabe8cf10d018f2f53bc32c7105ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.

Transparency log

Security for prompt-to-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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for prompt_to_mcp-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.

Transparency log

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.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page