Turn OpenAPI specs into MCP-friendly catalogs, exports, and FastMCP bootstrap artifacts.
Project description
oas2mcp
Turn an OpenAPI spec into a cleaner MCP-oriented surface.
oas2mcp loads and normalizes OpenAPI, classifies operations into deterministic MCP hints, adds catalog- and operation-level semantic refinement, exports inspectable JSON artifacts, and bootstraps a FastMCP server from the original spec plus exported metadata.
Why this exists
Raw OpenAPI-to-MCP conversion is useful for bootstrapping, but it usually produces a surface that is too literal.
oas2mcp is built to add the missing middle layer:
- normalize the source API into typed internal models
- classify likely tools, resources, and resource templates deterministically
- summarize the API at the catalog level
- refine operations one at a time for naming, descriptions, and prompt templates
- export artifacts you can inspect, diff, and reuse
- bootstrap FastMCP with exported route and naming overrides
What you get
- Typed OpenAPI loading and normalization
- Deterministic MCP candidate generation
- Exported enhanced catalog artifacts under
data/exports/ - FastMCP bootstrap that respects exported
final_kindmetadata - Explicit prompt registration for exported prompt templates
- Formal pytest coverage for normalization, export helpers, orchestrator flow, and FastMCP e2e
Install
For package usage:
pip install oas2mcp
For local development:
pdm install -G test -G docs
Example usage
1. Load and inspect an OpenAPI spec
from rich.console import Console
from oas2mcp import (
classify_catalog,
load_openapi_spec_dict_from_url,
render_catalog_summary,
spec_dict_to_catalog,
)
source_url = "https://petstore3.swagger.io/api/v3/openapi.json"
spec_dict = load_openapi_spec_dict_from_url(source_url)
catalog = spec_dict_to_catalog(spec_dict, source_uri=source_url)
bundle = classify_catalog(catalog)
print(catalog.name)
print(f"operations: {len(catalog.operations)}")
print(f"candidates: {len(bundle.candidates)}")
render_catalog_summary(catalog, console=Console())
2. Run the full summarize -> enhance -> export pipeline
This path requires OPENAI_API_KEY because it runs the catalog summarizer and operation enhancer agents.
from oas2mcp.agent.orchestrator import run_and_export_oas2mcp_pipeline
from oas2mcp.agent.runtime import Oas2McpRuntimeContext
source_url = "https://petstore3.swagger.io/api/v3/openapi.json"
outputs = run_and_export_oas2mcp_pipeline(
source_url=source_url,
runtime_context=Oas2McpRuntimeContext(
source_uri=source_url,
project_name="petstore-mcp",
user_goal="Create exported artifacts for FastMCP bootstrap.",
output_style="compact",
include_mcp_recommendations=True,
include_risk_notes=False,
),
)
for name, path in outputs.items():
print(name, path)
Typical outputs:
<catalog-slug>_enhanced_catalog.json<catalog-slug>_operation_notes.json<catalog-slug>_fastmcp_config.json- optional root snapshot:
<catalog-slug>.enhanced.json
3. Bootstrap a FastMCP server from exported artifacts
from oas2mcp.generate.fastmcp_app import (
build_fastmcp_from_exported_artifacts,
register_exported_prompts,
)
source_url = "https://petstore3.swagger.io/api/v3/openapi.json"
config_path = "data/exports/swagger-petstore-openapi-3-0_fastmcp_config.json"
mcp = build_fastmcp_from_exported_artifacts(
source_url=source_url,
fastmcp_config_path=config_path,
)
register_exported_prompts(mcp, config_path)
mcp.run(transport="http", port=8000)
The bootstrap layer now respects:
- exported OpenAPI
operationIdname overrides - exported
final_kindrouting for tool vs resource vs resource template - exported prompt templates registered explicitly on the server
Environment
Copy the example env file if you want agent-driven flows or live upstream FastMCP calls:
cp .env.example .env
Required for summarizer and enhancer flows:
OPENAI_API_KEY
Optional for live upstream FastMCP checks:
UPSTREAM_BEARER_TOKENUPSTREAM_API_KEYUPSTREAM_API_KEY_HEADER
Current status
- Deterministic parsing, normalization, classification, and export helpers are covered by pytest.
- FastMCP bootstrap is covered by an in-process e2e test that invokes tools, resources, resource templates, and prompts.
- The docs build runs in strict mode with
-W --keep-going. - Agent-driven summarizer and enhancer flows are still best treated as integration-style checks rather than pure unit tests.
Local verification
Run the formal test suite:
pdm run pytest
Run the strict docs build:
rm -rf docs/source/autoapi docs/_build
pdm run sphinx-build -b html -W --keep-going docs/source docs/_build/html
Manual smoke checks remain available for interactive inspection:
pdm run python scripts/test_orchestrator.py
pdm run python scripts/test_fastmcp_bootstrap.py
pdm run python scripts/test_fastmcp_server.py
pdm run python scripts/test_fastmcp_client.py
Project layout
src/oas2mcp/
loaders/ Fetch and parse OpenAPI sources
normalize/ Convert raw specs into normalized models
classify/ Deterministic MCP candidate generation
agent/ Summarizer, enhancer, runtime, and orchestration
generate/ Artifact export and FastMCP bootstrap
tests/ Formal unit and end-to-end coverage
scripts/ Manual smoke runners and local inspection helpers
docs/ Sphinx documentation published through Read the Docs
Documentation and release
- Docs:
docs/source/, published via Read the Docs - CI:
.github/workflows/ci.yml - Docs validation:
.github/workflows/docs.yml - PyPI release:
.github/workflows/release.yml
The release workflow is wired for GitHub Releases plus trusted publishing to PyPI.
If you have not configured a PyPI trusted publisher yet, add a repository secret
named PYPI_API_TOKEN and the same workflow will publish with a token instead.
Project details
Release history Release notifications | RSS feed
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 oas2mcp-0.1.3.tar.gz.
File metadata
- Download URL: oas2mcp-0.1.3.tar.gz
- Upload date:
- Size: 52.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
639377b326fb156266ef8eee253a09b6680cbf9ac05a84db8f6ec6180a71960b
|
|
| MD5 |
ce624cc2d4f76ec3bd2295eaad23b556
|
|
| BLAKE2b-256 |
7d7667f9c89c61dc9dec31c66ff2a5f67134ae90af92c82572197fa08a229c9d
|
Provenance
The following attestation bundles were made for oas2mcp-0.1.3.tar.gz:
Publisher:
release.yml on pr1m8/oas2mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oas2mcp-0.1.3.tar.gz -
Subject digest:
639377b326fb156266ef8eee253a09b6680cbf9ac05a84db8f6ec6180a71960b - Sigstore transparency entry: 1319851507
- Sigstore integration time:
-
Permalink:
pr1m8/oas2mcp@41d46656b9018070c4685594a73c7f0b01aea197 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/pr1m8
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@41d46656b9018070c4685594a73c7f0b01aea197 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file oas2mcp-0.1.3-py3-none-any.whl.
File metadata
- Download URL: oas2mcp-0.1.3-py3-none-any.whl
- Upload date:
- Size: 60.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0581df7af16047b76074018119ea2e7a0e9b47b57f581b3d7d2d71e8a8308f5c
|
|
| MD5 |
5053556f6c31ae368095ad5d2488d5d4
|
|
| BLAKE2b-256 |
0dc314a75db5296cca031583b32781431cdc96936dfa1c4d6087fe2317d3df69
|
Provenance
The following attestation bundles were made for oas2mcp-0.1.3-py3-none-any.whl:
Publisher:
release.yml on pr1m8/oas2mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oas2mcp-0.1.3-py3-none-any.whl -
Subject digest:
0581df7af16047b76074018119ea2e7a0e9b47b57f581b3d7d2d71e8a8308f5c - Sigstore transparency entry: 1319851570
- Sigstore integration time:
-
Permalink:
pr1m8/oas2mcp@41d46656b9018070c4685594a73c7f0b01aea197 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/pr1m8
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@41d46656b9018070c4685594a73c7f0b01aea197 -
Trigger Event:
workflow_dispatch
-
Statement type: