Generating Production-Ready MCP Servers from OpenAPI Specifications

speakeasy · Tech · 2025 · source Agentic: yes · promotional bias: med · source-backed · extracted with prompt 0.5.6 (schema v2)

Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.

Problem

Domain: API-to-agent tool generation

Speakeasy needed to generate production-ready MCP servers from OpenAPI documents so AI agents could use existing APIs, while avoiding tool overload, bad tool descriptions, fragile complex payloads, unsafe capability exposure, and manual customizations that disappear when generated code is regenerated.

Constraints:

Architecture

Speakeasy extends its OpenAPI generator to produce MCP servers while moving agent-specific customization into three durable layers: the OpenAPI document where appropriate, generator behavior for common transformations, and custom function files or overlays for endpoint-specific control. The generated MCP server exposes pruned, well-described tools, transforms complex payloads into LLM-friendly formats, and enforces scopes server-side so agents receive a focused, safer capability surface.

Diagram confidence: explicit (topology described by the source).

flowchart LR
  openapi_document["OpenAPI document"] --> speakeasy_mcp_generator["Speakeasy MCP generator"]
  openapi_document --> overlay_document["Overlay document"]
  overlay_document --> speakeasy_mcp_generator
  x_speakeasy_mcp_annotations["x-speakeasy-mcp annotations"] --> speakeasy_mcp_generator
  speakeasy_mcp_generator --> generated_mcp_server["Generated MCP server"]
  speakeasy_mcp_generator --> custom_function_file["Custom function file"]
  custom_function_file --> generated_mcp_server
  response_transformation_layer["Response transformation layer"] --> generated_mcp_server
  response_transformation_layer --> ai_agent["AI agent"]
  scope_configuration["Scope configuration"] --> generated_mcp_server
  generated_mcp_server --> mcp_client["MCP client"]
  generated_mcp_server --> backend_api["Backend API"]
  mcp_client --> ai_agent
  ai_agent --> mcp_client
Drag to pan · scroll or use +/− to zoom · reconstructed from the source's described component topology

Components

Component Role Interacts with
OpenAPI document Primary API specification describing endpoints, fields, schemas, responses, and errors. Speakeasy MCP generator, Overlay document
Overlay document Optional companion document that modifies OpenAPI behavior without editing the original specification. Speakeasy MCP generator
x-speakeasy-mcp annotations OpenAPI extensions controlling disabled operations, tool names, descriptions, and scopes for MCP generation. Speakeasy MCP generator
Speakeasy MCP generator Generation engine that converts OpenAPI input and MCP-specific customizations into a server artifact. Generated MCP server, Custom function file
Custom function file Adjacent customization layer for controlling specific generated tool behavior without editing generated server code. Generated MCP server
Response transformation layer Generated or hook-based logic that converts streaming, binary, nested, or noisy API responses into simpler client-facing forms. Generated MCP server, AI agent
Scope configuration Server-side access-control metadata that limits exposed tools by read, write, product, or other domains. Generated MCP server
Generated MCP server Runtime server exposing selected API operations as MCP tools with schemas, descriptions, transformations, and scopes. MCP client, Backend API
MCP client Client environment such as Claude Desktop or a custom client that connects the agent to the MCP server. AI agent
AI agent LLM-driven user of the MCP tools that chooses operations based on tool names, schemas, and descriptions. MCP client, Generated MCP server
Backend API Existing business API whose endpoints become controlled MCP tools. Generated MCP server

Data flow

An OpenAPI document enters the Speakeasy generator, optionally augmented with x-speakeasy-mcp annotations or overlays. The generator prunes disabled endpoints, emits MCP tool names, schemas, descriptions, and scope metadata, and handles common data-shape conversions such as streaming and binary responses. Custom function files or SDK hooks refine behavior for endpoint-specific cases. The resulting MCP server exposes a controlled tool set to MCP clients and AI agents, which then call the underlying API through the generated server rather than directly through raw OpenAPI operations.

3 supporting quotes
“A generator is a tool that takes an OpenAPI document as input and produces an artifact.”article, stated
“our approach creates a workflow that allows us to elegantly control the MCP server while enabling regeneration at any time without losing customizations.”article, stated
“A tool is a function that an agent can call. An MCP Tool consists of the following components:”article, stated

Why this architecture

Speakeasy keeps OpenAPI as the single source of truth while adding MCP-specific controls outside the generated server because generated artifacts must be safe to regenerate. Tool pruning, concise agent-facing descriptions, data transformations, and server-side scopes reduce the agent's decision space and risk surface before the LLM chooses a tool.

3 supporting quotes
“Shifting the optimization layer helps us avoid manual changes directly on the generated MCP server that would need to be repeated after every regeneration.”article, stated
“The OpenAPI document: This serves as your single source of truth”article, stated
“This way, the server configuration provides built-in protection, regardless of which client the user is on.”article, stated

Models used: LLM agents · smaller models with shorter context windows

Scale

Alternatives considered (roads not taken)

Generate one MCP tool for every OpenAPI operation

Rejected because: The resulting tool explosion overwhelms the LLM's context window and makes wrong tool selection more likely.

“When faced with 200 tools, the model becomes confused as its context window is overwhelmed.”article, stated

Manually edit the generated MCP server

Rejected because: Manual generated-server changes would have to be repeated after every regeneration, so Speakeasy moves customization to OpenAPI, generator, overlays, and custom files.

“avoid manual changes directly on the generated MCP server that would need to be repeated after every regeneration.”article, stated

Use the same verbose OpenAPI descriptions for humans and LLM tool selection

Rejected because: Verbose descriptions consume tokens and repeated details add noise when all tool descriptions enter the context window together.

“more words mean more characters and therefore more tokens consumed in the LLM’s context window.”article, stated
“LLMs prefer concise and direct descriptions.”article, stated

Rely on client-side toggles to hide risky or irrelevant tools

Rejected because: Client-specific toggling becomes unscalable across many tools, clients, and environments, so Speakeasy supports server-side scopes.

“Claude Desktop allows this, but if the server exposes over 200 tools, manually toggling them off one by one isn’t much fun.”article, stated
“things become complicated when you have multiple tools or descriptive actions. Managing this complexity across multiple clients or environments quickly becomes unscalable.”article, stated

Pass complex API responses directly to the LLM

Rejected because: Agents struggle with streaming, binary, metadata-heavy, and deeply nested response formats, so Speakeasy transforms data first.

“Agents generally expect simple JSON responses, but APIs often return complex and varied payloads.”article, stated
“Speakeasy handles complex formats by automatically transforming data before sending it to the MCP server.”article, stated

Patterns

tool-use-orchestration (agent tool surface)

Speakeasy turns OpenAPI operations into MCP tools for agents, then prunes, scopes, and describes those tools so models can choose useful API capabilities reliably.

“MCP is a protocol for AI agents to interact with your API.”article, stated
“A tool is a function that an agent can call.”article, stated

structured-output-contract (schema-driven tool generation)

OpenAPI and MCP both use schemas to define request/response and tool contracts, letting generated MCP tools expose names, schemas, and descriptions to agents.

“An OpenAPI document is a YAML or JSON file that describes your API, from endpoints to fields to schemas for request payloads, successful responses, and errors.”article, stated
“An MCP Tool consists of the following components:”article, stated

safety-policy-enforcement (server-side access control)

Speakeasy uses endpoint scopes such as read, write, or product so generated MCP servers expose only the permitted operations regardless of client UI behavior.

“By using scopes, you can restrict tool use on the server rather than the client”article, stated
“With scopes in place, you can start the server with a read scope and only expose the corresponding operations.”article, stated

guardrails-io-filtering (tool pruning and response shaping)

The generator can disable irrelevant endpoints and transform complex API payloads before they reach the agent, reducing unsafe or confusing tool exposure.

“When set to true, a tool is not generated for this operation.”article, stated
“if Speakeasy detects an image or audio file, it encodes it in Base64 before passing it to the LLM.”article, stated

Tradeoffs

Keep OpenAPI as the source of truth while adding MCP-specific customization layers.

Chose OpenAPI plus generator behavior, extensions, overlays, and custom function files over Editing generated MCP server code directly.

Rationale: This preserves regeneration while letting teams tailor tools for agents without compromising SDK and documentation generation.

“The OpenAPI document: This serves as your single source of truth”article, stated
“enabling regeneration at any time without losing customizations.”article, stated

Prune tool surfaces before generation.

Chose Disable non-useful or out-of-scope endpoints in OpenAPI/MCP metadata over Letting the agent see every operation.

Rationale: Pruning reduces context-window load and makes tool choice more reliable for the model.

“When faced with 200 tools, the model becomes confused as its context window is overwhelmed.”article, stated
“keeping only low-level operations that represent genuinely useful, distinct capabilities that an LLM might perform.”article, stated

Use server-side scopes for access control.

Chose Scope-based server configuration over Manual per-client tool toggling.

Rationale: Server scopes scale across clients and environments and avoid relying on a UI setting to hide dangerous operations.

“By using scopes, you can restrict tool use on the server rather than the client”article, stated
“This way, the server configuration provides built-in protection, regardless of which client the user is on.”article, stated

Transform complex responses before they reach the agent.

Chose Generator and hook-based response simplification over Sending raw streams, binary files, envelopes, or nested JSON to the LLM.

Rationale: Agents expect simple JSON-like outputs, so generated transforms and hooks make tool outputs easier for LLMs to process reliably.

“Agents generally expect simple JSON responses, but APIs often return complex and varied payloads.”article, stated
“extract information from a CSV file returned in a response and convert it to JSON.”article, stated

Use overlays when MCP-specific descriptions would pollute the base OpenAPI document.

Chose Separate overlay documents over Putting every agent-facing term directly into the source OpenAPI spec.

Rationale: Overlays allow MCP-specific edits while keeping the original API spec clean for documentation and SDK use.

“if you don’t want to pollute your OpenAPI document with extensions or non-native terminologies, you can use an overlay”article, stated
“a separate document that modifies the OpenAPI document without directly editing the original.”article, stated

Gotchas (what bit them)

Tool explosion overwhelms model context and decision-making.

Root cause: A one-operation-to-one-tool mapping can expose hundreds of tools, especially for large APIs.

Resolution: Prune the OpenAPI document, disable non-useful endpoints, and keep only genuinely useful capabilities for the MCP use case.

“Generating an MCP server from this document will easily create around 200 tools.”article, stated
“Exclude non-useful endpoints (like health/ and inspect/) and any that don’t address the problem you’re solving by using an MCP server.”article, stated

Descriptions optimized for API docs can harm LLM tool selection.

Root cause: Long repeated descriptions consume tokens, while short vague descriptions fail to distinguish similar endpoints.

Resolution: Use clear, concise MCP-specific descriptions through x-speakeasy-mcp annotations or overlays when the human-facing OpenAPI docs cannot be changed.

3 supporting quotes
“These multi-paragraph descriptions often repeat the same details and add noise.”article, stated
“If several endpoints have similar names but do different things, the LLM won’t know which one to use.”article, stated
“Speakeasy supports the custom x-speakeasy-mcp extension for describing endpoints to LLMs.”article, stated

Complex API payloads are brittle model inputs.

Root cause: APIs may return streams, binary media, metadata, or nested envelopes that agents are not good at processing.

Resolution: The generator and SDK hooks transform responses, such as buffering streams, Base64-encoding media, or converting CSV data to JSON.

“LLMs struggle with complex JSON formats, it’s common for them to have difficulty processing such responses.”article, stated
“For streaming data, Speakeasy generates code that first streams the entire response and only passes it to the client once the stream completes.”article, stated

Exposing all API operations creates safety and privacy risk.

Root cause: An agent connected to an MCP server may be one tool call away from leaking sensitive data or modifying accounts unintentionally.

Resolution: Define scopes before generation so the server exposes only the operations allowed for a given runtime context.

“you’re one tool call away from leaking sensitive identity information or modifying accounts in unintended ways”article, stated
“you can restrict tool use on the server rather than the client, and configure that behavior directly”article, stated

Manual generated-code edits do not survive regeneration.

Root cause: MCP servers are generated artifacts, so direct edits become repeat work whenever the OpenAPI document or generator changes.

Resolution: Speakeasy moves customizations into the OpenAPI document, the generator, custom function files, and overlays.

“avoid manual changes directly on the generated MCP server that would need to be repeated after every regeneration.”article, stated
“a separate document that modifies the OpenAPI document without directly editing the original.”article, stated

Evaluation

The article does not describe a formal benchmark harness. Speakeasy bases the guidance on lessons from generating 50-plus production MCP servers and evaluates failure modes by whether agents can choose the right tools, stay within context, process responses, preserve customizations across regeneration, and avoid unsafe exposure.

Metrics: number of production MCP servers generated · tool count per API · context-window pressure · wrong-tool selection risk · hallucinated response risk · regeneration safety of customizations · scope-controlled tool exposure

3 supporting quotes
“After generating more than 50 production MCP servers, we’ve seen what breaks, what matters, and what to avoid.”article, stated
“As a result, the LLM chooses the wrong tool or hallucinates a response. However, short and vague descriptions also create issues.”article, stated
“our approach creates a workflow that allows us to elegantly control the MCP server while enabling regeneration at any time without losing customizations.”article, stated

Outcomes

The production lessons come from more than 50 generated MCP servers. The article repeatedly frames scale around large APIs: 200 endpoints mapping to roughly 200 tools, APIs with more than 500 operations, multiple MCP servers, and smaller models with shorter context windows.

3 supporting quotes
“So far, we’ve used it to generate over 50 MCP servers for customers”article, stated
“Our generator looks for a custom disabled key in the OpenAPI document (defaulting to false).”article, stated
“With scopes in place, you can start the server with a read scope and only expose the corresponding operations.”article, stated