# Generate MCP servers from OpenAPI documents
Source: https://speakeasy.com/docs/standalone-mcp/build-server

import { FileTree } from "nextra/components";



Learn how to build MCP servers from your OpenAPI documents using Speakeasy for production-ready servers with extensive customization options.

## Getting started with Speakeasy

Use the following steps to build an MCP server using Speakeasy.

- Install the Speakeasy CLI with the following commands:

   ```bash
   # Homebrew (macOS)
   brew install speakeasy-api/tap/speakeasy

   # Script Installation (macOS and Linux)
   curl -fsSL https://go.speakeasy.com/cli-install.sh | sh
   ```

- Run the Speakeasy quickstart command:

   ```bash
   speakeasy quickstart --mcp
   ```

- Indicate whether you plan to deploy your server on Cloudflare.

   [Cloudflare](https://developers.cloudflare.com/agents/guides/remote-mcp-server/) is a popular choice for hosting MCP servers. If selected, a Cloudflare Worker config file is generated with your MCP server code, making it easy to deploy your server to a Cloudflare Worker.

These steps create a TypeScript-based MCP server in the specified directory, ready to be deployed into production.

## Example server code

The generated MCP server includes a comprehensive file structure with TypeScript source code:

<div className="filetree-container">
<FileTree>
  <FileTree.Folder name="mcp-server/src" defaultOpen>
    <FileTree.Folder name="cloudflare-worker">
      <FileTree.File name="cloudflare-worker.ts" />
      <FileTree.File name="landing-page.ts" />
    </FileTree.Folder>
    <FileTree.File name="core.ts" />
    <FileTree.Folder name="funcs">
      <FileTree.File name="bookingsCreateBooking.ts" />
      <FileTree.File name="bookingsCreateBookingRaw.ts" />
      <FileTree.File name="bookingsDeleteBooking.ts" />
      <FileTree.File name="bookingsGetBooking.ts" />
      <FileTree.File name="bookingsGetBookings.ts" />
      <FileTree.File name="paymentsCreateBookingPayment.ts" />
      <FileTree.File name="stationsGetStations.ts" />
      <FileTree.File name="tripsGetTrips.ts" />
    </FileTree.Folder>
    <FileTree.Folder name="hooks">
      <FileTree.File name="hooks.ts" />
      <FileTree.File name="registration.ts" />
      <FileTree.File name="types.ts" />
    </FileTree.Folder>
    <FileTree.Folder name="lib">
      <FileTree.File name="base64.ts" />
      <FileTree.File name="config.ts" />
      <FileTree.File name="dlv.ts" />
      <FileTree.File name="encodings.ts" />
      <FileTree.File name="env.ts" />
      <FileTree.File name="files.ts" />
      <FileTree.File name="http.ts" />
      <FileTree.File name="is-plain-object.ts" />
      <FileTree.File name="logger.ts" />
      <FileTree.File name="matchers.ts" />
      <FileTree.File name="primitives.ts" />
      <FileTree.File name="result.ts" />
      <FileTree.File name="retries.ts" />
      <FileTree.File name="schemas.ts" />
      <FileTree.File name="sdks.ts" />
      <FileTree.File name="security.ts" />
      <FileTree.File name="url.ts" />
    </FileTree.Folder>
    <FileTree.Folder name="mcp-server" defaultOpen>
      <FileTree.File name="build.mts" />
      <FileTree.File name="cli.ts" />
      <FileTree.Folder name="cli">
        <FileTree.Folder name="start">
          <FileTree.File name="command.ts" />
          <FileTree.File name="impl.ts" />
        </FileTree.Folder>
      </FileTree.Folder>
      <FileTree.File name="console-logger.ts" />
      <FileTree.File name="extensions.ts" />
      <FileTree.File name="mcp-server.ts" />
      <FileTree.File name="prompts.ts" />
      <FileTree.File name="resources.ts" />
      <FileTree.File name="scopes.ts" />
      <FileTree.File name="server.ts" />
      <FileTree.File name="shared.ts" />
      <FileTree.File name="tools.ts" />
      <FileTree.Folder name="tools">
        <FileTree.File name="bookingsCreateBooking.ts" />
        <FileTree.File name="bookingsCreateBookingRaw.ts" />
        <FileTree.File name="bookingsDeleteBooking.ts" />
        <FileTree.File name="bookingsGetBooking.ts" />
        <FileTree.File name="bookingsGetBookings.ts" />
        <FileTree.File name="paymentsCreateBookingPayment.ts" />
        <FileTree.File name="stationsGetStations.ts" />
        <FileTree.File name="tripsGetTrips.ts" />
      </FileTree.Folder>
    </FileTree.Folder>
    <FileTree.Folder name="models">
      <FileTree.File name="booking.ts" />
      <FileTree.File name="bookinginput.ts" />
      <FileTree.File name="bookingpayment.ts" />
      <FileTree.File name="createbookingop.ts" />
      <FileTree.File name="createbookingpaymentop.ts" />
      <FileTree.File name="createbookingrawop.ts" />
      <FileTree.File name="deletebookingop.ts" />
      <FileTree.Folder name="errors">
        <FileTree.File name="apierror.ts" />
        <FileTree.File name="httpclienterrors.ts" />
        <FileTree.File name="sdkvalidationerror.ts" />
      </FileTree.Folder>
      <FileTree.File name="getbookingop.ts" />
      <FileTree.File name="getbookingsop.ts" />
      <FileTree.File name="getstationsop.ts" />
      <FileTree.File name="gettripsop.ts" />
      <FileTree.File name="linksbooking.ts" />
      <FileTree.File name="linksself.ts" />
      <FileTree.File name="newbookingop.ts" />
      <FileTree.File name="problem.ts" />
      <FileTree.File name="security.ts" />
      <FileTree.File name="station.ts" />
      <FileTree.File name="trip.ts" />
    </FileTree.Folder>
    <FileTree.Folder name="types">
      <FileTree.File name="async.ts" />
      <FileTree.File name="blobs.ts" />
      <FileTree.File name="enums.ts" />
      <FileTree.File name="fp.ts" />
      <FileTree.File name="rfcdate.ts" />
      <FileTree.File name="streams.ts" />
    </FileTree.Folder>
  </FileTree.Folder>
</FileTree>
</div>

## Running your MCP server locally

You can run your MCP server from the generated code, a published npm package, or the generated MCP Bundle (MCPB) package.

### Local development setup

For local development and debugging, you can run your MCP server directly from the generated code:

```json
{
  "mcpServers": {
    "MyAPI": {
      "command": "node",
      "args": ["/path/to/repo/bin/mcp-server.js", "start"],
      "env": {
        "API_TOKEN": "your-api-token-here"
      }
    }
  }
}
```

This configuration allows you to do the following:

- Debug your server code directly.
- Make real-time changes during development.
- Test API integrations locally.
- Validate tool functionality before distribution.

### Testing with a published package

Once you've published your MCP server to npm (following our [SDK publishing guide](/docs/publish-sdk)), you can test using the npm package format that will be used in production:

```json
{
  "mcpServers": {
    "MyAPI": {
      "command": "npx",
      "args": ["your-npm-package@latest", "start"],
      "env": {
        "API_TOKEN": "your-api-token-here"
      }
    }
  }
}
```

**Note:** You must first publish your package to npm before you can test it using this configuration.

### Using the generated MCPB

For the most user-friendly testing experience, use the generated MCPB package. Claude Desktop and other MCP clients can load MCPB files directly:

- **Locate your generated MCPB file** in the output directory (it typically has a `.mcpb` extension).
- **Install the MCPB** in your MCP client following the client's installation process.
- **Configure environment variables** if your server requires authentication.

## Advanced configuration

You can further configure your MCP server to specify the tools or tool scopes it includes at runtime.

### Specify scopes at runtime

When starting the MCP server, you can specify which scopes to include:

```json
{
  "mcpServers": {
    "MyAPI": {
      "command": "npx",
      "args": ["your-npm-package@latest", "start", "--scope", "read"],
      "env": {
        "API_TOKEN": "your-api-token-here"
      }
    }
  }
}
```

This example configuration only mounts tools tagged with the `read` scope, creating a read-only server.

### Specify individual tools

You can further limit the subset of tools mounted on an MCP server by specifying individual tool names:

```json
{
  "mcpServers": {
    "MyAPI": {
      "command": "npx",
      "args": ["your-npm-package@latest", "start", "--tool", "my_tool_1", "--tool", "my_tool_2"],
      "env": {
        "API_TOKEN": "your-api-token-here"
      }
    }
  }
}
```

## Distribution and hosting options

Speakeasy generates MCP servers with three primary distribution methods. You can distribute your server as an npm package, a Cloudflare Worker, or an MCPB file. These methods aren't mutually exclusive — most customers use all three approaches to serve different use cases.

### Distribute your MCP server on npm

Publishing your MCP server as an npm package is the most common starting point, as it provides the most flexible distribution method, in addition to the following benefits:

- **Universal compatibility:** You can use a single command that works with all major MCP clients.
- **Easy customization:** Users can modify tools, add tools, and extend functionality.
- **Version management:** Standard npm versioning and dependency management apply.
- **Team sharing:** Distribution across development teams is simple.

```json
{
  "mcpServers": {
    "MyAPI": {
      "command": "npx",
      "args": ["your-npm-package@latest", "start"],
      "env": {
        "API_TOKEN": "your-api-token-here"
      }
    }
  }
}
```

Follow the [SDK publishing guide](/docs/publish-sdk) for detailed instructions on publishing to npm and other package managers.

### Deploy your MCP server to Cloudflare Workers

Cloudflare hosting enables OAuth authentication flows and eliminates the need for users to manage API keys directly. The benefits include:

- **OAuth support:** End-users authenticate through OAuth instead of providing API keys.
- **Serverless hosting:** No infrastructure management is required.
- **Global distribution:** You can use Cloudflare's edge network for low latency.
- **Same customization:** Full tool customization capabilities are available.

Follow the [Cloudflare deployment guide](/docs/standalone-mcp/cloudflare-deployment) for detailed instructions on using Cloudflare hosting.

### Generate your MCP server as an MCPB file

In addition to a drag-and-drop experience for end users (particularly in Claude Desktop), MCPB provides the following benefits:

- **User-friendly installation:** Drag-and-drop installation in Claude Desktop.
- **Guided setup:** Nicely prompts end-users for API keys and auth credentials.
- **Self-contained format:** All dependencies and metadata bundled together.
- **Cross-platform compatibility:** Works across different operating systems and MCP clients.

Speakeasy automatically generates [MCP Bundle (`.mcpb` files)](https://github.com/anthropics/dxt) as part of MCP server generation. The MCPB includes:

- **A `manifest.json` file**, containing metadata describing your MCP server
- **All the necessary server files**, packaged for distribution
- **Tool descriptions and parameters**, automatically inferred from your OpenAPI document
- **Icon and branding assets**, if provided

You can customize the generated MCPB manifest through the `gen.yaml` configuration file:

```yaml
targets:
  mcp-typescript:
    mcpbManifestOverlay:
      icon: "https://example.com/my-icon.png"
      displayName: "My Custom API Tools"
      description: "Custom description for my MCP server"
      version: "1.0.0"
```

### Hybrid distribution strategy

You can use all three distribution methods simultaneously, giving users the flexibility to choose their preferred installation method based on their specific needs and technical requirements.

## Best practices

When building MCP servers with Speakeasy:

- **Use clear OpenAPI documentation:** Well-documented APIs generate better MCP tools.
- **Implement proper error handling:** Ensure your API returns meaningful error messages.
- **Use the `x-speakeasy-mcp` extension:** Customize tool names, descriptions, and scopes.
- **Test thoroughly:** Verify that your MCP server works with different clients.
- **Version your APIs:** Use semantic versioning for your OpenAPI documents.
- **Monitor performance:** Track the usage and performance of your MCP tools.
- **Provide clear branding:** Include a `.png` icon file in your project for automatic [MCPB](https://www.anthropic.com/engineering/desktop-extensions) icon detection.
- **Customize MCPB metadata:** Use `mcpbManifestOverlay` in `gen.yaml` to provide custom display names and descriptions.

## Next steps

Having set up your MCP server with Speakeasy, you can now learn to do the following:

- **[Customize your MCP tools](/docs/standalone-mcp/customize-tools):** Customize your generated tools using the `x-speakeasy-mcp` OpenAPI extension.
- **[Build custom resources](/docs/standalone-mcp/custom-resources):** Add custom tools and resources to your MCP server
- **[Use custom prompts](/docs/standalone-mcp/custom-prompts):** Create reusable prompt templates.
- **[Set up OAuth](/docs/standalone-mcp/setting-up-oauth):** Configure authentication for your MCP server.