# Read-only mode
Source: https://speakeasy.com/blog/generate-mcp-from-openapi

AI agents are becoming a standard part of software interaction. From Claude Desktop assisting with research to custom agents automating workflows, these tools need a reliable way to interact with APIs.

This is where the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) comes in. Introduced by Anthropic in November 2024, MCP provides a universal standard for connecting AI agents to APIs and data sources. Think of it as the bridge between natural language and your API endpoints.

If you already have an API documented with OpenAPI, you're in luck. You can automatically generate a fully functional MCP server from your existing OpenAPI document. In this guide, we'll look at four tools that make this possible: Speakeasy's SDK generation, the Gram platform, FastMCP for Python developers, and the open-source openapi-mcp-generator.

## What is MCP and why does it matter?

The Model Context Protocol is an open standard that enables AI agents to interact with APIs in a consistent way. Instead of building custom integrations for each AI platform, you create one MCP server that works across compatible AI tools like Claude Desktop, Cursor, and others.

MCP follows a client-server architecture where AI applications act as clients, and your MCP server exposes API operations as "tools" that agents can discover and use. These tools are structured descriptions of what your API can do - complete with parameters, expected inputs, and return types. When an AI agent needs to accomplish a task that requires your API, it queries the MCP server for available tools, selects the appropriate one, and executes it with the necessary parameters.

### From OpenAPI to MCP: Where generators fit in

Now, why does this matter if you already have an OpenAPI document? Because OpenAPI specs already contain everything needed to create MCP tools:

- **Endpoint paths and methods** define what operations are available
- **Parameters and request schemas** specify what inputs each operation needs
- **Response schemas** describe what data comes back
- **Operation descriptions** explain the purpose of each endpoint

An MCP generator transforms your OpenAPI specification into a functioning MCP server that exposes your API endpoints as tools AI agents can use:

![Generation explained](/assets/blog/generate-mcp-from-openapi/generation-explained.png)

Your OpenAPI document serves as the source of truth, with its operations documented in OpenAPI format. An MCP generator reads this document and automatically creates tool definitions for each endpoint. The generated MCP server then acts as a bridge, translating AI agent requests into proper API calls. AI agents can discover and use your API's capabilities through the MCP server, without needing to understand your API's specific implementation details.

Your OpenAPI document becomes the single source of truth, eliminating the need to manually maintain two separate specifications. Your MCP server stays in sync with your API automatically.

## The challenge: Building MCP servers manually

While the MCP specification is well-documented, building a server from scratch involves significant work:

- **Understanding the protocol**: MCP uses JSON-RPC 2.0 for transport and has specific conventions for tool definitions, resource handling, and error responses.
- **Keeping tools in sync**: Every time your API changes, you need to manually update tool definitions to match.
- **Type safety and validation**: You'll need to implement request validation and ensure type safety across the entire chain.
- **Hosting and deployment**: MCP servers need infrastructure for hosting, whether locally for development or remotely for team-wide access.

For teams that already maintain OpenAPI documents, duplicating this effort in MCP format creates unnecessary maintenance burden. This is where automation helps.

## Four tools for generating MCP servers from OpenAPI documents

In this post we'll look at four platforms and tools that automatically generate MCP servers from OpenAPI documents:

