/`)
* **Client settings UI**: Some clients let you add MCP servers through a settings panel
## Network connection (SSE / HTTP)
For remote or containerized servers, start with a network transport:
```bash theme={null}
# SSE transport
python server.py --transport sse --port 8000
# Streamable HTTP transport
python server.py --transport streamable-http --port 8000
```
Then configure your client with the URL:
```json theme={null}
{
"mcpServers": {
"my-api": {
"url": "http://localhost:8000/sse"
}
}
}
```
This is the standard approach for Docker deployments, remote servers, and shared environments.
## Multiple servers
You can connect multiple MCP servers to a single client. Each server runs independently and securely handles its own API:
```json theme={null}
{
"mcpServers": {
"gmail": {
"command": "python",
"args": ["/path/to/gmail-server/server.py"]
},
"github": {
"command": "python",
"args": ["/path/to/github-server/server.py"]
},
"stripe": {
"command": "python",
"args": ["/path/to/stripe-server/server.py"]
}
}
}
```
The AI agent sees all tools from all servers and selects the right one based on context.
## Verifying the connection
After configuring your client:
1. Restart the client (most clients read configuration on startup)
2. Check that your API's tools are listed in the client's tool/MCP panel
3. Ask the agent to perform an operation: *"List all users using the my-api server"*
If tools don't appear, run `python server.py` directly in a terminal to verify the server starts without errors.
## Troubleshooting
### Server doesn't appear in the client
* Verify the path to `server.py` is absolute and correct
* Ensure `python` resolves to Python 3.11+ (try `python3` if needed)
* Check that `requirements.txt` dependencies are installed
* Restart the client completely after changing configuration
### Tools appear but return errors
* Check your `.env` file has correct credentials
* Run `python server.py` in a terminal to see detailed error output
* Verify the target API is reachable from your machine
### OAuth2 authorization prompt
For APIs using OAuth2, the first connection may open a browser for authorization. Run `python server.py` once in a terminal to complete the OAuth flow. After that, tokens are cached and the server works non-interactively.
# Local Development
Source: https://docs.mcpblacksmith.com/deployment/local
Run your generated MCP server locally for development and testing.
## Running the server
After installing dependencies and configuring `.env`:
```bash theme={null}
python server.py
```
By default, the server starts with **stdio** transport — the standard for local MCP connections.
## Transport options
Select a transport at runtime:
```bash theme={null}
# stdio (default) — for direct MCP client connections
python server.py
# SSE — for network-based connections
python server.py --transport sse --port 8000
# Streamable HTTP — newer HTTP-based transport
python server.py --transport streamable-http --port 8000
```
| Transport | Use case |
| ------------------- | ------------------------------------------------------- |
| **stdio** | Local MCP clients (Claude Desktop, Claude Code, Cursor) |
| **SSE** | Remote or Docker-based deployments |
| **streamable-http** | Newer MCP clients that support HTTP streaming |
## Virtual environment
It's recommended to use a virtual environment:
```bash theme={null}
cd my-api-server
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
pip install -r requirements.txt
python server.py
```
## Testing tools manually
Run the server and connect an MCP client to test individual tools. Try asking the AI agent to perform operations:
> "List all users"
> "Create a new order for product X"
> "Get the status of order #123"
Check the server's terminal output for request logs, errors, and validation warnings.
# Self-Hosting
Source: https://docs.mcpblacksmith.com/deployment/self-hosting
Deploy your generated MCP server with Docker or on any cloud provider.
## Docker
Every generated server includes a production-ready `Dockerfile`:
```bash theme={null}
# Build
docker build -t my-api-mcp .
# Run with stdio transport
docker run --env-file .env my-api-mcp
# Run with SSE transport (network accessible)
docker run -p 8000:8000 --env-file .env my-api-mcp --transport sse
```
## Cloud deployment
The server is standard Python — deploy it anywhere you can run Python 3.11+:
* **AWS** — ECS, Lambda (with SSE transport), EC2
* **Google Cloud** — Cloud Run, GCE, GKE
* **Azure** — Container Apps, ACI, AKS
* **Railway, Render, Fly.io** — Container-based platforms
* **VPS** — Any Linux server with Python installed
### Example: Docker Compose
```yaml docker-compose.yml theme={null}
services:
mcp-server:
build: .
ports:
- "8000:8000"
env_file:
- .env
command: ["python", "server.py", "--transport", "sse", "--port", "8000"]
restart: unless-stopped
```
## Connecting remote MCP clients
When running with SSE or streamable-http transport, MCP clients connect over the network:
```json theme={null}
{
"mcpServers": {
"my-api": {
"url": "http://your-server-host:8000/sse"
}
}
}
```
If exposing over the internet, add a reverse proxy (nginx, Caddy) with TLS termination. The generated server does not include TLS by default.
MCP Armory provides managed multi-tenant MCP server hosting.
# Enhancement
Source: https://docs.mcpblacksmith.com/generation/enhancement-passes
Optional optimization passes that improve your generated server for production use.
## Overview
Enhancement passes analyze your API operations and optimize the generated server for better AI agent interaction. Passes make tools and parameters not only LLM-friendly but also token-aware — reducing the number of tokens consumed by tool definitions while preserving their semantic meaning.
The Metadata Filter is rule-based and always free. The remaining three passes are AI-driven and consume credits.
### Model selection
AI-driven passes use Anthropic's Claude models, which consistently outperform other providers when processing OpenAPI specifications and code-like formats. A more capable model produces better results across all passes — we recommend **Claude Sonnet 4.6** for the best balance of quality and speed. Model selection is configurable in the Generation tab.
Additional models from other providers may be introduced in the future once we confirm stable behavior across the full pass pipeline.
## Metadata Filter
Removes parameters and operations that are provably irrelevant for API requests, using only OpenAPI specification metadata — no heuristics, no keyword matching.
**What it removes:**
* **Read-only parameters** (`readOnly: true`) — response-only fields like server-generated IDs, computed counts, and timestamps that cannot be set in requests
* **Explicitly non-writable parameters** (`writeOnly: false`) — fields marked as response-only
* **Deprecated parameters** (`deprecated: true`) — outdated fields the API provider has flagged for removal
* **Deprecated operations** (`deprecated: true`) — entire endpoints the API provider has flagged for removal
**Why it matters:** Many APIs carry dozens of read-only fields in their request schemas (creation timestamps, internal IDs, computed aggregates). Without this filter, AI agents see these as valid inputs and waste tokens trying to populate fields the API will ignore.
## Parameter Filter
Identifies and removes parameters that add noise to tool definitions without providing value for typical API usage. Runs in two phases.
**Phase 1 — Field Curation:**
An LLM analyzes each operation's parameters and identifies low-value fields such as:
* **Server-generated fields** — internal IDs, ETags, and metadata the API manages automatically
* **Computed and derived fields** — byte sizes, message counts, content snippets that the server calculates
* **Response structure controls** — field masks, expand directives, and view selectors that control response shape rather than request content
* **Server-managed timestamps** — creation, modification, and deletion timestamps that the API sets automatically
The filter is biased toward preserving path parameters, user-editable content (names, titles, descriptions), user preferences (timezone, language), behavioral controls (dry-run, notification settings), and filtering, pagination, and sorting parameters.
**Phase 2 — Mutual Exclusion:**
A second LLM pass detects redundant parameter representations within the same operation:
* **Hierarchical duplicates** — when both a complete object (`body::message`) and its individual fields (`body::message::subject`, `body::message::body`) are exposed, the simpler representation is kept
* **Duplicate identifiers** — the same identifier appearing in multiple locations (path, query, body), resolved by priority: path > body > query
* **Alternative encodings** — plaintext kept over base64 variants; direct content kept over URL pointers
**Why it matters:** Real-world APIs may expose 20–40 parameters per operation or even more, most of which are irrelevant for typical use. Reducing this to the essential set means fewer tokens in tool definitions, less confusion for AI agents, and more focused API calls.
## Parameter Consolidator
Identifies complex, non-LLM-friendly parameter representations and replaces them with simpler alternatives backed by auto-generated helper functions. Runs in two phases.
**Phase 1 — Transformation Analysis:**
An LLM evaluates each parameter and transforms it when the representation is too complex for an LLM to reliably construct. Transformations include:
* **Decompose** — a single complex parameter is split into multiple simpler ones. For example, a parameter expecting RFC 2822 email format with base64 encoding is replaced with separate fields (to, subject, body, cc, bcc) and a helper function (`build_rfc2822_message`) handles assembly and encoding.
* **Compose** — multiple related parameters are merged into a single, simpler one (less common, but applies when several parameters combine to form a structured value).
* **Complex DSL rewriting** — a parameter expecting a query language with operators (AND, OR, NOT, parentheses) is replaced with individual filter fields and a helper function builds the query string.
A single tool may have multiple transformations if it contains several complex parameters. Each transformation generates its own helper function.
Parameters that are typically not transformed: timestamps, standard formats (UUIDs, emails, URLs, hex colors), simple primitives, enums, pagination controls, and opaque binary data.
**Phase 2 — Consolidation:**
When the same parameter appears across multiple operations (eg. `body::message::raw` in both `create_draft` and `send_message`), the consolidator ensures consistent transformations — same helper function, same decomposed fields, same behavior everywhere.
**Why it matters:** Without this pass, an AI agent asked to "send an email" would need to construct an RFC 2822 formatted string, base64url-encode it, and pass it as a single opaque parameter. With this pass, the agent simply provides `to`, `subject`, and `body` — the generated helper function handles the rest.
While modern LLMs are capable of crafting complex parameter content such as DSL queries and base64-encoded payloads, doing so on every request adds repetitive token consumption and latency. Offloading these structural tasks to the MCP server via helper functions saves both time and tokens across repeated tool invocations.
## Tool Enhancer
Improves tool names, descriptions, and parameter descriptions for better discoverability and usability by AI agents. Resolves duplicate operation names across the API.
**What it enhances:**
* **Operation names** — converted to action-oriented `verb_noun` patterns. API-specific prefixes are removed, and related operations use consistent nouns (eg. all message operations use `_message` rather than mixing `_msg`, `_mail`, `_email`)
* **Operation descriptions** — rewritten to clearly describe what the tool does, including key constraints and expected behavior in 1–2 sentences
* **Parameter descriptions** — enriched with context, valid ranges, expected formats (ISO 8601, comma-separated), and constraint information
**Deduplication:**
When multiple operations end up with the same enhanced name (common in large APIs), the Tool Enhancer resolves conflicts by adding contextual suffixes — for example, three `get_message` operations become `get_message`, `get_message_thread`, and `get_message_event`.
**Why it matters:** OpenAPI specifications often contain developer-focused, cryptic, or low-quality descriptions that poorly characterize their purpose. Operation IDs may be machine-generated identifiers like `gmail.users.messages.send` or `drives_v3_files_copy`. The Tool Enhancer rewrites these into clear, action-oriented names and rich descriptions that AI agents can reliably interpret — leading to better tool selection and correct parameter usage on the first attempt.
Parameter names are not enhanced — they are preserved exactly as defined in the specification. Original names are needed for full upstream API compliance: error messages and response fields reference the spec-defined names, and renaming them would break that link. Parameter names are generally trivial for LLMs to understand regardless of style; descriptions are where enhancement has the most impact and are the primary focus of this pass.
## How to use
In the [dashboard](https://mcpblacksmith.com/dashboard):
1. Upload your specification and generate the base server (free)
2. In the Generation tab, enable the passes you want
3. Configure which operations to optimize (all or selected)
4. Click Generate — credits are consumed based on operation count for the AI-driven passes
## Credits
The Parameter Filter, Parameter Consolidator, and Tool Enhancer consume credits based on the number of operations and parameters processed. The Metadata Filter is always free. See [Pricing](https://mcpblacksmith.com/pricing) for details.
Base generation is free and requires no credits. All passes are entirely optional.
# Generation
Source: https://docs.mcpblacksmith.com/generation/generation
Configure and run MCP server generation — tools, passes, authentication overrides, and real-time progress tracking.
## Overview
The Generation tab is where you configure and run the server generation pipeline. Select which tools to include, enable enhancement passes, configure authentication overrides, and track progress in real time.
## Configuration
### Server settings
* **Server Name** — display name for your MCP server
* **LLM Model** — the AI model used for enhancement passes (does not affect base generation)
### Enhancement passes
Select which [enhancement passes](/generation/enhancement-passes) to run during generation:
* **Metadata Filter** — removes read-only fields, deprecated parameters, and deprecated operations using OpenAPI metadata. Has sub-options for filtering parameters, operations, or both.
* **Parameter Filter** — identifies and removes low-value parameters (server-generated fields, computed values, redundant representations) to reduce tool noise
* **Parameter Consolidator** — replaces complex parameter representations (eg. base64-encoded structured content, DSL queries) with simple fields backed by auto-generated helper functions
* **Tool Enhancer** — rewrites operation names and descriptions, enriches parameter descriptions for better AI agent discoverability and usability, and resolves duplicate operation names
### Tool selection
The **Tools** sub-tab lets you select which API operations to include in the generated server. By default, all operations are included. Deselect operations you don't need to reduce the server's tool count and focus on the endpoints that matter for your use case.
### Authentication overrides
The **Auth** sub-tab lets you inject custom authentication schemes that your specification doesn't define or only partially covers through [`securitySchemes`](/reference/oas-3-0#security-scheme-object).
Use authentication overrides when:
* The specification **lacks `securitySchemes` entirely** — the API requires authentication but the specification doesn't declare it
* The specification has **partial coverage** — some operations require authentication that isn't defined in the specification
* You want to **inject a different authentication type** than what the specification declares (eg. using OAuth2 instead of API key). You don't need to remove the original scheme — simply leave its `.env` credentials empty at runtime and only configure the ones you want to use, whether they come from the specification's native `securitySchemes` or from your overrides.
Each override defines the authentication type, its configuration (token URL, flows, header names), and which operations it applies to.
Changes to `.env` require a server restart to take effect.
## Generation controls
### Real-time progress
The console panel shows real-time progress as each stage completes — from validation through enhancement passes to final code generation. Each stage reports its duration and summary statistics.
### Cost tracking
The dashboard displays both **estimated cost** and **actual cost** in real time:
* **Estimated cost** is calculated before generation starts, based on the number of operations and parameters
* **Actual cost** updates as each pass completes and tends to be lower than the estimate — parameters filtered by earlier passes reduce the workload for subsequent passes, which the estimate cannot account for in advance
### Pause and resume
If generation is **paused**, the task automatically stops with a 24-hour TTL. You can resume where it left off within that window.
Generation also **auto-pauses** if you run out of credits midway through a paid pass. Top up your credits and resume — no progress is lost.
### Stop
If generation is **stopped**, all progress is lost. The server will not be generated from partial results — stopping is a full cancellation.
## Output
Once generation completes, the **Download Server** button appears. The generated server is packaged as a ZIP archive containing all files described in [Server Structure](/server/structure).
The console summary shows:
* Total tool count
* Parameter statistics (average and maximum per tool)
* Authentication type and coverage
* Duration per stage
# Upload
Source: https://docs.mcpblacksmith.com/generation/spec-upload
Supported specification formats and how to upload your OpenAPI specification.
## Supported formats
MCP Blacksmith accepts OpenAPI specifications in:
| Format | Versions | File types |
| ------- | ---------------------------------- | ------------------------ |
| OpenAPI | 2.0 (Swagger), 3.0.x, 3.1.x, 3.2.x | `.json`, `.yaml`, `.yml` |
Have a Postman Collection or Google Discovery document instead? You can convert them to OpenAPI using [postman-to-openapi](https://joolfe.github.io/postman-to-openapi/) or [google-discovery-to-openapi](https://github.com/stackql/google-discovery-to-openapi), then upload the result.
Support for additional API specification formats is planned, including GraphQL, gRPC (Protocol Buffers), AsyncAPI, RAML, and API Blueprint.
## How to upload
In the [dashboard](https://mcpblacksmith.com/dashboard):
1. Create a new project
2. Drag and drop your specification file into the upload zone, or click to browse
3. MCP Blacksmith parses and validates the specification immediately
## Where to find specifications
Most APIs publish their OpenAPI specification. Common locations:
* **API documentation pages** — Look for "OpenAPI", "Swagger", or "API Reference" links
* **Common URL patterns** — `/openapi.json`, `/swagger.json`, `/api-docs`, `/v3/api-docs`
* **GitHub repositories** — Many companies publish specifications in their public repos
* **Public registries** — [SwaggerHub](https://app.swaggerhub.com/search) or [APIs.guru](https://apis.guru)
## Specification quality tips
While any valid specification should result in a fully functional server, better specifications produce better servers:
* **Include descriptions** — These become tool descriptions for AI agents
* **Define [security schemes](/reference/oas-3-0#security-scheme-object)** — Authentication handlers are auto-generated
* **Use [component schemas](/reference/oas-3-0#components-object)** — Shared references produce deduplicated models
* **Specify [response schemas](/reference/oas-3-0#responses)** — Enables response validation at runtime
# Validation
Source: https://docs.mcpblacksmith.com/generation/validation
Validate your OpenAPI specification before generation to uncover structural issues and improve server quality.
## Overview
MCP Blacksmith validates your specification at two stages:
1. **On upload** — structural issues and required metadata are checked automatically using [openapi-spec-validator](https://github.com/python-openapi/openapi-spec-validator). This validation always runs and blocks further steps if the specification is malformed. See [Specification Upload](/generation/spec-upload) for details.
2. **Pre-generation** — the specification is syntactically validated against the OpenAPI standard. If the specification is found to be malformed, generation is blocked and errors are reported in the console.
In addition, you can run an **optional validation pass** from the Validation tab, powered by [vacuum](https://quobix.com/vacuum/), to uncover deeper issues — security pattern problems, quality gaps, and best practice violations. Fixing these issues upstream in the specification directly improves the quality of the generated server.
## How to validate
In the [dashboard](https://mcpblacksmith.com/dashboard):
1. [Upload your specification](/generation/spec-upload)
2. Navigate to the **Validation** tab
3. Select the validation rules you want to run (or use **Select All**)
4. Click **Validate specification**
Results are viewable by clicking **View issues in Viewer** or by navigating directly to the **Viewer** tab and opening the **Problems** panel. Issues are clickable and navigate to the exact location in your specification.
The Viewer currently supports viewing only. Editing specifications directly within the dashboard will be available in a future release.
## What it checks
Validation rules cover structural correctness, security patterns, and specification quality:
* **Structural issues** — duplicate paths, broken `$ref` references, ambiguous path definitions, missing required fields
* **Security concerns** — missing API description, `$ref` sibling conflicts, eval-in-markdown, script tags in markdown
* **Quality improvements** — missing operation descriptions, duplicate enum entries, license identifiers, naming conventions
Each rule includes a description and a **how to fix** guide explaining the issue and how to resolve it in your specification.
## Why it matters
A better specification produces a better server. Validation helps you:
* Discover errors that could affect security patterns and generated code quality
* Identify missing descriptions that result in undocumented tools
* Catch duplicate or ambiguous paths that lead to silent overwrites
* Surface broken references before they become runtime errors
Improve your specification and you improve the generated MCP server — validation is the fastest way to find what needs attention.
# How It Works
Source: https://docs.mcpblacksmith.com/how-it-works
Understand the MCP Blacksmith generation pipeline — from OpenAPI specification to running server.
## The generation pipeline
MCP Blacksmith converts an OpenAPI specification into a fully functional MCP server through a multi-stage pipeline:
1. **Parse & Validate** — Verify structural and syntactical specification correctness
2. **Filter & Enhance** *(optional)* — AI-curate operations and parameters
3. **Generate Code** — Produce a complete Python project with dependencies
4. **Package Server** — Bundle into a downloadable ZIP archive
### 1. Parse and validate
Your OpenAPI specification is parsed and validated for structural correctness. MCP Blacksmith supports:
* **OpenAPI 2.0** (Swagger)
* **OpenAPI 3.0.x**
* **OpenAPI 3.1.x**
* **OpenAPI 3.2.x**
Specifications are validated for schema correctness, reference integrity, and required fields before generation begins. Issues that would produce broken code block generation and are reported with specific locations and suggested fixes.
You can also run a dedicated validation pass separately to inspect your specification in detail. This is optional and non-blocking — results are shown in the Viewer tab of the dashboard.
### 2. Extract and enrich operations
Operations and their request/response schemas are extracted from the specification. Each API operation (e.g., `GET /users`, `POST /orders`) is mapped to an MCP tool with its parameters, request body, response schemas, and authentication requirements.
Optionally, request schemas can be filtered and enhanced using [enhancement passes](/generation/enhancement-passes). Read-only and server-generated fields are removed, meanwhile authentication-related fields are abstracted from AI agents. Parameter descriptions, examples, and constraints are optimized for LLM readability, and schemas are rewritten for token efficiency. This curation step is what separates a raw API wrapper from a production-quality MCP server — it ensures AI agents see only the parameters they should control, with descriptions, examples, and constraints they can understand.
### 3. Generate code
The generator produces a complete Python project:
| File | Purpose |
| ------------------ | ------------------------------------------------------------------------------------------------------- |
| `server.py` | MCP server with tool definitions for every operation |
| `_models.py` | Pydantic models for request/response validation |
| `_validators.py` | 50+ format validators (full [OAS Format Registry](https://spec.openapis.org/registry/format/) coverage) |
| `_auth.py` | Authentication handlers for each security scheme |
| `.env` | Environment variables for credentials and configuration |
| `requirements.txt` | Python dependencies |
| `LICENSE` | MIT license for generated code |
| `Dockerfile` | Production Docker build |
| `.mcp.json` | MCP client configuration template |
| `README.md` | Setup and usage instructions |
Each API operation becomes an MCP **tool** — an async function that handles parameter validation, authentication injection, HTTP request execution, and response processing.
### 4. Package and download
The complete server is packaged as a ZIP file. Extract it, install dependencies, configure credentials, and run — no additional code generation or compilation needed.
## What the generated server does at runtime
When an MCP client (like Claude) calls a tool:
1. **Validate** — Parameters are validated against Pydantic models. If types, formats, or constraints don't match, the agent receives immediate, context-rich feedback describing exactly what failed — before any request is sent to the API
2. **Authenticate** — Correct credentials are injected based on the operation's authentication requirements
3. **Execute** — HTTP request is sent to the target API with retry logic and circuit breaking
4. **Validate response** — Response is optionally validated against the API's response schema
5. **Return** — Structured data is returned to the MCP client. API errors are normalized into a consistent, LLM-readable format regardless of the upstream API's error structure
All of this happens transparently. The AI agent sees simple tools with typed parameters and receives actionable feedback on every outcome.
## Deployment considerations
Generated servers are designed for **self-hosted, single-tenant** deployment. Each server instance serves one user or application with its own credentials.
* **Do not commit `.env` to version control** — it may contain sensitive API credentials
* The server requires its dependencies installed (via `requirements.txt`, either in a virtual environment or globally)
* For multi-tenant deployment with shared infrastructure, visit MCP Armory
# Introduction
Source: https://docs.mcpblacksmith.com/index
MCP Blacksmith generates production-ready MCP servers from OpenAPI specifications in seconds.
## What is MCP Blacksmith?
MCP Blacksmith transforms OpenAPI specifications into fully functional [Model Context Protocol](https://modelcontextprotocol.io) (MCP) servers. Upload a specification, and get complete Python code — with authentication, security, and validation — ready to deploy anywhere.
**You own every line of generated code.** Download it, modify it, deploy it, sell it. No attribution, no royalties, no lock-in.
Generate your first MCP server in under 2 minutes.
## What is MCP?
The **Model Context Protocol (MCP)** is an open standard for connecting AI applications to external systems. It defines a universal interface for AI agents to discover and call tools.
MCP Blacksmith generates these MCP servers from OpenAPI specifications. Each generated server wraps an API and exposes its operations as **tools** that any MCP-compatible AI client can call:
```
AI Agent
├── MCP Server: Gmail API
├── MCP Server: Stripe API
├── MCP Server: GitHub API
└── MCP Server: Your Internal API
```
The server handles authentication, request formatting, error handling, and validation transparently — the AI agent sees simple tools with typed parameters.
## Who is MCP Blacksmith for?
* **Developers** who need MCP servers for their APIs without weeks of manual coding
* **Teams** integrating multiple APIs into AI agent workflows
* **Companies** wanting to expose their APIs to AI agents securely
* **Anyone** building with MCP-compatible AI tools and IDEs
You don't need deep technical expertise to generate MCP servers. All you need is an OpenAPI specification for the API your agent needs access to.
## What you get
Full Python server with FastMCP framework, Pydantic validation, and typed models.
Extensive support for OAuth2, API Key, JWT, Bearer, Basic, OIDC, and mTLS. See [supported security schemes](/reference/oas-3-0#security-scheme-object).
Circuit breakers, exponential backoff, rate limiting, and multi-layer timeouts.
Download the server with all dependencies. Run locally, in Docker, or on any cloud.
## Next steps
Generate your first server in 2 minutes.
Understand the generation pipeline.
What's inside a generated server.
Use your server with any MCP client.
# Quickstart
Source: https://docs.mcpblacksmith.com/quickstart
Generate and run your first MCP server in under 2 minutes.
## Prerequisites
* **Python 3.11+** installed on your machine
* An **OpenAPI specification** for the API you want to wrap (JSON or YAML)
Don't have a specification handy? Try one of these:
* **[The Cat API](https://thecatapi.com)** ([specification](https://raw.githubusercontent.com/thatapicompany/apis/main/theCatAPI.com/thecatapi-oas.yaml)) — Cat images, breeds, and facts. 18 endpoints, some public, some require a free API key
* **[JSONPlaceholder](https://jsonplaceholder.typicode.com)** ([specification](https://raw.githubusercontent.com/sebastienlevert/jsonplaceholder-api/main/openapi.yaml)) — Fake REST API for testing. 5 endpoints, fully public, no authentication required
Looking for more APIs? The [APIs.guru OpenAPI Directory](https://apis.guru) maintains thousands of validated OpenAPI specifications from real-world APIs.
## Step 1: Generate your server
Go to [mcpblacksmith.com/dashboard](https://mcpblacksmith.com/dashboard) and create a new project.
Drag and drop your OpenAPI specification file (JSON or YAML) into the upload zone. MCP Blacksmith supports OpenAPI 2.0 (Swagger), 3.0, 3.1, and 3.2.
Optionally enable the *Metadata Filter* (free) to remove read-only and server-generated fields, or paid enhancement passes to optimize tool descriptions, parameters, and constraints for AI consumption. See [Enhancement Passes](/generation/enhancement-passes) for details.
Click **Generate**. MCP Blacksmith analyzes your specification, extracts all operations, builds typed models, configures authentication, and generates the complete server code.
Download the generated server as a ZIP file. Extract it to a directory of your choice.
## Step 2: Install dependencies
```bash theme={null}
cd my-api-server
pip install -r requirements.txt
```
## Step 3: Configure credentials
If your API requires authentication, open the `.env` file and fill in your credentials:
```bash .env theme={null}
# Example: API Key authentication
API_KEY=your-api-key-here
# Example: Bearer token
BEARER_TOKEN=your-token-here
# Example: OAuth2
OAUTH2_CLIENT_ID=your-client-id
OAUTH2_CLIENT_SECRET=your-client-secret
```
The `.env` file is pre-configured with the correct variable names for your API's authentication scheme. You only need to configure the credentials for the tools you intend to use. If a tool requires credentials that are not provided, a warning is logged and the request will likely be rejected by the upstream API — unless the endpoint is public and does not require authentication.
See [Authentication](/server/authentication) for details on each authentication type.
## Step 4: Run the server
```bash theme={null}
python server.py
```
By default, the server starts with `stdio` transport — the standard for local MCP connections. You'll see output like:
```
INFO: MCP server 'The Cat API' started (transport: stdio)
```
## Step 5: Connect to an MCP client
Add your server to your MCP client's configuration. Most clients use a JSON configuration file:
```json theme={null}
{
"mcpServers": {
"the-cat-api": {
"command": "python",
"args": ["/absolute/path/to/server.py"]
}
}
}
```
Restart your MCP client so the new configuration is picked up. Your API tools are now available to the AI agent.
See the full guide at [Connecting to AI Agents](/deployment/connecting-agents) for transport options, virtual environments, and troubleshooting.
## What's next?
Understand what each generated file does.
Configure OAuth2, API keys, JWT, and more.
Circuit breakers, rate limiting, and retries.
Optimize your server with free and AI-driven passes.
# FAQ
Source: https://docs.mcpblacksmith.com/reference/faq
Frequently asked questions about MCP Blacksmith.
## Product
The Model Context Protocol (MCP) is an open standard that enables AI agents to interact with external services. It provides a unified way for AI systems to securely discover and call tools exposed by MCP servers. Learn more at [modelcontextprotocol.io](https://modelcontextprotocol.io).
MCP Blacksmith generates production-ready MCP servers from OpenAPI specifications. Upload a specification, and get complete Python code with authentication, security, and validation — ready to deploy anywhere. See [About](https://mcpblacksmith.com/about) for more.
Yes. You own all generated code outright. Use it for personal projects, commercial products, client work — no attribution required, no royalties, no restrictions.
Anywhere you can run Python 3.11+. Self-host on your infrastructure, deploy to any cloud, run in Docker, or use MCP Armory for managed hosting. See [Self-Hosting](/deployment/self-hosting) for deployment options.
Python, using the [FastMCP](https://github.com/jlowin/fastmcp) framework and [Pydantic](https://docs.pydantic.dev) for validation. TypeScript generation is on the roadmap.
Any MCP-compatible client — AI assistants, IDEs with AI features, agent frameworks, and custom applications. Generated servers support stdio, SSE, and streamable-http transports. See [Connecting to AI Agents](/deployment/connecting-agents) for setup instructions.
For supported specification formats, see [Specification Upload](/generation/spec-upload). For details on authentication, security, and customization, see [Your Generated Server](/server/structure).
## Pricing
Yes. Base server generation and the Metadata Filter are free — no credits required. You only pay for AI-driven enhancement passes (parameter curation, description optimization). See [Pricing](https://mcpblacksmith.com/pricing) for details.
Credits are consumed only when using AI-driven enhancement passes. Credit usage depends on the number of operations and parameters being optimized. The Metadata Filter is always free. No subscriptions — buy credits when you need them, use them at your own pace. Credits are valid for 1 year. See [Pricing](https://mcpblacksmith.com/pricing) for details.
Free generation and the Metadata Filter always work. Only AI-driven enhancement passes are blocked when you have insufficient credits. Your existing generated servers remain fully accessible.
For details on what each pass does, see [Enhancement Passes](/generation/enhancement-passes).
Have more questions? Visit our [FAQ](https://mcpblacksmith.com/faq) or [contact us](https://mcpblacksmith.com/contact).
# OpenAPI 3.0
Source: https://docs.mcpblacksmith.com/reference/oas-3-0
Compliance reference for OpenAPI Specification 3.0.0–3.0.4.
These pages document exactly which OpenAPI fields MCP Blacksmith processes during generation — field by field, with support status and behavior notes. Use them to check whether a specific feature in your spec will be reflected in the generated server.
This page covers [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.4.md) (all patch versions 3.0.0–3.0.4). The [OAS 3.1](/reference/oas-3-1) and [OAS 3.2](/reference/oas-3-2) pages document only what changed relative to this baseline.
**Swagger 2.0** specs are automatically converted to OAS 3.0 before generation.
### Data Types
OAS 3.0 defines primitive data types based on JSON Schema with `format` modifiers.
| Type / Format | Support | Behavior |
| ---------------------- | --------------------- | --------------------------------------------------------------------- |
| `integer` / `int32` | | Maps to `int` with runtime overflow validation |
| `integer` / `int64` | | Maps to `int` with runtime overflow validation |
| `number` / `float` | | Maps to `float` |
| `number` / `double` | | Maps to `float` |
| `string` | | Maps to `str` |
| `string` / `byte` | | Maps to `str` with Base64 encoding validation |
| `string` / `binary` | | Maps to `bytes` with binary validation |
| `boolean` | | Maps to `bool` |
| `string` / `date` | | Maps to `str` with RFC 3339 full-date validation |
| `string` / `date-time` | | Maps to `str` with RFC 3339 date-time validation |
| `string` / `password` | | Maps to `str`; no special validation (UI hint only per specification) |
#### Extended Formats
MCP Blacksmith supports all 49 formats defined in the [OAS Format Registry](https://spec.openapis.org/registry/format/) with runtime validators, plus additional formats commonly found in real-world API specifications. See the [OAS 3.2 Format Registry](/reference/oas-3-2#oas-format-registry) section for the full registry breakdown.
The following formats extend beyond what is defined in the OAS 3.0 base [Data Types](#data-types) table above:
| Format | Support | Behavior |
| ----------------------- | --------------------- | -------------------------------------------------------------------- |
| `int8` | | Signed 8-bit range validation (-128 to 127) |
| `int16` | | Signed 16-bit range validation (-32,768 to 32,767) |
| `uint8` | | Unsigned 8-bit range validation (0 to 255) |
| `uint16` | | Unsigned 16-bit range validation (0 to 65,535) |
| `uint32` | | Unsigned 32-bit range validation (protobuf/gRPC convention) |
| `uint64` | | Unsigned 64-bit range validation (protobuf/gRPC convention) |
| `double-int` | | Integer storable in IEEE 754 double without precision loss (±2^53-1) |
| `decimal` | | Arbitrary-precision decimal validation |
| `decimal128` | | IEEE 754 decimal128 validation (≤34 significant digits) |
| `time` | | RFC 3339 time validation |
| `duration` | | ISO 8601 duration validation |
| `date-time-local` | | RFC 3339 date-time without timezone |
| `time-local` | | RFC 3339 time without timezone |
| `http-date` | | RFC 7231 HTTP-date (IMF-fixdate, RFC 850, asctime) |
| `unixtime` | | Unix timestamp range validation |
| `email` | | RFC 5322 email validation |
| `idn-email` | | RFC 6531 internationalized email validation |
| `hostname` | | RFC 1123 hostname validation |
| `idn-hostname` | | RFC 5890 internationalized hostname validation |
| `ipv4` | | Dotted-decimal IPv4 validation |
| `ipv6` | | IPv6 address validation |
| `uri` | | RFC 3986 URI validation |
| `uri-reference` | | RFC 3986 URI-reference validation |
| `uri-template` | | RFC 6570 URI template validation |
| `iri` | | RFC 3987 IRI validation |
| `iri-reference` | | RFC 3987 IRI-reference validation |
| `uuid` | | UUID format validation |
| `json-pointer` | | RFC 6901 JSON Pointer validation |
| `relative-json-pointer` | | Relative JSON Pointer validation |
| `regex` | | Regular expression validation |
| `commonmark` | | CommonMark-formatted text (string type check) |
| `html` | | HTML-formatted text (string type check) |
| `char` | | Single character validation |
| `media-range` | | RFC 9110 media-range validation (e.g., `text/html`, `*/*`) |
| `base64url` | | URL-safe Base64 validation (alias for `byte`) |
| `sf-integer` | | RFC 8941 Structured Fields integer (±15 digits) |
| `sf-decimal` | | RFC 8941 Structured Fields decimal (12+3 digits) |
| `sf-string` | | RFC 8941 Structured Fields string (printable ASCII) |
| `sf-token` | | RFC 8941 Structured Fields token |
| `sf-boolean` | | RFC 8941 Structured Fields boolean (`?0` / `?1`) |
| `sf-binary` | | RFC 8941 Structured Fields binary (`:base64:`) |
#### Custom Formats (not in OAS registry)
These additional formats are not part of the OAS Format Registry but are commonly found in real-world API specifications:
| Format | Support | Behavior |
| -------------------- | --------------------- | ------------------------------------------------------------------------ |
| `unix-time` | | Unix timestamp range validation (alias: `unixtime` is the registry name) |
| `date-time-rfc-2822` | | RFC 2822 date-time validation |
| `date-time-rfc1123` | | RFC 1123 date-time validation |
| `phone-number` | | E.164 phone number validation |
| `timestamp` | | Alias for `unix-time` |
| `url` | | Alias for `uri` |
Unknown format strings are kept as metadata on the generated field (visible to AI agents) but have no runtime validation.
### OpenAPI Object (Root)
| Field | Support | Behavior |
| ------------ | --------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `openapi` | | Selects version-specific validation and processing rules (3.0, 3.1, and 3.2 each have dedicated handling) |
| `info` | | Title becomes the server name; description and version appear in the server docstring and `.env` |
| `servers` | | Three-level cascade: root → `BASE_URL`, path-item/operation → per-tool URL overrides in `.env` |
| `paths` | | Each operation becomes an MCP tool with typed parameters, authentication, and response models |
| `components` | | Schemas become Pydantic models; parameters, request bodies, and responses are resolved via `$ref` into tool definitions |
| `security` | | Generates authentication classes applied to all tools unless overridden per-operation |
### Info Object
| Field | Support | Behavior |
| ---------------- | --------------------- | ---------------------------------------------------------------- |
| `title` | | Used as fallback server name when no override provided |
| `description` | | Used as generated server description |
| `termsOfService` | | Rendered in generated server docstring and README |
| `contact` | | Contact name, email, URL rendered in server docstring and README |
| `license` | | License name and URL rendered in server docstring and README |
| `version` | | Appears in the generated server docstring |
### Server Object
All three server levels are supported (`operation > pathItem > root`). The first entry at each level is used; you can override any resolved URL via `SERVER_URL_*` environment variables.
| Field | Support | Behavior |
| ----------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url` | | Resolved with variable default substitution; trailing slashes stripped. At root level, becomes `BASE_URL`. At path-item/operation level, stored as per-tool override when it differs from root |
| `variables` | | Defaults substituted into URL at all three levels. Root-level variables become `SERVER_*` entries in `.env` — editable by the user to switch environments without code changes |
#### Server Variable Object
| Field | Support | Behavior |
| ------------- | --------------------- | --------------------------------------------------------------------------------- |
| `enum` | | Documented as allowed values in `.env` comments (root-level variables) |
| `default` | | Substituted into server URL; used as env var default value (root-level variables) |
| `description` | | Rendered as `.env` comment (root-level variables) |
Only `servers[0]` is used at each level. Multiple server entries (e.g., production vs sandbox) are accepted but alternates beyond the first are not exposed. Users can override any resolved URL via the corresponding `SERVER_URL_*` or `BASE_URL` environment variable.
### Paths Object
| Feature | Support | Behavior |
| ----------------- | --------------------- | ---------------------------------------------------------------------------------- |
| `/{path}` entries | | All path entries processed for MCP tool generation |
| Path templating | | Template variables (e.g., `/users/{id}`) become path parameters on generated tools |
### Path Item Object
| Field | Support | Behavior |
| ------------ | --------------------- | --------------------------------------------------------------------------------------------- |
| `$ref` | | Shared path items resolved — multiple paths can reference the same definition |
| `get` | | Generates an MCP tool |
| `put` | | Generates an MCP tool |
| `post` | | Generates an MCP tool |
| `delete` | | Generates an MCP tool |
| `options` | | Generates an MCP tool |
| `head` | | Generates an MCP tool |
| `patch` | | Generates an MCP tool |
| `trace` | | Generates an MCP tool |
| `servers` | | Per-path server override applied to all operations under this path item |
| `parameters` | | Inherited by all operations; overridden by operation-level parameters with same name+location |
### Operation Object
| Field | Support | Behavior |
| ------------- | --------------------- | --------------------------------------------------------------------------------- |
| `summary` | | Preferred as the tool description shown to AI agents |
| `description` | | Used as the tool description when `summary` is absent |
| `operationId` | | Primary tool name identifier; auto-synthesized from method + path when missing |
| `parameters` | | Each parameter becomes a typed argument on the generated tool function |
| `requestBody` | | Body schema properties are flattened into tool function arguments |
| `responses` | | Success response schema generates a Pydantic model used as the tool's return type |
| `tags` | | Rendered as comments in generated server code and used for operation grouping |
| `deprecated` | | Deprecated operations optionally filtered out during generation |
| `security` | | Per-operation authentication requirements override global security |
| `servers` | | Per-operation server override; takes priority over path-item and root servers |
| `callbacks` | | Not supported. Planned for a future release |
### Parameter Object
#### Core Fields
| Field | Support | Behavior |
| ----------------- | --------------------- | -------------------------------------------------------------------------------------------------- |
| `name` | | Used as parameter identifier; collision-safe renaming applied when names conflict across locations |
| `in` | | All four locations supported: `path`, `query`, `header`, `cookie` |
| `description` | | Becomes `Field(description=...)` on the generated parameter, visible to AI agents |
| `required` | | Controls whether parameter has a default value; always `true` for path params |
| `deprecated` | | Deprecated parameters optionally filtered out during generation |
| `allowEmptyValue` | | Not processed (flagged NOT RECOMMENDED since OAS 3.0.2) |
#### Serialization Fields
| Field | Support | Behavior |
| --------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `style` | | Read for query and path parameters; non-default styles generate serialization transforms |
| `explode` | | Read for query and path parameters; non-default values generate serialization transforms |
| `schema` | | Determines the Python type annotation for the generated tool parameter |
| `example` | | Emitted in generated `Field(examples=[...])` |
| `examples` | | Named Example Objects read and emitted in `Field(examples=[...])`. When both `example` and `examples` present, `examples` takes priority |
| `content` | | Supported for all locations. Content-encoded values are JSON-serialized for `application/json` and `*+json` media types. Non-JSON encodings pass through as-is |
| `allowReserved` | | Not supported — `httpx` always percent-encodes query parameters; most servers decode transparently |
#### Serialization Style Values
| Style | Support | Behavior |
| ---------------- | --------------------- | ------------------------------------------------------------------------------------------------- |
| `matrix` | | Path params: `;name=value` serialization for primitives, arrays, and objects with explode control |
| `label` | | Path params: `.value` serialization for primitives, arrays, and objects with explode control |
| `form` | | Default for query/cookie; `explode: false` generates comma-joined serialization |
| `simple` | | Default for path/header; primitives pass through, arrays/objects comma-joined |
| `spaceDelimited` | | Query params: space-joined serialization for arrays |
| `pipeDelimited` | | Query params: pipe-joined serialization for arrays |
| `deepObject` | | Query params: `key[subkey]=value` serialization for objects |
### Request Body Object
| Field | Support | Behavior |
| ------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `description` | | Used as docstring on generated body model classes |
| `content` | | Content type selected by priority: `application/json` → `application/x-www-form-urlencoded` → `multipart/form-data` → `application/xml` → `*/*` → first available. Each tool uses the correct HTTP encoding for its content type |
| `required` | | When `false`, all body parameters become optional. When `true`, optionality follows the schema's `required` array |
### Media Type Object
| Field | Support | Behavior |
| ---------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `schema` | | Generates the Pydantic model for this request or response body |
| `example` | | For flat body schemas, emitted in `Field(examples=[...])`. For multi-property schemas, property-level examples are used instead |
| `examples` | | Same as `example`. Named Example Objects normalized to list format. `externalValue` not fetched |
| `encoding` | | Not processed. Per-property serialization for form and multipart bodies |
Media type range matching (e.g., `application/*` per RFC 7231) is not implemented. Content type keys are matched literally.
#### Encoding Object
| Field | Support | Behavior |
| --------------- | --------------------- | ------------------------------------------------- |
| `contentType` | | Per-field media type override for multipart parts |
| `headers` | | Additional headers per multipart part |
| `style` | | Serialization style for form-encoded fields |
| `explode` | | Explode flag for form-encoded fields |
| `allowReserved` | | Reserved character encoding control |
The Encoding Object is not supported. Generated servers send form and multipart bodies using standard encoding — per-property overrides (`contentType`, `headers`, `style`) are rarely needed in practice.
### Responses
| Feature | Support | Behavior |
| ------------------ | ------------------------------------ | ------------------------------------------------------------- |
| Status codes | | Each status code's schema generates a Pydantic response model |
| `default` | | Supported but not semantically distinguished as fallback |
| `1XX`, `2XX`, etc. | | Range codes accepted but no semantic range interpretation |
#### Response Object
| Field | Support | Behavior |
| ------------- | --------------------- | ------------------------------------------------------------------------- |
| `description` | | Becomes the docstring on the generated Pydantic response model |
| `content` | | Schema from the matched media type generates the response model fields |
| `headers` | | Not applicable — MCP tools return structured data, not raw HTTP responses |
| `links` | | Not applicable — operation chaining is handled by the AI agent at runtime |
### Schema Object
#### JSON Schema Keywords
| Field | Support | Behavior |
| ---------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title` | | Used as context during model class naming. Final class names are derived from the schema's location path |
| `multipleOf` | | Generates `Field(multiple_of=...)` |
| `maximum` | | Generates `Field(le=...)` |
| `exclusiveMaximum` | | When `true`, combined with `maximum` to produce `Field(lt=...)` |
| `minimum` | | Generates `Field(ge=...)` |
| `exclusiveMinimum` | | When `true`, combined with `minimum` to produce `Field(gt=...)` |
| `maxLength` | | Generates `Field(max_length=...)` |
| `minLength` | | Generates `Field(min_length=...)` |
| `pattern` | | Generates `Field(pattern=...)`; incompatible regex patterns are not processed |
| `maxItems` | | Generates `Field(max_length=...)` on list fields |
| `minItems` | | Generates `Field(min_length=...)` on list fields |
| `uniqueItems` | | Runtime uniqueness validation; handles unhashable items via equality comparison |
| `maxProperties` | | Generates `Field(max_length=...)` on dict fields |
| `minProperties` | | Generates `Field(min_length=...)` on dict fields |
| `required` | | Controls field optionality in generated models |
| `enum` | | Generates `Literal["a", "b", ...]` type annotation |
| `type` | | Maps to the corresponding Python type. When omitted, inferred from `properties` or composition keywords |
| `allOf` | | All variant properties merged into a single Pydantic model |
| `anyOf` | | Generates `Union[A, B, ...]` type annotation |
| `items` | | Generates `list[ItemType]` annotation |
| `properties` | | Each property becomes a typed field on the generated Pydantic model |
| `additionalProperties` | | Boolean or schema. `true` → permissive model, `false` → strict model, schema → `dict[str, ValueType]` |
| `description` | | Generates `Field(description=...)` |
| `format` | | All 49 [OAS Format Registry](https://spec.openapis.org/registry/format/) formats plus custom extensions generate runtime validators; unknown formats kept as metadata for AI visibility |
| `default` | | Generates `Field(default=...)` with type-aware coercion |
| `oneOf` | | Generates `Union[A, B, ...]`. Exclusivity not enforced without explicit `discriminator` |
| `not` | | Only `not: {required: [...]}` mutual exclusivity pattern handled |
#### OAS Extension Keywords
| Field | Support | Behavior |
| --------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| `nullable` | | Produces `T \| None` type annotation. Parameters accept `None` values but explicit `null` cannot be sent to the upstream API |
| `discriminator` | | Generates `Field(discriminator="field")` when viable; validates all variants |
| `readOnly` | | Read-only parameters optionally filtered out during generation |
| `writeOnly` | | Write-only parameters kept (request-only fields) |
| `example` | | Converted to `Field(examples=[...])` format |
| `deprecated` | | Deprecated parameters and operations optionally filtered out during generation |
Nullable type annotations (`T | None`) are generated correctly, but explicit `null` values cannot be sent to the upstream API. The MCP protocol implementation does not distinguish between an omitted parameter and one explicitly set to `null` — both arrive as `None` in the tool function. This is an MCP ecosystem limitation, not a generation issue.
#### Discriminator Object
| Field | Support | Behavior |
| -------------- | --------------------- | ------------------------------------------------------------------------------- |
| `propertyName` | | Validated against all variants; generates `Field(discriminator=...)` |
| `mapping` | | Not processed. Union variants are built from the `oneOf`/`anyOf` array directly |
### Components Object
| Field | Support | Behavior |
| ----------------- | --------------------- | ------------------------------------------------------------------------------------------- |
| `schemas` | | Each schema becomes a Pydantic model class, used as request/response types across tools |
| `responses` | | Shared response definitions resolved into Pydantic models wherever referenced |
| `parameters` | | Shared parameter definitions resolved into typed tool arguments wherever referenced |
| `requestBodies` | | Shared body definitions resolved into tool arguments wherever referenced |
| `securitySchemes` | | Each referenced scheme generates a dedicated authentication class with `.env` configuration |
| `headers` | | Not applicable — request headers are handled via `in: header` parameters instead |
| `links` | | Not applicable — operation chaining is handled by the AI agent |
| `callbacks` | | Not supported. Planned for a future release |
### Reference Object
| Feature | Support | Behavior |
| --------------- | --------------------- | -------------------------------------------------------------------------------- |
| Local `$ref` | | Full JSON Pointer resolution (`#/...`) within the specification |
| External `$ref` | | External file/URL references not resolved. Planned for multi-file bundle support |
In OAS 3.0, sibling properties alongside `$ref` should be ignored. MCP Blacksmith implements OAS 3.1 superset behavior — select siblings (`description`, `summary`, `default`, `deprecated`, `readOnly`, `writeOnly`) are honored alongside `$ref`.
### Security Scheme Object
| Field | Support | Behavior |
| ------------------ | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | | All four types: `apiKey`, `http`, `oauth2`, `openIdConnect` |
| `name` | | API key parameter name used in the generated authentication class |
| `in` | | All three locations: `query`, `header`, `cookie` |
| `scheme` | | `basic` → BasicAuth; `bearer` → BearerTokenAuth; other schemes → generic bearer fallback |
| `bearerFormat` | | When `"JWT"`, generates a JWT Bearer auth class that signs tokens with a private key (RS256). See [JWT Bearer authentication](/server/authentication#jwt-bearer) |
| `flows` | | All four OAuth2 flows supported |
| `openIdConnectUrl` | | Used in generated OpenID Connect authentication configuration |
#### OAuth Flows Object
| Field | Support | Behavior |
| ------------------- | --------------------- | ------------------------------------------------------ |
| `implicit` | | Supported (lowest priority among flows) |
| `password` | | Supported (third priority) |
| `clientCredentials` | | Supported (second priority) |
| `authorizationCode` | | Supported (highest priority; preferred when available) |
[OAS 3.2](/reference/oas-3-2#oauth-flows-object) adds a fifth flow, `deviceAuthorization`, which slots between `clientCredentials` and `password` in the priority order.
When a specification defines multiple OAuth2 flows on the same security scheme, the generator selects **one flow** based on security priority: `authorizationCode` > `clientCredentials` > `deviceAuthorization` > `password` > `implicit`. This ensures the server always uses the most secure available grant type. See [Flow Selection](/server/authentication#flow-selection) for details.
#### OAuth Flow Object
| Field | Support | Behavior |
| ------------------ | --------------------- | ----------------------------------------------------------------------- |
| `authorizationUrl` | | Used in the generated OAuth2 auth class for the authorization redirect |
| `tokenUrl` | | Used in the generated OAuth2 auth class for token exchange |
| `refreshUrl` | | Used in the generated OAuth2 auth class for automatic token refresh |
| `scopes` | | Per-operation scopes are passed to the auth class during token requests |
#### Security Requirement Object
| Feature | Support | Behavior |
| ------------- | --------------------- | --------------------------------------------------------------------------------------------------------------- |
| OR logic | | Each array entry is an OR alternative, sorted by security: `mutualTLS > oauth2 > openIdConnect > http > apiKey` |
| AND logic | | Multiple schemes within a single entry treated as AND |
| Empty (`[]`) | | Recognized as "no auth required" |
| Global | | Default `security` applied to all operations |
| Per-operation | | Operation-level `security` overrides global |
### Example Object
| Field | Support | Behavior |
| --------------- | --------------------- | -------------------------------------------------------------------- |
| `value` | | Inline and `$ref` both supported; emitted in `Field(examples=[...])` |
| `externalValue` | | External example URLs not fetched |
### Specification Extensions
| Feature | Support | Behavior |
| ---------------------- | --------------------- | --------------------------------------------------------------- |
| `x-*` extension fields | | Ignored during generation. Their presence does not cause errors |
### Additional Generator Capabilities
Features that go beyond per-field processing of the OAS 3.0 specification:
| Feature | Support | Behavior |
| ------------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Circular `$ref` handling | | Self-references, mutual references, and deep chains all detected and handled with forward references |
| Inline schema discovery | | Unnamed schemas within request/response bodies automatically become generated classes |
| Name collision resolution | | Same-name parameters across locations and duplicate `operationId` values across operations get collision-safe renaming |
| Multiple OAuth2 merging | | Identical-scope schemes merged into a single auth class |
| Content type negotiation | | Multiple media types with different schemas generate separate tools. Identical schemas use highest-priority type |
| Strict/Permissive models | | Models with `additionalProperties: false` or `unevaluatedProperties: false` use strict mode (`extra='forbid'`); all others use permissive (`extra='allow'`) |
Generated server doesn't match this reference? Let us know — we'll fix it.
# OpenAPI 3.1
Source: https://docs.mcpblacksmith.com/reference/oas-3-1
Compliance reference for new and changed features in OpenAPI 3.1 (JSON Schema 2020-12 alignment).
This page covers new and changed features in [OpenAPI 3.1](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md) (3.1.0–3.1.2) relative to [OAS 3.0](/reference/oas-3-0). Only deltas are documented — for base feature coverage, see the [OAS 3.0](/reference/oas-3-0) page.
### Data Types
OAS 3.1 aligns data types with JSON Schema Draft 2020-12. The primitive format table is unchanged from [OAS 3.0](/reference/oas-3-0#data-types).
| Field | Support | Behavior |
| ------------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` as array | | `["string", "null"]` maps to `str \| None`, `["string", "integer"]` maps to `str \| int` |
| `contentEncoding` | | `base64`/`base64url` generates `format: byte` validation. `base16`/`base32` stored as metadata. Raw value surfaced in `Field(json_schema_extra=...)` for LLM visibility |
| `contentMediaType` | | Surfaced in `Field(json_schema_extra=...)` alongside `contentEncoding` and `format` |
| `type: "null"` standalone | | Maps to `None` type annotation |
| `contentSchema` | | Schema of decoded content. Not processed |
### OpenAPI Object (Root)
| Field | Support | Behavior |
| ------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `paths` | | Specification must contain at least one of `paths`, `components`, or `webhooks`. Specifications without `paths` produce no tools |
| `jsonSchemaDialect` | | Standard OAS 3.1 dialect assumed. Custom JSON Schema dialects not supported |
| `webhooks` | | Not supported. Planned for a future release |
### Info Object
New `summary` field added to the Info Object.
| Field | Support | Behavior |
| --------- | --------------------- | -------------------------------------------------------- |
| `summary` | | Rendered in generated server module docstring and README |
#### License Object
New `identifier` field for SPDX license expressions.
| Field | Support | Behavior |
| ------------ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `identifier` | | SPDX license expression (e.g., `"Apache-2.0"`); mutually exclusive with `url`. Rendered in generated server docstring and README. Takes precedence over `url` when present |
### Schema Object
The Schema Object is now a superset of JSON Schema Draft 2020-12.
#### Changed Keywords
| Field | Support | Behavior |
| ------------------ | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `exclusiveMaximum` | | Now a standalone number (was boolean in 3.0). Both forms generate correct `Field(lt=...)` constraints |
| `exclusiveMinimum` | | Now a standalone number (was boolean in 3.0). Both forms generate correct `Field(gt=...)` constraints |
| `type` | | Can now be a string or array. `["string", "null"]` maps to `str \| None`, `["string", "integer"]` maps to `str \| int` |
| `example` | | Deprecated in 3.1 in favor of `examples`. Both forms are read and emitted in generated `Field(examples=[...])` |
| `$ref` siblings | | `$ref` can now coexist with sibling keywords. Generated output merges `description`, `summary`, `default`, `deprecated`, `readOnly`, `writeOnly` from siblings |
| `nullable` | | Removed in 3.1, replaced by type arrays. Both forms produce identical `T \| None` type annotation. See [nullable limitation](/reference/oas-3-0#oas-extension-keywords) |
#### New JSON Schema 2020-12 Keywords
##### Conditional / Composition
| Field | Support | Behavior |
| ---------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `if` / `then` / `else` | | Generates `@model_validator` with conditional logic. When `if` matches, `then` constraints enforced; otherwise `else` constraints |
| `dependentRequired` | | Generates `@model_validator` enforcing "if field X present, fields Y and Z required" |
| `const` | | Generates `Literal[value]` type annotation |
| `dependentSchemas` | | Not processed. Referenced schemas within are discovered for model generation, but conditional application is not enforced |
##### Array
| Field | Support | Behavior |
| ------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `prefixItems` | | Generates `tuple[T1, T2, ...]` for fixed-position arrays. With `items: false` produces a fixed-length tuple. With an `items` schema falls back to `list[Union]` |
| `contains` | | Generates `AfterValidator` that validates at least one item matches the subschema. Supported patterns: `const`, `enum`, `pattern`, numeric range, string length. Complex subschemas not processed |
| `minContains` | | Enforced via `AfterValidator` — counts matching items and raises `ValueError` when below the threshold (default 1) |
| `maxContains` | | Enforced via `AfterValidator` — counts matching items and raises `ValueError` when above the threshold |
##### Object
| Field | Support | Behavior |
| ----------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `propertyNames` | | Generates `AfterValidator` validating all dict keys. Supported: `const`, `enum`, `pattern`, `minLength`/`maxLength`. `{"type": "string"}` is a no-op |
| `unevaluatedProperties` | | Composition-aware `additionalProperties`. `false` produces a strict model, `true`/schema produces a permissive model. Takes precedence over `additionalProperties`. Sub-schema validation on extras not enforced |
| `unevaluatedItems` | | `false` with `prefixItems` produces a fixed-length `tuple[T1, T2, ...]`. Same effect as `items: false` at code generation level |
| `patternProperties` | | Standalone usage maps to `dict[str, T]` with regex patterns in `Field(json_schema_extra=...)`. When combined with `properties`, named fields are generated but regex-keyed extras are not surfaced as parameters |
##### Schema Identity / Reference
| Field | Support | Behavior |
| ---------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `$id` | | Schemas with `$id` URIs are resolved to standard `#/components/schemas/...` references. Supports absolute URIs, relative URIs, and nested `$id` scope chains |
| `$anchor` | | `$ref: "#myAnchor"` resolved to standard JSON Pointer references |
| `$defs` | | Definitions are hoisted into `components/schemas` with collision-safe renaming. All `$defs` references rewritten to standard JSON Pointers |
| `$dynamicRef` | | `$dynamicRef: "#name"` resolved by matching `$dynamicAnchor: "name"` within the same document. Full dynamic scoping not implemented |
| `$dynamicAnchor` | | Same limitation as `$dynamicRef` — duplicate names use first-seen rather than dynamic scoping precedence |
| `$vocabulary` | | Meta-schema keyword. Not applicable to code generation |
| `$comment` | | Human-readable comment. No runtime effect |
| `$schema` | | Per-schema dialect declaration |
##### Content
| Field | Support | Behavior |
| ------------------ | --------------------- | ------------------------------------- |
| `contentEncoding` | | See [Data Types](#data-types) section |
| `contentMediaType` | | See [Data Types](#data-types) section |
| `contentSchema` | | Not processed |
##### Metadata
| Field | Support | Behavior |
| ------------------ | --------------------- | --------------------------------------------------------------------------------------- |
| `examples` (array) | | Emitted in generated `Field(examples=[...])` alongside the deprecated `example` keyword |
### Components Object
| Field | Support | Behavior |
| ----------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pathItems` | | Reusable Path Item Objects referenced via `$ref` from `paths` are fully resolved. Path-level parameters, sibling overrides, and multiple paths referencing the same `pathItem` all work correctly |
### Reference Object
New `summary` and `description` sibling properties.
| Field | Support | Behavior |
| ------------- | --------------------- | ---------------------------------------------------------------- |
| `summary` | | Overrides referenced component's summary in generated output |
| `description` | | Overrides referenced component's description in generated output |
In OAS 3.0, `$ref` siblings were supposed to be ignored. The generator already supported `summary`/`description` siblings, now officially sanctioned by 3.1.
### Security Scheme Object
New `mutualTLS` type.
| Field | Support | Behavior |
| ---------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `mutualTLS` type | | TLS transport layer authentication via client certificates. Generated server configures mTLS cert/key paths via environment variables |
Generated server doesn't match this reference? Let us know — we'll fix it.
# OpenAPI 3.2
Source: https://docs.mcpblacksmith.com/reference/oas-3-2
Compliance reference for new and changed features in OpenAPI Specification 3.2.
This page covers new and changed features in [OpenAPI 3.2](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.2.0.md) relative to [OAS 3.1](/reference/oas-3-1). Only deltas are documented — for base feature coverage, see the [OAS 3.0](/reference/oas-3-0) and [OAS 3.1](/reference/oas-3-1) pages.
### OpenAPI Object (Root)
| Field | Support | Behavior |
| --------- | --------------------- | ----------------------------------------------------------------------------------------- |
| `openapi` | | `"3.2.x"` accepted |
| `$self` | | Document's canonical URI. Appears as "Specification Source" in generated server docstring |
### Server Object
| Field | Support | Behavior |
| ------ | --------------------- | ------------------------------------------------------------------------- |
| `name` | | Server host identifier. Appears as "Server" in generated server docstring |
### Path Item Object
| Field | Support | Behavior |
| ---------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query` | | HTTP QUERY method. Generates an MCP tool identical to other HTTP methods. When `operationId` is absent, auto-generated name uses `query_` prefix (e.g., `query_search`) |
| `additionalOperations` | | Map of arbitrary HTTP method strings (e.g., COPY, MOVE, LOCK, PROPFIND) to Operation Objects. Each entry generates an MCP tool with the method string sent as-is (uppercased) |
### Parameter Object
#### New Parameter Location
| Location | Support | Behavior |
| ------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `querystring` | | Entire URL query string as a single parameter value, specified via `content` with a media type. Supported: `application/x-www-form-urlencoded`, `application/json` / `*+json`, `text/plain` / `text/*`. Unsupported media types fall back to `application/x-www-form-urlencoded` |
#### New Serialization Style
| Style | Support | Behavior |
| -------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cookie` | | RFC 6265-compliant cookie serialization. Name-value pairs separated by `; `, no percent-encoding. Supports primitives, arrays, and objects with explode control |
#### Changed Field Types
| Field | Support | Behavior |
| --------- | --------------------- | -------------------------------------------------------------------------------------------------- |
| `content` | | Map values now allow Reference Objects. `$ref` values in `content` maps are resolved transparently |
### Request Body Object
| Field | Support | Behavior |
| --------- | --------------------- | ----------------------------------------------------------------------------- |
| `content` | | Map values now accept Reference Objects. `$ref` values resolved transparently |
### Media Type Object
| Field | Support | Behavior |
| ---------------- | --------------------- | ------------------------------------------------------------------------------------- |
| `itemSchema` | | Schema for each item in sequential media types. Planned for future streaming support |
| `prefixEncoding` | | Positional Encoding Objects for multipart types. Planned for future streaming support |
| `itemEncoding` | | Per-item Encoding Object for multipart arrays. Planned for future streaming support |
#### Sequential Media Types
OAS 3.2 formalizes sequential/streaming media types. Planned for future streaming support.
| Media Type | Support | Behavior |
| ---------------------- | --------------------- | -------------------------------------- |
| `application/jsonl` | | JSON Lines — each line is a JSON value |
| `application/x-ndjson` | | Newline-Delimited JSON |
| `application/json-seq` | | JSON Text Sequences (RFC 7464) |
| `text/event-stream` | | Server-Sent Events (SSE) |
| `multipart/mixed` | | Sequential multipart content |
### Responses
#### Response Object
| Field | Support | Behavior |
| ------------- | --------------------- | ----------------------------------------------------------------------------- |
| `description` | | Absent descriptions handled gracefully |
| `content` | | Map values now accept Reference Objects. `$ref` values resolved transparently |
### OAS Format Registry
OAS 3.2 introduced the [OAS Format Registry](https://spec.openapis.org/registry/format/) — a canonical list of 49 format values for use with the `format` keyword. MCP Blacksmith supports all 49 registry formats with runtime validators.
| Category | Support | Formats |
| ---------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Integer | | `int8`, `int16`, `int32`, `int64`, `uint8`, `uint16`, `uint32`, `uint64`, `double-int` |
| Number | | `float`, `double`, `decimal`, `decimal128` |
| Binary/encoding | | `byte`, `binary`, `base64url` |
| Date/time | | `date`, `date-time`, `time`, `duration`, `date-time-local`, `time-local`, `http-date`, `unixtime` |
| String/text | | `password`, `commonmark`, `html`, `char`, `regex` |
| Email/hostname | | `email`, `idn-email`, `hostname`, `idn-hostname` |
| Network/identifiers | | `ipv4`, `ipv6`, `uri`, `uri-reference`, `uri-template`, `iri`, `iri-reference`, `uuid`, `json-pointer`, `relative-json-pointer`, `media-range` |
| Structured Fields (RFC 8941) | | `sf-integer`, `sf-decimal`, `sf-string`, `sf-token`, `sf-boolean`, `sf-binary` |
For detailed behavior of each format, see the [Extended Formats](/reference/oas-3-0#extended-formats) table on the OAS 3.0 page. MCP Blacksmith also supports [custom formats](/reference/oas-3-0#custom-formats-not-in-oas-registry) not in the registry for common API conventions.
### Schema Object
No changes from 3.1. See [OAS 3.1 Schema Object](/reference/oas-3-1#schema-object) for full coverage.
#### Discriminator Object
| Field | Support | Behavior |
| ---------------- | --------------------- | ------------------------------------------------------------------------------------------------ |
| `propertyName` | | The discriminating property MAY now be optional. When optional, `defaultMapping` must be present |
| `defaultMapping` | | Fallback schema when the discriminating property is absent or unmapped |
### Components Object
| Field | Support | Behavior |
| ------------ | --------------------- | ---------------------------------------------------------- |
| `pathItems` | | Reusable Path Item Objects via `$ref` from `paths` |
| `mediaTypes` | | Reusable Media Type Objects via `$ref` from `content` maps |
### Security Scheme Object
| Field | Support | Behavior |
| ------------------- | ------------------------------------ | ----------------------------------------------------------------------------- |
| `deprecated` | | Supported on Operations and Parameters. Not yet supported on Security Schemes |
| `oauth2MetadataUrl` | | OAuth 2.0 Authorization Server Metadata URL (RFC 8414) |
#### OAuth Flows Object
| Field | Support | Behavior |
| --------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `deviceAuthorization` | | OAuth 2.0 Device Authorization Grant (RFC 8628). Generated server handles device code flow with user instructions and token polling |
#### OAuth Flow Object
| Field | Support | Behavior |
| ------------------------ | --------------------- | ---------------------------------------------------------------------------------- |
| `deviceAuthorizationUrl` | | Required for `deviceAuthorization` flow. Used as the device authorization endpoint |
#### Security Requirement Object
| Feature | Support | Behavior |
| -------------------- | --------------------- | ------------------------------------------------------------------------------------------------ |
| URI-based references | | Cross-document security scheme references via URIs. Planned for multi-file specification support |
### Example Object
| Field | Support | Behavior |
| ----------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------- |
| `value` | | Deprecated in 3.2 in favor of `dataValue`. Still fully functional |
| `dataValue` | | Structured example data. Mutually exclusive with `value` |
| `serializedValue` | | Wire-format string of the example. JSON strings are deserialized and used; non-JSON formats not processed |
### Tag Object
| Field | Support | Behavior |
| --------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parent` | | Resolved to hierarchical paths (e.g., tag `refunds` with `parent: payments` becomes `payments/refunds`). Parent chains of any depth with cycle detection |
| `kind` | | Classification string (e.g., `nav`, `lifecycle`, `badge`). Rendered alongside tags in tool comments as `tag (kind)` |
| `summary` | | Not processed |
### Encoding Object
| Field | Support | Behavior |
| ---------------- | --------------------- | --------------------------------------------- |
| `encoding` | | Nested Encoding Objects for multipart content |
| `prefixEncoding` | | Positional encoding for multipart |
| `itemEncoding` | | Per-item encoding for multipart arrays |
The Encoding Object is not supported. Generated servers send form and multipart bodies using standard encoding — per-property overrides (`contentType`, `headers`, `style`) are rarely needed in practice.
Generated server doesn't match this reference? Let us know — we'll fix it.
# Troubleshooting
Source: https://docs.mcpblacksmith.com/reference/troubleshooting
Common issues and how to resolve them.
## Generation issues
### "Specification validation failed"
Your OpenAPI specification has structural issues. Run the Validation check in the dashboard to see specific errors. Common causes:
* Missing `paths` or `info` fields
* Broken `$ref` references pointing to non-existent schemas
* Invalid OpenAPI version identifier
### Generation succeeds but some operations are missing
Operations may be skipped if they:
* Have no defined HTTP method
* Have duplicate operation IDs (the second is renamed with a `_2` suffix)
* Reference undefined schemas that can't be resolved
Check the generation console output for warnings.
## Runtime issues
### "ModuleNotFoundError"
Dependencies aren't installed. Run:
```bash theme={null}
pip install -r requirements.txt
```
If using a virtual environment, make sure it's activated.
### "Connection refused" or timeout errors
The target API is unreachable. Check:
* `BASE_URL` in `.env` is correct
* Your network can reach the API (try `curl` or a browser)
* The API isn't rate-limiting you (check for HTTP 429 responses in logs)
### Authentication errors (401 / 403)
The most common cause is missing or incorrect credentials in your `.env` file. The generated server reads credentials from environment variables — if they're empty or wrong, requests will be rejected by the target API.
* Open the `.env` file and verify all credential fields are filled in with valid values
* Make sure the variable names match what the generated code expects (they're pre-configured — just fill in the values)
* For API Key or Bearer authentication, confirm the key/token is active and not expired
* See [Authentication](/server/authentication) for `.env` examples for each authentication type
**For OAuth2 / OIDC specifically:**
* Ensure `OAUTH2_CLIENT_ID` and `OAUTH2_CLIENT_SECRET` are correct and belong to an active OAuth application
* Verify the API is enabled in your provider's developer console (e.g., Google Cloud Console, Azure Portal)
* Select valid scopes for your use case and provide them in `.env` as a comma-separated list (e.g., `OAUTH2_SCOPES=read,write`)
* Delete `oauth2_tokens.json` to force re-authorization if tokens become invalid
**OAuth2 callback port (authorization code and implicit flows):**
The server starts a temporary local HTTP server to receive the OAuth callback during authorization. This requires the callback port to be free and the redirect URI to match between your server and OAuth provider.
1. **Check the port is free** — the default callback port is `8080` (configured via `OAUTH2_CALLBACK_PORT` in `.env`). If another process is using this port, the authorization flow fails silently and requests go out unauthenticated. Check with:
```bash theme={null}
# Linux / macOS
lsof -i :8080
# or
ss -tlnp | grep 8080
```
If the port is occupied, either stop the conflicting process or change `OAUTH2_CALLBACK_PORT` in `.env` to a free port.
2. **Redirect URI must match** — your OAuth provider's allowed redirect URIs must include `http://localhost:/callback` where `` matches `OAUTH2_CALLBACK_PORT` in `.env`. For example, with the default port:
```
http://localhost:8080/callback
```
Add this to your OAuth application's redirect URIs in the provider's developer console (e.g., Google Cloud Console → Credentials → OAuth 2.0 Client → Authorized redirect URIs).
### "Rate limit exceeded"
This can come from two sources:
**Local rate limiter** — The generated server includes an optional local rate limiter that caps outgoing requests per second. This is disabled by default. If you enabled it during generation (Generation tab → Config → Advanced settings → Security: Enable Rate Limiting), you can adjust the limit in `.env` or disable it at runtime:
```bash .env theme={null}
RATE_LIMIT_REQUESTS_PER_SECOND=20 # adjust the limit (default: 10)
```
To disable rate limiting at runtime, start the server with the `--rate-limiting disabled` flag:
```bash theme={null}
python server.py --rate-limiting disabled
```
**Target API rate limiting** — The upstream API is rejecting your requests (HTTP 429). Check the API's documentation for rate limits and reduce your request frequency.
### Circuit breaker is open
The target API has been failing consistently. The circuit breaker blocks requests to prevent cascading failures. Wait for the timeout period (default 60 seconds) or restart the server to reset the circuit breaker state.
## MCP client issues
### Tools don't appear in your MCP client
See [Connecting to AI Agents — Troubleshooting](/deployment/connecting-agents#troubleshooting).
### Tools appear but return errors
Run `python server.py` directly in a terminal to see detailed error output. Common causes:
* Missing or incorrect credentials in `.env`
* API returning unexpected response format
* Network issues between your machine and the API
## Still stuck?
[Contact us](https://mcpblacksmith.com/contact) with your error output and we'll help debug.
# Authentication
Source: https://docs.mcpblacksmith.com/server/authentication
How generated MCP servers handle authentication — OAuth2, API keys, JWT, Bearer tokens, and more.
## Overview
MCP Blacksmith auto-detects authentication requirements from your OpenAPI specification's [`securitySchemes`](/reference/oas-3-0#security-scheme-object) and generates the appropriate handlers. You only need to provide credentials in the `.env` file.
Each operation is mapped to its required authentication scheme via the [Security Requirement](/reference/oas-3-0#security-requirement) object. The server automatically injects the correct credentials into every request.
## Supported authentication types
### API Key
Used when the API requires a key passed as a header, query parameter, or cookie.
```bash .env theme={null}
API_KEY=your-api-key-here
```
The generated code reads the key location (header, query, or cookie) and parameter name from the specification. For example, if the specification defines an API key in the `X-API-Key` header, the server automatically sends:
```
X-API-Key: your-api-key-here
```
### Bearer Token
Used for APIs that accept a static token in the `Authorization` header.
```bash .env theme={null}
BEARER_TOKEN=your-bearer-token
```
Sends `Authorization: Bearer your-bearer-token` with each request.
### HTTP Basic
Used for username/password authentication.
```bash .env theme={null}
BASIC_AUTH_USERNAME=your-username
BASIC_AUTH_PASSWORD=your-password
```
Credentials are Base64-encoded and sent as `Authorization: Basic `.
### OAuth 2.0
Used for APIs requiring [OAuth2 flows](/reference/oas-3-0#oauth2-flows) (Authorization Code, Client Credentials, Password).
```bash .env theme={null}
OAUTH2_CLIENT_ID=your-client-id
OAUTH2_CLIENT_SECRET=your-client-secret
OAUTH2_SCOPES=scope1,scope2
```
**How it works:**
1. On first run, the server opens your browser for authorization
2. You authorize the application on the API provider's consent page
3. The server receives the authorization code via a local callback server
4. Tokens are exchanged and saved to `oauth2_tokens.json`
5. On subsequent runs, saved tokens are reused
6. Expired tokens are automatically refreshed
Delete `oauth2_tokens.json` to force re-authorization if your tokens become invalid.
The callback server runs on port `8080` by default. Change `OAUTH2_CALLBACK_PORT` in `.env` if needed — make sure the matching redirect URI (`http://localhost:/callback`) is registered in your OAuth provider's developer console.
#### Flow selection
When an OpenAPI specification defines multiple OAuth2 flows on the same security scheme, the generator picks a single flow based on security strength:
1. **Authorization Code** — most secure; requires user authorization via browser redirect
2. **Client Credentials** — server-to-server; no user interaction
3. **Device Authorization** — for headless/CLI devices (OAS 3.2+)
4. **Password** — legacy; sends credentials directly
5. **Implicit** — deprecated in OAuth 2.1; least secure
The generated `.env` and authentication class reflect only the selected flow. For example, a specification offering both `authorizationCode` and `implicit` flows will generate an Authorization Code handler — the implicit flow is discarded.
If you need a different flow than the one selected, you can override the authentication configuration in the generation dashboard before generating your server.
### OpenID Connect (OIDC)
Extends OAuth2 with ID token validation and automatic discovery.
```bash .env theme={null}
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
OIDC_SCOPES=openid,profile,email
```
Works the same as OAuth2 with additional:
* Automatic discovery from the OIDC Discovery endpoint
* ID token validation
* Tokens saved to `oidc_tokens.json`
### JWT Bearer
Used for APIs that require dynamically signed JSON Web Tokens — such as GitHub Apps, Google service accounts, and Apple APIs. Detected when the OpenAPI spec declares `bearerFormat: JWT` on an HTTP Bearer scheme.
```bash .env theme={null}
# Required
JWT_PRIVATE_KEY=mcp-blacksmith-test.pem
JWT_ISSUER_ID=123456
# Optional (leave empty if not needed)
JWT_ALGORITHM=RS256
JWT_EXPIRY=600
JWT_AUDIENCE=
JWT_KEY_ID=
JWT_TOKEN_URL=
JWT_SCOPES=
```
`JWT_PRIVATE_KEY` accepts either a path to a `.pem` file (relative to the server directory or absolute) or an inline PEM key with newlines encoded as `\n`.
**How it works:**
1. The server reads the private key and issuer ID from `.env`
2. Before each API request, a short-lived JWT is signed locally (RS256 by default)
3. The JWT is sent as `Authorization: Bearer `
4. Tokens are cached in memory and regenerated when near expiry (30-second buffer)
No browser flow or token file is needed — the private key acts as the permanent credential.
#### Token exchange variant
Some APIs (e.g. Google) require an additional step: the signed JWT is exchanged at a token endpoint for an access token. Set `JWT_TOKEN_URL` to enable this:
```bash .env theme={null}
JWT_TOKEN_URL=https://oauth2.googleapis.com/token
JWT_SCOPES=https://www.googleapis.com/auth/cloud-platform
```
When `JWT_TOKEN_URL` is set, the server POSTs the signed JWT to that endpoint and uses the returned access token instead.
### Mutual TLS (mTLS)
Used for APIs requiring client certificate authentication. See [mutualTLS in OAS 3.1](/reference/oas-3-1#security-scheme-object) for specification details.
```bash .env theme={null}
MTLS_CERT_PATH=/path/to/client-cert.pem
MTLS_KEY_PATH=/path/to/client-key.pem
MTLS_CA_CERT_PATH=/path/to/ca-cert.pem
```
The HTTP client is configured with the client certificate for mutual authentication. If paths are not set, mTLS is disabled and a warning is logged.
## Per-operation authentication
Not every operation uses the same authentication. The generated server maps each operation to its required schemes:
```python theme={null}
# Generated in _auth.py
OPERATION_AUTH_MAP = {
"list_users": [["oauth2"], ["api_key"]], # Use oauth2 OR api_key
"create_user": [["oauth2"]], # OAuth2 only
"get_public_info": [], # No authentication required
}
```
* **Outer list** = OR — any one of these options works
* **Inner list** = AND — all schemes in this group are required together
The server automatically selects the first available authentication option based on which credentials you've configured.
## Security best practices
Never commit your `.env` file to version control. Add it to `.gitignore`.
* Store credentials in the `.env` file, not in code
* Use the minimum required scopes for OAuth2/OIDC
* Replace API keys and tokens periodically
* For multi-tenant deployments, add proper isolation and credentials management — or let us handle it with MCP Armory
# Security Features
Source: https://docs.mcpblacksmith.com/server/security
Circuit breakers, rate limiting, retries, timeouts, and validation — built into every generated server.
## Overview
Every generated MCP server includes multiple layers of resilience and security, protecting both the AI agent and the target API. All features are configurable via the `.env` file.
## Retry with exponential backoff
Failed requests are automatically retried with increasing delays:
| Attempt | Delay |
| ------- | ----------- |
| 1st | Immediate |
| 2nd | \~2 seconds |
| 3rd | \~4 seconds |
Retries are triggered on transient errors: HTTP 429 (rate limited), 500, 502, 503, and 504.
```bash .env theme={null}
MAX_RETRIES=3
RETRY_BACKOFF_FACTOR=2.0
```
Set `MAX_RETRIES=0` to disable retries.
## Circuit breaker
Prevents cascading failures when the target API is down. Instead of repeatedly hitting a failing endpoint, the circuit breaker temporarily blocks requests and returns an error immediately.
**States:**
* **Closed** (normal) — Requests pass through. Failures are counted.
* **Open** (blocking) — Requests are blocked immediately. Entered after consecutive failures exceed the threshold.
* **Half-open** (testing) — After a timeout, a limited number of requests are allowed through to test recovery.
```bash .env theme={null}
CIRCUIT_BREAKER_FAILURE_THRESHOLD=5
CIRCUIT_BREAKER_TIMEOUT_SECONDS=60
```
## Rate limiting
Prevents your server from overwhelming the target API.
Uses a **token bucket** algorithm — requests consume tokens, tokens regenerate at a configured rate. When the bucket is empty, requests are delayed.
```bash .env theme={null}
RATE_LIMIT_REQUESTS_PER_SECOND=10
```
## Timeouts
Multi-layer timeout configuration prevents hanging requests:
```bash .env theme={null}
# Individual HTTP phases
HTTPX_CONNECT_TIMEOUT=10.0 # Connection establishment
HTTPX_READ_TIMEOUT=60.0 # Waiting for response
HTTPX_WRITE_TIMEOUT=30.0 # Sending request body
HTTPX_POOL_TIMEOUT=5.0 # Acquiring connection from pool
# Overall tool execution
TOOL_EXECUTION_TIMEOUT=90.0 # Total time for one tool call
```
## Connection pool
HTTP connections are reused for efficiency:
```bash .env theme={null}
CONNECTION_POOL_SIZE=100
MAX_KEEPALIVE_CONNECTIONS=20
```
Cookies are disabled across requests for safety in multi-tenant scenarios.
## Input validation
All request parameters are validated using Pydantic models before any HTTP request is made:
* **Type checking** — Correct types enforced (string, integer, boolean, etc.)
* **Required fields** — Missing required parameters are rejected with clear error messages
* **Format validation** — Dates, emails, UUIDs, IP addresses validated against [50+ formats](/reference/oas-3-0#extended-formats) (full OAS Format Registry coverage)
* **Strict mode** — Unknown/extra fields are rejected
## Response validation
Optionally validate API responses against the OpenAPI [response schema](/reference/oas-3-0#responses):
```bash .env theme={null}
RESPONSE_VALIDATION_MODE=warn # off, warn, or strict
```
| Mode | Behavior |
| -------- | ------------------------------------------------------------------------ |
| `off` | No response validation (fastest) |
| `warn` | Validate and log warnings, but return data anyway (default) |
| `strict` | Block invalid responses — returns error if response doesn't match schema |
## Response sanitization
Optionally redact sensitive fields from API responses before returning them to the AI agent:
```bash .env theme={null}
SANITIZATION_LEVEL=DISABLED # DISABLED, LOW, MEDIUM, or HIGH
```
| Level | Fields redacted |
| ------ | ------------------------------------------------- |
| LOW | `password`, `token`, `secret`, `private_key` |
| MEDIUM | + `access_token`, `credentials`, `authorization` |
| HIGH | + `session_id`, `cookie`, `api_key`, `ip_address` |
# Server Structure
Source: https://docs.mcpblacksmith.com/server/structure
What's inside a generated MCP server — file layout, purpose of each file, and how they work together.
## File layout
A generated MCP server contains the following files:
```
my-api-server/
├── server.py # Main MCP server — tool definitions and request handling
├── _models.py # Pydantic models for parameter and response validation
├── _validators.py # 50+ format validators (full OAS Format Registry coverage)
├── _auth.py # Authentication handlers (if API requires authentication)
├── .env # Credentials and runtime configuration
├── requirements.txt # Python dependencies
├── LICENSE # MIT license for generated code
├── Dockerfile # Production Docker build
├── .mcp.json # MCP client configuration template
└── README.md # Setup and usage guide
```
`_auth.py` is only generated if the OpenAPI specification defines [security schemes](/reference/oas-3-0#security-scheme-object). APIs without authentication skip this file entirely.
## Core files
### `server.py`
The main entry point. Contains:
* **Tool definitions** — One `@mcp.tool()` async function per API operation
* **HTTP client setup** — Connection pooling, timeouts, mTLS support
* **Resilience logic** — Retry with exponential backoff, circuit breaker, rate limiting
* **Authentication injection** — Selects correct authentication per operation
* **Response handling** — JSON parsing, error formatting, optional validation
* **Transport selection** — stdio, SSE, or streamable-http (selected at runtime)
Each tool function follows this flow:
```
Validate parameters → Inject authentication → Make HTTP request → Validate response → Return data
```
### `_models.py`
Pydantic models for every operation's parameters and (optionally) responses. Models are generated from the OpenAPI [schema definitions](/reference/oas-3-0#schema-object) and enforce:
* **Type safety** — Correct Python types for each parameter
* **Required fields** — Missing required parameters are rejected
* **Format validation** — Dates, emails, UUIDs, etc. are validated against their declared formats
* **Strict mode** — Unknown fields in requests are rejected (prevents malformed calls)
### `_validators.py`
Shared validation infrastructure with [50+ format validators](/reference/oas-3-0#extended-formats) covering all 49 [OAS Format Registry](https://spec.openapis.org/registry/format/) formats plus custom extensions:
| Category | Formats |
| ----------------- | ------------------------------------------------------------------------------------------------- |
| Integer | `int8`, `int16`, `int32`, `int64`, `uint8`, `uint16`, `uint32`, `uint64`, `double-int` |
| Number | `float`, `double`, `decimal`, `decimal128` |
| Date/time | `date-time`, `date`, `time`, `duration`, `date-time-local`, `time-local`, `http-date`, `unixtime` |
| Identifiers | `uuid`, `uri`, `iri`, `json-pointer`, `relative-json-pointer`, `media-range` |
| Network | `ipv4`, `ipv6`, `hostname`, `idn-hostname`, `email`, `idn-email` |
| Text | `commonmark`, `html`, `char`, `regex`, `password` |
| Structured Fields | `sf-integer`, `sf-decimal`, `sf-string`, `sf-token`, `sf-boolean`, `sf-binary` |
| Encoding | `byte`, `binary`, `base64url` |
Also provides base model classes (`StrictModel`, `PermissiveModel`) that all generated models inherit from. See [Strict/Permissive models](/reference/oas-3-0#additional-generator-capabilities) for details.
### `_auth.py`
Authentication handler classes, one per security scheme found in your specification. See [Authentication](/server/authentication) for details on each type.
Includes `OPERATION_AUTH_MAP` — a mapping from each operation ID to its required authentication schemes, supporting both OR (use any available) and AND (use all together) logic.
## Configuration files
### `.env`
Runtime configuration split into sections:
```bash .env theme={null}
# --- Authentication ---
API_KEY=your-api-key
# BEARER_TOKEN=your-token
# OAUTH2_CLIENT_ID=your-client-id
# OAUTH2_CLIENT_SECRET=your-client-secret
# --- API Configuration ---
BASE_URL=https://api.example.com
# --- Timeouts (seconds) ---
HTTPX_CONNECT_TIMEOUT=10.0
HTTPX_READ_TIMEOUT=60.0
HTTPX_WRITE_TIMEOUT=30.0
HTTPX_POOL_TIMEOUT=5.0
TOOL_EXECUTION_TIMEOUT=90.0
# --- Connection Pool ---
CONNECTION_POOL_SIZE=100
MAX_KEEPALIVE_CONNECTIONS=20
# --- Resilience ---
MAX_RETRIES=3
RETRY_BACKOFF_FACTOR=2.0
CIRCUIT_BREAKER_FAILURE_THRESHOLD=5
CIRCUIT_BREAKER_TIMEOUT_SECONDS=60
RATE_LIMIT_REQUESTS_PER_SECOND=10
# --- Validation ---
RESPONSE_VALIDATION_MODE=warn
# --- Logging ---
LOG_LEVEL=INFO
LOG_FORMAT=simple
```
The `.env` file contains sensitive credentials. Never commit it to version control.
### `requirements.txt`
Auto-detected dependencies based on what the generated code imports:
```txt requirements.txt theme={null}
fastmcp>=2.12.0,<3.0.0
httpx>=0.27.0,<1.0.0
pydantic>=2.0.0,<3.0.0
python-dotenv>=1.0.0,<2.0.0
```
Additional packages are included when needed:
* `authlib` and `PyJWT` — if OAuth2, OIDC, or JWT authentication is used
* `requests` — if OAuth2 browser-based flow is used
### `.mcp.json`
Pre-configured MCP client configuration template:
```json .mcp.json theme={null}
{
"mcpServers": {
"my-api": {
"command": "python",
"args": ["server.py"]
}
}
}
```
Copy this into your MCP client's configuration file, adjusting the path to `server.py`.
## Next steps
Configure credentials for each authentication type.
Circuit breakers, rate limiting, retries.