Generate MCP servers from OpenAPI documents

Info Icon

Beta

The MCP server feature is currently in Beta. The Beta tag indicates the maturity of the MCP protocol which Anthropic is actively evolving. it does not reflect the maturity of Speakeasy code generation.

Model Context Protocol (MCP) (opens in a new tab) is an open-source protocol for defining tools, developed by Anthropic. Many AI-powered tools, like the Claude (opens in a new tab) desktop app or Cursor (opens in a new tab) code editor, are adopting MCP. The full list of clients is available here (opens in a new tab).

Speakeasy-generated TypeScript SDKs include a Model Context Protocol (MCP) server, enabling integration with any supported client.

Prerequisites

To enable MCP server generation, set enableMCPServer to true in the gen.yaml file, then regenerate the SDK on GitHub or run speakeasy run locally.

Info Icon

Temporary restriction

MCP server generation is only supported for TypeScript SDKs using responseFormat: flat.

<sdk-root>/.speakeasy/gen.yaml
typescript:
responseFormat: flat
enableMCPServer: true

What’s generated

The MCP server code is generated in a new src/mcp-server folder in the SDK:

bluesky-ts/src/mcp-server
├── tools
│ ├── accountDelete.ts
│ ├── accountExportData.ts
│ ├── accountsGetInviteCodes.ts
│ ├── actorGetSuggestions.ts
│ ├── ...
├── build.mts
├── mcp-server.ts
├── resources.ts
├── server.ts
├── shared.ts
└── tools.ts

Instructions for installing the server are generated in the “SDK Installation” section of the README.md file. The MCP client’s install command uses the bin section added to package.json to locate the executable entry point for the server.

Configuring generated tools

The x-speakeasy-mcp OpenAPI extension on any operation customizes the MCP tool that will be generated:

openapi.yaml
paths:
/products:
post:
operationId: createProduct
tags: [products]
summary: Create product
description: API endpoint for creating a product in the CMS
x-speakeasy-mcp:
disabled: false
name: create-product
scopes: [write, ecommerce]
description: |
Creates a new product using the provided form. The product name should
not contain any special characters or harmful words.
requestBody:
# ...
responses:
# ...

disabled (optional, default: false)

If disabled is set to true, the generator will not create the MCP tool for this operation.

name (optional)

The name of the MCP tool. The default value is derived from operationId, tags, x-speakeasy-name-override, and x-speakeasy-name-group, and is usually sufficient. In the example above, the default name of the tool would be products_create-product.

scopes (optional)

Scopes tag tools so that specific sets of tools can be mounted when the MCP server starts. For example, tagging relevant operations with a read scope allows starting a server in read-only mode. This adds safety by preventing accidental modification or deletion of data during exploration.

description (optional)

The description of the MCP tool passed as context to MCP clients and language models. The default value for a tool’s description is the OpenAPI operation summary. In the example above, the description would be:

Create product
API endpoint for creating a product in the CMS

The default description often lacks sufficient context, making it beneficial to review and override generated descriptions with this option.

Using overlays

Overlays provide a convenient way to introduce the x-speakeasy-mcp extension to existing OpenAPI documents. The Speakeasy Overlay Playground (opens in a new tab) simplifies creating an overlays file.

For example, to add scopes to operations based on the HTTP method:

overlay.yaml
overlay: 1.0.0
info:
title: Add MCP scopes
version: 0.0.0
actions:
- target: $.paths.*["get","head","query"]
update: { "x-speakeasy-mcp": { "scopes": ["read"] } }
- target: $.paths.*["post","put","delete","patch"]
update: { "x-speakeasy-mcp": { "scopes": ["write"] } }

Using the MCP server

The example below shows a basic MCP server defined in a claude_desktop_config.json file. The env property makes environment variables available to the server while arguments after start allow customization of specific server attributes.

{
"mcpServers": {
"Todos": {
"command": "npx",
"args": ["-y", "--", "todos", "mcp", "start"]
"env": {
"TODOS_API_TOKEN": "..."
}
}
}
}

Running standalone binaries

Standalone MCP server binaries are automatically built and included in GitHub releases for published SDKs.

curl -L -o mcp-server \
https://github.com/{org}/{repo}/releases/download/{tag}/mcp-server-bun-darwin-arm64 && \
chmod +x mcp-server

For private repositories, include a GitHub personal access token (PAT) to download a release: -H "Authorization: Bearer {GITHUB_PAT}".

{
"mcpServers": {
"Todos": {
"command": "./DOWNLOAD/PATH/mcp-server",
"args": [
"start"
]
}
}
}

Running MCP locally

Publishing an npm package for every test of custom changes can be time-consuming. Running MCP server changes locally is more efficient.

Execute npm run build after each change to rebuild the MCP server. This requires Node.js v20 or above.

{
"mcpServers": {
"Todos": {
"command": "node",
"args": [
"/path/to/repo/bin/mcp-server.js",
"start"
],
"env": {
"TODOS_API_TOKEN": "..."
}
}
}
}

Specifying scopes

Scopes determine which set of tools to mount when the MCP server starts.

{
"mcpServers": {
"Todos": {
"command": "npx",
"args": ["-y", "--", "todos", "mcp", "start", "--scope", "read"]
"env": {
"TODOS_API_TOKEN": "..."
}
}
}
}

Specifying tools

To narrow the subset of tools mounted on an MCP server, pass specific tool names as arguments.

{
"mcpServers": {
"Todos": {
"command": "npx",
"args": ["-y", "--", "todos", "mcp", "start", "--tool", "my_tool_1", "--tool", "my_tool_2"]
"env": {
"TODOS_API_TOKEN": "..."
}
}
}
}