- **[Speakeasy](https://www.speakeasy.com/docs/standalone-mcp/build-server)** generates TypeScript SDKs and MCP servers together, giving you full control over the generated code and deployment.
- **[Gram](https://getgram.ai)** is a managed platform made by Speakeasy that provides instant hosting and built-in toolset curation.
- **[FastMCP](https://github.com/jlowin/fastmcp)** is a Pythonic framework that converts OpenAPI specs and FastAPI applications into MCP servers with minimal code.
- **[openapi-mcp-generator](https://github.com/harsha-iiiv/openapi-mcp-generator)** is an open-source CLI tool that generates standalone TypeScript MCP servers.

These tools differ primarily in their hosting models. **Managed platforms** like Gram and FastMCP Cloud handle hosting and infrastructure for you - on Gram you upload your OpenAPI document and you get an instantly accessible MCP server. **Self-hosted** tools like Speakeasy and openapi-mcp-generator generate code that you deploy and run yourself, giving you full control over infrastructure, customization, and deployment.

Here's how they compare across hosting model and automation level:

![Comparing MCP server generators](/assets/blog/generate-mcp-from-openapi/comparing-mcp-server-generators.png)

**[Gram](https://getgram.ai)** offers the fastest path to production with a fully managed platform - no infrastructure to maintain. **[Speakeasy](https://www.speakeasy.com/docs/standalone-mcp/build-server)** provides comprehensive code generation for self-hosted deployment. **[FastMCP](https://github.com/jlowin/fastmcp)** gives you both options: use the Python framework for self-hosted servers or FastMCP Cloud for managed hosting. **[openapi-mcp-generator](https://github.com/harsha-iiiv/openapi-mcp-generator)** generates standalone TypeScript servers for complete self-hosted control.

## MCP server generators comparison

Here's a more detailed comparison of the features of each:

| Feature              | Speakeasy             | Gram          | FastMCP             | openapi-mcp-generator |
|----------------------|-----------------------|---------------|---------------------|-----------------------|
| **Language**         | TypeScript            | N/A (hosted)  | Python              | TypeScript            |
| **Setup complexity** | Low                   | Low           | Low                 | Low                   |
| **Customization**    | Full code access      | Config-based  | Programmatic        | None                  |
| **Tool curation**    | N/A                   | Yes, built-in | Programmatic        | None                  |
| **Hosting**          | Self-hosted           | Managed       | Self-hosted/Managed | Self-hosted           |
| **Type safety**      | Full (Zod)            | N/A           | Partial             | Full (Zod)            |
| **SDK generation**   | Yes (7+ langs)        | No            | No                  | No                    |
| **Auth handling**    | OAuth 2.0             | OAuth 2.0     | Manual config       | Env variables         |
| **Test clients**     | Generated Test Client | Playground    | No                  | HTML clients          |


Next, we'll explore each tool in detail.

## Speakeasy: SDK + MCP server generation

[Speakeasy](https://www.speakeasy.com/docs/standalone-mcp/build-server) is an SDK generation platform that creates production-ready SDKs from OpenAPI documents. When you generate a TypeScript SDK with Speakeasy, you also get a complete MCP server implementation.

### How it works

When Speakeasy processes your OpenAPI document, it generates a type-safe TypeScript SDK using Zod schemas for validation, creates an MCP server that wraps the SDK methods, transforms each SDK operation into an MCP tool with proper type definitions, and provides a CLI for starting and configuring the server.

The generated MCP server includes:

```bash
mcp-server/
├── tools/              # Each API operation as an MCP tool
│   ├── listTasks.ts
│   ├── createTask.ts
│   ├── getTask.ts
│   └── updateTask.ts
├── server.ts          # Main MCP server implementation
├── scopes.ts          # Scope-based access control
└── cli.ts             # Command-line interface
```

### Example: Task management API

Let's say you have a simple task management API with this OpenAPI operation:

```yaml openapi.yaml
paths:
  /tasks:
    post:
      operationId: createTask
      summary: Create a new task
      description: Creates a new task with the provided details
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - title
              properties:
                title:
                  type: string
                  description: Task title
                description:
                  type: string
                  description: Detailed task description
                priority:
                  type: string
                  enum: [low, medium, high]
      responses:
        '201':
          description: Task created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Task'
```

Speakeasy generates an MCP tool that looks like this:

```ts tools/createTask.ts
import { createTask } from "../../funcs/createTask.js";
import * as operations from "../../models/operations/index.js";
import { formatResult, ToolDefinition } from "../tools.js";

const args = {
  request: operations.CreateTaskRequest$inboundSchema,
};

export const tool$createTask: ToolDefinition<typeof args> = {
  name: "create-task",
  description: "Create a new task\n\nCreates a new task with the provided details",
  args,
  tool: async (client, args, ctx) => {
    const [result, apiCall] = await createTask(client, args.request, {
      fetchOptions: { signal: ctx.signal },
    }).$inspect();

    if (!result.ok) {
      return {
        content: [{ type: "text", text: result.error.message }],
        isError: true,
      };
    }

    return formatResult(result.value, apiCall);
  },
};
```

The tool is type-safe, handles errors gracefully, and includes full request validation using Zod schemas.

### Customizing with x-speakeasy-mcp

Speakeasy supports the `x-speakeasy-mcp` OpenAPI extension for fine-tuning your MCP tools:

```yaml
paths:
  /tasks:
    post:
      operationId: createTask
      summary: Create a new task
      x-speakeasy-mcp:
        name: "create_task_tool"
        description: |
          Creates a new task in the task management system.
          Use this when the user wants to add a new task or todo item.
          Requires a title and optionally accepts a description and priority level.
        scopes: [write, tasks]
```

This allows you to provide AI-specific descriptions and organize tools using scopes.

### Using scopes for access control

Scopes let you control which tools are available in different contexts:

```yaml
paths:
  /tasks:
    get:
      x-speakeasy-mcp:
        scopes: [read]
    post:
      x-speakeasy-mcp:
        scopes: [write]
  /tasks/{id}:
    delete:
      x-speakeasy-mcp:
        scopes: [write, destructive]
```

Start the server with specific scopes:

```bash

npx mcp start --scope read