Generate MCP servers from OpenAPI documents

Info Icon

Experimental

The MCP server feature is currently experimental. The AI tools ecosystem is nascent and we plan to keep iterating on it. There may be breaking changes for this feature within the minor and patch version ranges of a TypeScript SDK release.

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 your 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 will be 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 will be generated in the “SDK Installation” section of the README.md file. The MCP client’s install command will use the bin section added to package.json to locate the executable entry point for the server.

Configuring generated tools

Use the x-speakeasy-mcp OpenAPI extension on any operation to customize the MCP tool that will be generated for it:

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 are a way to tag tools so that users can choose which set of tools they want to mount when the MCP server starts. For example, tagging relevant operations with a read scope will allow users to start a server in read-only mode. This adds a level of safety that prevents a client from accidentally modifying or deleting data while exploring.

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 does not have enough useful context, so it’s a good idea to review generated descriptions and override them with this option.

Using overlays

Overlays are a convenient way to introduce the x-speakeasy-mcp extension to existing OpenAPI documents. Use the Speakeasy Overlay Playground (opens in a new tab) to easily create 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 how to launch a basic MCP server defined in a claude_desktop_config.json file. Notice that the env property is used to make environment variables available to the server while arguments after start allow one to customize 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 your 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. Fortunately, you can easily run MCP server changes locally.

After each change, execute npm run build to rebuild the MCP server. Ensure you have Node.js v20 or above installed.

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

Specifying scopes

Scopes allow you to specify 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 further 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": "..."
}
}
}
}