Turn OpenAPI specs into MCP-friendly catalogs, exports, and FastMCP bootstrap artifacts.
Project description
oas2mcp
Turn an OpenAPI spec into an inspectable, agent-refined MCP surface.
oas2mcp is not a raw OpenAPI-to-MCP mirror. It combines deterministic normalization and classification with a small agent pipeline that improves naming, descriptions, prompt surfaces, and shared server ergonomics before exporting artifacts for FastMCP bootstrap or LangGraph deployment.
What the agents do
The repo now has three distinct agent stages, each with a narrow role:
catalog summarizer: understands the API as a whole, including domains, authentication shape, and read/write patternsoperation enhancer: refines one operation at a time for titles, descriptions, tool vs resource semantics, confirmation notes, and prompt templatescatalog surface planner: designs the shared MCP layer, including catalog prompts, shared resources, and server instructions
The orchestrator keeps these stages deterministic and ordered:
- load and normalize the source spec
- classify deterministic MCP hints
- summarize the catalog once
- enhance each operation
- plan the shared surface once
- export inspectable artifacts
- bootstrap FastMCP or expose the flow through LangGraph
Why this exists
Plain OpenAPI bootstrapping is good for speed, but usually too literal for real MCP use. oas2mcp adds the semantic middle layer that OpenAPI specs usually lack:
- stable internal models
- deterministic candidate generation
- better tool, resource, and resource-template framing
- shared prompt and resource planning
- exported metadata you can inspect, diff, and reuse
- deployable graph wrappers around the same pipeline
Supported source inputs
The loader accepts common OpenAPI forms directly:
- remote URLs such as
https://example.com/openapi.json - local files such as
openapi.yamlorspecs/petstore.json file://URIs- raw JSON or YAML text
- Swagger 2.0 / OpenAPI 2 documents, normalized into the internal catalog model
What you get
- typed OpenAPI loading and normalization
- deterministic MCP candidate generation
- three focused agent layers instead of one monolithic agent
- exported artifacts under
data/exports/ - FastMCP bootstrap with name and kind overrides from exported metadata
- deployable LangGraph wrappers for the in-memory and export flows
- LangSmith tracing support for agent and deployment runs
- pytest coverage for normalization, export logic, FastMCP e2e behavior, and LangGraph deployment wrappers
By default, generated JSON stays under data/exports/. Root-level snapshot files are now opt-in only.
Install
For package usage:
pip install oas2mcp
For local development:
pdm install -G test -G docs -G cli
The cli group includes the in-memory LangGraph API server extras needed for
langgraph dev, not just the bare CLI wrapper.
Example usage
1. Load and inspect a local or remote spec
from rich.console import Console
from oas2mcp import classify_catalog, load_openapi_spec_dict, render_catalog_summary
from oas2mcp.normalize.spec_to_catalog import spec_dict_to_catalog
source = "openapi.yaml"
spec_dict = load_openapi_spec_dict(source)
catalog = spec_dict_to_catalog(spec_dict, source_uri=source)
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 agent pipeline and export artifacts
This path requires OPENAI_API_KEY.
from oas2mcp.agent.orchestrator import run_and_export_oas2mcp_pipeline
from oas2mcp.agent.runtime import Oas2McpRuntimeContext
from oas2mcp.generate.config import ExportConfig
source = "openapi.yaml"
outputs = run_and_export_oas2mcp_pipeline(
source=source,
runtime_context=Oas2McpRuntimeContext(
source_uri=source,
project_name="petstore-mcp",
user_goal="Produce a clean MCP surface for deployment.",
output_style="compact",
include_mcp_recommendations=True,
include_risk_notes=False,
),
export_config=ExportConfig(
export_dir="data/exports",
write_root_snapshot=False,
),
)
for name, path in outputs.items():
print(name, path)
Typical outputs:
data/exports/<catalog-slug>_enhanced_catalog.jsondata/exports/<catalog-slug>_operation_notes.jsondata/exports/<catalog-slug>_surface_plan.jsondata/exports/<catalog-slug>_fastmcp_config.json
3. Bootstrap FastMCP from exported artifacts
from oas2mcp.generate.fastmcp_app import (
build_fastmcp_from_exported_artifacts,
register_exported_prompts,
register_exported_resources,
)
source = "openapi.yaml"
config_path = "data/exports/example-api_fastmcp_config.json"
mcp = build_fastmcp_from_exported_artifacts(
source=source,
fastmcp_config_path=config_path,
)
register_exported_resources(mcp, config_path)
register_exported_prompts(mcp, config_path)
mcp.run(transport="http", port=8000)
The bootstrap layer respects:
- exported name overrides keyed by OpenAPI
operationId - exported
final_kindrouting for tool vs resource vs resource template - catalog-level prompts and resources from the surface planner
- server instructions derived from the shared surface plan
LangGraph and LangSmith deployment
The repo includes deployable LangGraph wrappers in src/oas2mcp/deploy/langgraph_app.py and a deployment config at config/langgraph.json.
Run the LangGraph CLI commands from the repository root so the config's ./src
and ./.env paths resolve correctly.
The two exposed graphs are:
enhance_catalog: runs the in-memory summarize -> enhance -> surface-plan flow and returns enhanced catalog JSONenhance_and_export_catalog: runs the export flow and returns written artifact paths
Run the local LangGraph dev server:
pdm run langgraph dev --config config/langgraph.json --no-browser
Validate the deployment config:
pdm run langgraph validate --config config/langgraph.json
Build or deploy:
pdm run langgraph build --config config/langgraph.json -t oas2mcp
pdm run langgraph deploy --config config/langgraph.json
langgraph deploy reads LANGSMITH_API_KEY from .env. The config is pinned to Python 3.13 so deployment matches the package runtime.
Environment
Copy the example env file:
cp .env.example .env
Required for agent-driven flows:
OPENAI_API_KEY
Optional for LangSmith tracing and LangGraph deployment:
LANGSMITH_TRACING=trueLANGSMITH_API_KEYLANGSMITH_PROJECTLANGSMITH_WORKSPACE_IDLANGSMITH_DEPLOYMENT_NAMELANGSMITH_ENDPOINTfor self-hosted LangSmith only
Optional for live upstream FastMCP checks:
UPSTREAM_BEARER_TOKENUPSTREAM_API_KEYUPSTREAM_API_KEY_HEADER
Verification
Formal test coverage:
pdm run pytest
The current suite covers:
- loader and normalization behavior
- deterministic export logic
- FastMCP in-process e2e behavior
- LangGraph wrapper behavior
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:
pdm run python scripts/test_catalog_surface_planner_agent.py
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, surface planner, runtime, orchestration
deploy/ LangGraph deployment wrappers around the orchestrator
generate/ Artifact export and FastMCP bootstrap
tests/ Unit and end-to-end coverage
scripts/ Manual smoke runners and local inspection helpers
config/ Deployment config such as LangGraph
docs/ Sphinx documentation published through Read the Docs
Documentation and release
- docs source:
docs/source/ - CI:
.github/workflows/ci.yml - docs validation:
.github/workflows/docs.yml - PyPI release:
.github/workflows/release.yml
The release path is now tag-driven and smoother:
pdm run release_cut_patch(orrelease_cut_minor/release_cut_major)git push origin maingit push origin vX.Y.Z
release_cut_* now performs the full local release cut in one step:
- checks that the worktree is clean before starting
- bumps
pyproject.tomlanddocs/source/conf.pytogether - refreshes
pdm.lock - runs tests, docs, and build validation through
pdm run release_check - creates the release commit
- creates the annotated
vX.Y.Ztag
Pushing a v* tag triggers .github/workflows/release.yml, which:
- verifies the tag matches
pyproject.toml - runs tests
- builds docs
- builds distributions
- publishes to PyPI
- creates the GitHub Release and attaches
dist/*
If you have not configured a PyPI trusted publisher yet, add a repository secret named PYPI_API_TOKEN and the same workflow can 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.10.tar.gz.
File metadata
- Download URL: oas2mcp-0.1.10.tar.gz
- Upload date:
- Size: 76.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e43e76c7b79818a76c10809d7d95173c1f0a9fbdd38e272a5b640813b58ef4a
|
|
| MD5 |
4f13af75310ae8ea32b6f4c110653938
|
|
| BLAKE2b-256 |
6a7b5dbad4aa61d03ea2c5a4b754e90533809382f2547e3b112a008108ac6f3b
|
Provenance
The following attestation bundles were made for oas2mcp-0.1.10.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.10.tar.gz -
Subject digest:
4e43e76c7b79818a76c10809d7d95173c1f0a9fbdd38e272a5b640813b58ef4a - Sigstore transparency entry: 1331479707
- Sigstore integration time:
-
Permalink:
pr1m8/oas2mcp@ec71b6d370d496f21d5e78ddad306134e7cbc979 -
Branch / Tag:
refs/tags/v0.1.10 - Owner: https://github.com/pr1m8
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ec71b6d370d496f21d5e78ddad306134e7cbc979 -
Trigger Event:
push
-
Statement type:
File details
Details for the file oas2mcp-0.1.10-py3-none-any.whl.
File metadata
- Download URL: oas2mcp-0.1.10-py3-none-any.whl
- Upload date:
- Size: 82.4 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 |
c90fe97c96c8ce6ddd61771a7b4bad1ae6b0ad7d19cd96c21712a5f7fab30528
|
|
| MD5 |
79b0ba7fc56f8e7b6565f38bc1249d2f
|
|
| BLAKE2b-256 |
543f52fa7d7ae105db7423cb414f0ded3adfdd6f0a57d0dde9126241a9a477c7
|
Provenance
The following attestation bundles were made for oas2mcp-0.1.10-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.10-py3-none-any.whl -
Subject digest:
c90fe97c96c8ce6ddd61771a7b4bad1ae6b0ad7d19cd96c21712a5f7fab30528 - Sigstore transparency entry: 1331479790
- Sigstore integration time:
-
Permalink:
pr1m8/oas2mcp@ec71b6d370d496f21d5e78ddad306134e7cbc979 -
Branch / Tag:
refs/tags/v0.1.10 - Owner: https://github.com/pr1m8
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ec71b6d370d496f21d5e78ddad306134e7cbc979 -
Trigger Event:
push
-
Statement type: