---
title: "OpenAPI to MCP server generator or OpenAPI tools for AI agents (2026): FastMCP from_openapi, Stainless, Speakeasy, AgentCore Gateway, LangChain OpenAPI toolkit — Cadenya"
url: "https://cadenya.com/other-content/openapi-specs-as-agent-tools-and-mcp"
description: "How to generate tools from an OpenAPI spec in 2026: FastMCP from_openapi, Stainless MCP server generation with code mode, Speakeasy Gram, AWS AgentCore Gateway OpenAPI targets, and the LangChain OpenAPI toolkit, compared on sync, context window size, MCP OAuth and per-user auth for remote MCP servers, and MCP transport, plus a hosted option."
---

You can turn an OpenAPI spec into AI agent tools in two ways: generate an MCP server from the spec, or load the spec straight into your agent as tools. FastMCP `from_openapi`, Stainless, Speakeasy Gram, and AWS AgentCore Gateway take the first path, and the LangChain OpenAPI toolkit takes the second.

So pick FastMCP when you write Python and want an open-source MCP server you run yourself. Pick Stainless when you already generate a TypeScript SDK with it. Pick Speakeasy or AgentCore Gateway when you want someone else to host the MCP server, and you’re fine with an enterprise contract or an AWS account. And if you’d rather run no generator and no server at all, Cadenya reads your OpenAPI document into a tool set inside a hosted agent loop, and a coding agent can set it up with no account, in a temporary workspace you claim later. [What it offers](#what-does-cadenya-offer-that-openapi-to-mcp-generators-dont) is at the end.

Every price and limit below comes from each vendor’s own pages, checked on October 8, 2026.

## OpenAPI to MCP server generators side by side

|  | FastMCP from_openapi | Stainless MCP | Speakeasy Gram | AgentCore Gateway | LangChain OpenAPI toolkit | Cadenya |
| --- | --- | --- | --- | --- | --- | --- |
| What it is | Python library that builds an MCP server from a spec | MCP server generated as a subpackage of your TypeScript SDK | Hosted MCP servers built from an OpenAPI document | Managed AWS gateway with OpenAPI, Smithy, and Lambda targets | JavaScript toolkit that hands the spec to the agent | Hosted agent loop that reads the spec into a tool set |
| Tools from the spec | One per endpoint by default | Two: code execution and docs search | One per operation, then you curate | One per operationId | Three: requests_get, requests_post, json_explorer | Every operation, with filters and progressive discovery |
| Where it runs | Your process: stdio by default, or Streamable HTTP | Your machine over stdio, or your Docker image over HTTP | Speakeasy’s platform, at a hosted URL | AWS, as a managed endpoint | Inside your agent code | Cadenya, with nothing to deploy |
| When the spec changes | You reload the spec you pass at startup | New version with each SDK release | ”Only reaches the server through a new deployment” | Spec is inline or in S3 on the target | You reload the spec you pass in | Checked each hour when the source is a URL |
| Calling the API as a user | Headers on the HTTP client you pass in | Same auth as your SDK, or OAuth | OAuth, plus secret environments shared across servers | Outbound OAuth (2LO and 3LO), API key, or IAM | A headers object at construction | {{ secrets.MY_SECRET }} in a tool header, set per objective or widget session |
| Price | Free, Apache-2.0 | Free plan: 5 generators, 25 endpoints | Enterprise, “Tailored” | $0.005 per 1,000 invocations, plus search and indexing | Free, MIT (@langchain/classic 1.0.52) | Free for 1,000 loops a month, $49 a month for 50,000, then $0.0015 a loop |
| Version and status | 4.0.11, October 4, 2026 (Python 3.10+) | Same version as your TypeScript SDK | Supports MCP 2026-07-28 | Reads OpenAPI 3.0 and 3.1 | Moved to @langchain/classic | SDKs at 1.9.0. Reads OpenAPI 3.0 or later |

## Generate tools from an OpenAPI spec: what each option does

FastMCP converts “**every endpoint** in your OpenAPI specification into an MCP **Tool**.” You pass the parsed spec and an HTTP client, and it builds the server:

```
import httpx2
from fastmcp import FastMCP

# Create an HTTP client for your API
client = httpx2.AsyncClient(base_url="https://api.example.com")

# Load your OpenAPI spec
openapi_spec = httpx2.get("https://api.example.com/openapi.json").json()

# Create the MCP server
mcp = FastMCP.from_openapi(
    openapi_spec=openapi_spec,
    client=client,
    name="My API Server"
)

if __name__ == "__main__":
    mcp.run()
```

Route maps change which endpoints become tools, and the `EXCLUDE` type drops a route entirely. FastMCP’s own docs are blunt about the tradeoff: “LLMs achieve **significantly better performance** with well-designed and curated MCP servers than with auto-converted OpenAPI servers.”

Stainless does the opposite of one tool per endpoint. Its generated server has “two tools: a code execution tool and a docs search tool.” The model writes TypeScript against your Stainless SDK, and the server runs it “in a Deno subprocess on the same machine as your MCP server.” The server is a subpackage of your TypeScript SDK, so you need a Stainless TypeScript target first.

Speakeasy Gram builds hosted servers. “Uploading an OpenAPI document creates a built server automatically,” and every operation becomes a tool definition you can rename, re-describe, and filter by tag.

AgentCore Gateway uses each `operationId` as the tool name. It reads OpenAPI 3.0 and 3.1, but “Complex schema features like oneOf, anyOf, and allOf are not supported,” and only `application/json` is fully supported.

The LangChain OpenAPI toolkit doesn’t make one tool per operation at all. It gives the agent three generic tools and the spec, and the agent looks up each endpoint with `json_explorer` before it calls `requests_get` or `requests_post`. LangChain’s page warns that this agent “could theoretically send requests with provided credentials or other sensitive data to unverified or potentially malicious URLs.”

## Keeping tools in sync with the OpenAPI spec

**Most generators read your spec once, and a changed API means a rebuild.**

FastMCP builds its tools from the spec you hand it when the server starts. Stainless publishes the MCP server “at the same time as your TypeScript SDK and with the same version,” so a spec change ships with your next SDK release. Speakeasy says it plainly: “There is no background refresh, no time-to-live, and no webhook. A change to an OpenAPI document or a functions manifest only reaches the server through a new deployment.”

Then there’s the client side. Speakeasy notes that “MCP clients cache tool schemas for the life of a session.” The OpenAI Agents SDK offers `cache_tools_list` and says to “Set it to True only if you are confident that the tool definitions do not change frequently.” So a fresh spec can still meet a stale tool list in a client that’s already connected.

## Big APIs and the context window: dynamic tools and tool search

In a generator that makes one tool per operation, a spec with 300 operations makes 300 tools, and each tool’s schema goes into every model call. Speakeasy’s pricing FAQ puts a number on it: “LLM performance starts to drop significantly when an MCP server has 30-40 tools.”

Each option has its own answer:

1.  **Filter before the model sees it.** FastMCP route maps, Speakeasy tag filters, and the OpenAI Agents SDK’s MCP tool filters all cut the list down.
2.  **Search instead of listing.** AgentCore Gateway’s semantic tool selection allows “agents to use thousands of tools while minimizing prompt size.” It bills $0.025 per 1,000 searches and $0.02 per 100 tools indexed a month. OpenAI’s hosted tool search “lets OpenAI Responses models defer large tool surfaces until runtime.”
3.  **Shrink to a few tools.** Stainless code mode exposes two tools. Speakeasy gateway endpoints let agents “discover and call member tools through four tools instead of loading every member’s full catalog.”

Filtering is the cheapest of the three. But it only removes whole tools, and one operation with dozens of optional parameters and a verbose response can still crowd the window on its own.

## MCP OAuth and per-user auth for remote MCP servers

**An MCP server that holds one API key acts as one user, whoever is asking.** Stainless says so about its env-var setup: it “allows anyone who can access your server to perform actions as if they were authenticated.” Per-user auth takes two tokens: one the MCP client gets for the signed-in user, and one the MCP server uses to call your API.

The MCP authorization spec (revision 2026-07-28) covers the first token. “Authorization is **OPTIONAL** for MCP implementations,” and it’s written for remote MCP servers on HTTP. A stdio server should “instead retrieve credentials from the environment.” On a remote MCP server, the client gets a token for the user in four steps:

1.  **The server says where to log in.** The first request gets an “HTTP 401 Unauthorized with WWW-Authenticate header” that points to the server’s protected resource metadata. “MCP servers **MUST** implement OAuth 2.0 Protected Resource Metadata (RFC9728),” and the client reads it to find the authorization server.
2.  **The client registers.** Clients try pre-registered credentials first, then Client ID Metadata Documents, where the `client_id` is an HTTPS URL. Dynamic Client Registration “is deprecated and retained for backwards compatibility.”
3.  **The user signs in.** The client runs the OAuth 2.1 authorization code flow with PKCE in the browser. Its `resource` parameter “**MUST** identify the MCP server that the client intends to use the token with.”
4.  **Every call carries the token.** “Authorization **MUST** be included in every HTTP request from client to server,” in the `Authorization` header and never in the query string.

Client libraries run this flow for you. A FastMCP client takes `auth="oauth"`, and its `OAuth` helper “manages the complexities of the OAuth 2.1 Authorization Code Grant with PKCE.” The Vercel AI SDK’s MCP client takes an `authProvider` on its HTTP and SSE transports. On the server side, FastMCP’s `RemoteAuthProvider` works with identity providers that support Dynamic Client Registration, and `OAuthProxy` covers ones that don’t, “such as GitHub, Google, Azure, AWS.”

The second token has a strict rule. “MCP servers **MUST NOT** accept or transit any other tokens,” and the spec’s security guide calls forwarding the user’s token “an anti-pattern” named token passthrough. So the server can’t send the user’s MCP token on to your API. It needs a token issued for your API.

Here’s how the options get one:

-   **FastMCP** sets auth on the HTTP client you pass in, and when it forwards incoming headers it skips “credential and connection headers such as `Authorization`, `Cookie`, and `Host`.” Per-user tokens are code you write.
-   **Stainless** uses the same scheme as your SDK, an OAuth resource metadata setting, or a generated Cloudflare Worker “that acts as its own OAuth server” for APIs without OAuth.
-   **AgentCore Gateway** handles outbound auth with “two-legged OAuth (Client Credentials grant type) and three-legged OAuth (Authorization Code grant type),” an API key, or IAM SigV4.
-   **LangChain’s toolkit** takes one headers object when you build it.

## MCP transport and hosting: using the tools from the OpenAI Agents SDK or the Vercel AI SDK

The MCP spec defines two transports. stdio runs the server as “a client-launched subprocess.” In Streamable HTTP, “each message is an HTTP POST to a single MCP endpoint.” The older SSE transport is deprecated, and the OpenAI Agents SDK says “The MCP project has deprecated the Server-Sent Events transport.”

stdio is fine on a laptop. A deployed agent needs a remote MCP server over HTTP. The Vercel AI SDK says the stdio transport “cannot be deployed to production environments,” and its MCP client supports “stateless MCP 2026-07-28.” FastMCP serves HTTP with `mcp.run(transport="http")`, and Stainless with `--transport=http`.

The MCP pages of the OpenAI Agents SDK and the Vercel AI SDK never mention OpenAPI. Both connect to an MCP server you already run, or take tools you write by hand (`FunctionTool` wraps “any Python function as a tool”). LangChain’s current MCP path, `MCPAdapter`, “is built on FastMCP.” So for those frameworks, the generator and the server’s hosting stay your job.

## MCP servers in agent SDKs: Claude Agent SDK, Cursor SDK, and LangGraph

Three more agent SDKs load a generated server from config.

The Claude Agent SDK takes an `mcpServers` option on `query()`, or reads a `.mcp.json` file at the project root. A server you start with a command uses stdio, and a remote MCP server at a URL uses `http` or `sse`, with headers such as `Authorization` in the same config. Its tools arrive named `mcp__<server-name>__<tool-name>`, and `allowedTools` approves them.

The Cursor SDK takes an `mcpServers` map on `Agent.create()` or on each `agent.send()`. Each entry is `stdio` with a command, or `http` or `sse` with a URL, plus `headers` for a static token or `auth` for OAuth. On cloud agents, Cursor’s backend handles those headers, and sensitive fields don’t enter the VM.

For LangGraph, the documented path is LangChain’s `MCPAdapter`, which turns a server’s tools into LangChain tools for `create_agent`. LangChain’s agents are “built on top of LangGraph.” The adapter infers the transport from its target: an `https` URL connects over Streamable HTTP, a script path launches over stdio, and an `MCPConfig` dict puts several servers behind one adapter.

**So a server generated from your spec plugs into all three, over stdio on a laptop or over HTTP once it’s deployed.**

## What does Cadenya offer that OpenAPI to MCP generators don’t?

The generators above give you an MCP server to host, and your agent still needs a loop, a token per user, and a way to keep tools current. **Cadenya reads your OpenAPI spec into tools inside a hosted agent loop, with nothing to generate, deploy, or keep in sync.** Here’s what that covers:

1.  **No generator and no server to run.** Point a tool set at an OpenAPI 3.0 or later document, by URL or by upload, and Cadenya reads every operation. It turns path parameters and request bodies into tool parameters.
2.  **Spec changes arrive without a deploy.** When the source is a URL, Cadenya checks the spec for changes each hour. The tool set’s event list shows each sync, and an endpoint returns the exact spec JSON the tool set consumed.
3.  **A big API fits the context window.** Filter an OpenAPI or MCP tool set by name, description, and title, then turn on progressive discovery to load tools on demand.
4.  **Overlays trim what a filter can’t.** An overlay strips parameters, fixes them to literals, and compacts results before they reach the model. That’s the pagination cursors and verbose responses gone from a single heavy tool.
5.  **Each user’s own token on each call.** Reference a secret in a tool header as `{{ secrets.MY_SECRET }}`, and Cadenya resolves it from the workspace, the tool set, or the objective, most specific first. A widget session can carry a token your backend minted for the visitor, re-applied on every turn, encrypted at rest, and never returned by any API.
6.  **IDs the model can’t change.** A pinned parameter, such as `workspaceId` on a `/workspaces/{workspaceId}` path, disappears from the tool schema the model sees and is set server-side on every call.
7.  **Remote MCP servers and plain HTTP in the same agent.** Point an MCP tool set at a remote MCP server URL. It syncs each hour, or just in time when the server lists different tools for different users, and every request carries a challenge token you can verify. HTTP tool sets call endpoints you define on a base URL.
8.  **Approvals on the generated tools.** Require approval for every call, or only for tools that match a filter. The objective pauses on `toolApprovalRequested`, and a denial can carry a memo that steers the model to another choice.
9.  **The loop around the tools, on your keys.** Cadenya calls the model, runs the tools, and streams each reply, and a dropped stream resumes with `Last-Event-ID`. The model is a setting on a variation, so you use your own provider keys and switch models without a deploy.
10.  **SDKs and a price in one line.** TypeScript on Node 18, Python 3.9, Ruby 3.1, and Go 1.22, all 1.9.0 and Apache-2.0. Free for 1,000 loops a month, $49 a month for 50,000, then $0.0015 a loop.

[How tool sets work](/docs/guides/the-basics/tool-sets) shows an OpenAPI tool set end to end, and the free plan needs no card.

No account yet? A coding agent can create a temporary workspace with `cadenya workspaces create --temporary`, run its first objectives there, and hand you a link to claim it, as [auth.md](https://cadenya.com/auth.md) explains. To create an account, sign up at [app.cadenya.com/signup](https://app.cadenya.com/signup?utm_source=cadenya.com&utm_medium=article&utm_campaign=openapi-specs-as-agent-tools-and-mcp), then copy your API key from the API keys page at `app.cadenya.com/account/apiKeys`.