Adapting Speakeasy MCP Servers for Remote Deployment
Speakeasy-generated MCP servers are designed to run locally using Node.js, but
they can be adapted into remote services using MCP’s Streamable HTTP transport
specification
- Simplified deployment: Users don’t need Node.js, npm, or other local tooling installed
- Flexible hosting: Deploy to any cloud provider, container platform, or server infrastructure
- Distribution independence: Eliminate reliance on npm registries for server distribution
- Multi-client support: Handle concurrent connections from multiple MCP clients
This guide demonstrates how to prepare a Speakeasy-generated MCP server for cloud deployment by wrapping it in an HTTP framework like Express.js, enabling it to serve multiple clients simultaneously over standard HTTP connections.
Prerequisites
Before starting, readers will need the following:
Testing the MCP Server Locally
While working on the MCP server, take advantage of the MCP
Inspector
First, run the inspector with the following command:
Once the inspector is running, set the transport to “Streamable HTTP” and the
URL to the address of the local MCP endpoint, which is
http://localhost:3000/mcp
in this tutorial. This will allow you to connect to
the MCP server and verify it’s working correctly before deployment.
Preparing the HTTP Server
From a terminal, navigate to the root directory of your Speakeasy-generated MCP server project, and create a new file for the HTTP server:
In this file, we will set up an Express.js server to handle incoming HTTP requests and route them to the MCP server. First, we’ll set up the skeleton for the HTTP server - a thin wrapper around the generated MCP server. For now, it only requires a single endpoint to handle incoming requests.
Note
The MCP protocol requires a GET /mcp
endpoint for establishing Server-Sent
Events (SSE) connections. In this example, we return a 405 Method Not Allowed
response for this endpoint, as we are not implementing SSE support for the scope of this guide.
Read the MCP
Specification
Start the server with the following command:
This will start the server and listen for incoming requests on port 3000
.
Trying to connect to this server with the MCP Inspector will result in an
error, so let’s implement the MCP transport handling logic next.
Handling MCP Client Requests
To handle requests from an MCP client (eg: Claude, Cursor, MCP Inspector, etc),
we’ll need to implement the MCP transport logic in the POST /mcp
endpoint.
We’ll accomplish this by constructing an internal MCP server instance, and
connecting it to a transport that can handle incoming HTTP requests.
Let’s break down the key components of this code:
-
Key Component #1: Create the MCP Server Instance - The MCP Server instance manages the server’s capabilities and handles capability negotiation with clients. It processes resource discovery, tool registration, and routes MCP protocol messages.
-
Key Component #2: Create the MCP Transport Instance - The Transport handles the communication details between HTTP requests and MCP protocol messages. This includes aspects such as headers, status codes, encoding, and streaming. Setting
sessionIdGenerator
toundefined
makes the implementation stateless - each request is independent with no session tracking. -
Key Component #3: Connect the MCP Server to the Transport - This connects the MCP server to the transport, establishing the bridge between MCP protocol logic and HTTP communication.
-
Key Component #4: Handle the Request Using the MCP Transport - This processes the incoming HTTP request through the MCP transport layer and sends the appropriate MCP response back to the client.
After implementing the above code, the MCP Inspector (and other clients) should be able to connect to the server, list its capabilities (tools, prompts, resources), and even execute unauthenticated tools.
If your MCP server needs to be able to use tools that interact with authenticated API endpoints, keep reading to learn how to accept an authentication header from the client, and use it to authenticate requests to the API.
Adding Authentication Support
Our HTTP server can also accept headers from a client and pass them to the underlying MCP server. This is useful for scenarios where the MCP server needs to authenticate requests to an API.
The following example accepts an Authorization
header from the client, and
uses it to authorize the underlying API client, which is used by the MCP server
to make requests to the API.
Let’s review the key components again:
-
Key Component #1: Initialize the API Client with the Optional Credential - This initializes the API client with the
Authorization
header from the request, if it exists. This allows the MCP server to authenticate requests to the API. -
Key Component #2: Pass the API Client to the MCP Server - This passes the authenticated API client to the server, so calls can be made to secured API operations.
Now, when the MCP Inspector (or any other client) connects to the server, it
can include an Authorization
header with an API key or token. The MCP server
will use this header to authenticate requests to the API client, allowing it to
access secured operations and resources.
Note
This pattern can be used further configure the API client. For example, an
X-Env
header could be sent to the server from the client, which can be used
to select the serverUrl
to use for the API client (eg: production
or
sandbox
):
Last updated on