Skip to main content
Glama
iceener

MCP Streamable HTTP Server Template

by iceener

MCP Server Template

This template is a remote Model Context Protocol (MCP) server. It runs on Bun and on Cloudflare Workers. It uses the official MCP TypeScript SDK.

The server uses protocol version 2026-07-28. It also accepts clients that use the 2025 protocol versions.

The template includes these functions:

  • Checks of the Host and Origin headers.

  • OAuth token checks. The server is an OAuth resource server. Your code does not receive the token.

  • An error policy. The server does not send internal error data to clients.

  • Tests that run on Bun and on Cloudflare Workers.

The sample server gives weather data from Open-Meteo. Open-Meteo does not require an API key. Replace the samples with your tools. Keep the other parts of the template.

Requirements

  • Bun 1.4 or later.

  • Node.js 22.18 or later. The Wrangler commands and the smoke tests use Node.js.

Related MCP server: MCP Server + Clerk OAuth

Start the server

  1. Install the dependencies:

    bun install
  2. Start the server:

    bun run dev

The server URL is http://127.0.0.1:3000/mcp.

To use the Cloudflare local runtime, run bun run dev:worker. The server URL is then http://127.0.0.1:8787/mcp.

Connect a client

Use the server URL and the Streamable HTTP transport.

Client

Procedure

MCP Inspector

Run bun run inspector. Select Streamable HTTP. Enter the server URL.

Claude Code

Run claude mcp add --transport http weather http://127.0.0.1:3000/mcp.

VS Code

Add { "servers": { "weather": { "type": "http", "url": "http://127.0.0.1:3000/mcp" } } } to .vscode/mcp.json.

Cursor

Add { "mcpServers": { "weather": { "url": "http://127.0.0.1:3000/mcp" } } } to ~/.cursor/mcp.json.

To test the connection, send a request. For example: "What is the weather in Kraków this week?"

Samples

Each sample shows one procedure.

Sample

Type

Shows

get-forecast

Tool

A call to an external API through a service. It shows cancellation, progress, and errors that the model can correct.

echo

Tool

The smallest complete tool: an input schema, an output schema, and annotations.

whoami

Tool

How to read the identity of the verified caller.

confirm-action

Tool

How to ask the user for approval during a call (input_required). The tool also requires an OAuth scope.

docs://server/guide

Resource

A static resource.

weather://codes/{code}

Resource template

How to list, read, and complete URIs from a template.

weather-briefing

Prompt

Prompt arguments and argument completion.

Project structure

src/
  server.ts       Server identity, dependencies, token verification, extra routes, McpServer factory
  settings.ts     Settings for your code, for example API keys
  tools/          ┐
  resources/      │ Your code. Each tool, resource, or prompt has one file.
  prompts/        │ The index.ts file in each folder lists them.
  services/       ┘ Clients for the external APIs that your tools use
  platform/       Template code: configuration, HTTP pipeline, authentication, logs, defineTool
  bun.ts          Entry point for Bun
  worker.ts       Entry point for Cloudflare Workers
tests/            Tests for each tool and service, and tests for the platform code
scripts/          Smoke tests on real network sockets, and a local token issuer

You change server.ts, settings.ts, and the four folders. The platform/ folder is template code. Do not change it unless it is necessary.

platform/ uses only a fixed set of names from server.ts and settings.ts. This lets you replace platform/ with the version from a newer template. server.ts has hooks for settings, runtime resources (for example Workers KV), token verification, authorization server metadata, and extra HTTP routes.

Add a tool

  1. Create a file in src/tools/. For example:

    // src/tools/add.ts
    import * as z from 'zod/v4';
    import { defineTool } from '../platform/primitives';
    
    export const add = defineTool(
      'add',
      {
        description: 'Add two numbers.',
        inputSchema: z.object({ a: z.number(), b: z.number() }),
        outputSchema: z.object({ sum: z.number() }),
        annotations: { readOnlyHint: true, openWorldHint: false },
      },
      ({ a, b }) => ({
        content: [{ type: 'text', text: String(a + b) }],
        structuredContent: { sum: a + b },
      }),
    );
  2. Add the tool to the list in src/tools/index.ts.

  3. Create the test file tests/tools/add.test.ts. Use tests/tools/echo.test.ts as an example.

defineTool has the same arguments as server.registerTool in the SDK. It also does these tasks:

  • It gives your dependencies (deps) to the handler as the last argument.

  • It makes sure that structuredContent agrees with outputSchema when you compile the code.

  • It records unexpected errors in the log. The model does not see these errors.

For errors, progress, cancellation, user input, scopes, and tests, refer to docs/tools.md.

Runtimes

Bun

Cloudflare Workers

Start locally

bun run dev

bun run dev:worker

Configuration

.env (refer to .env.example)

vars in wrangler.jsonc. Put local secrets in .dev.vars.

Deployment

A host that runs Bun, behind HTTPS

bun run deploy

Use it for

Long tasks, local processes, your own servers

Global hosting without server maintenance

The two runtimes use the same application. Only the entry point is different. For more data, refer to docs/deploy.md.

Configuration

The server identity (name, version, and instructions) is in src/server.ts. The deployment settings are environment variables:

Variable

Default

Function

MCP_PUBLIC_URL

http://127.0.0.1:$PORT/mcp

The public URL of the endpoint. Production requires it.

MCP_ALLOWED_HOSTS

The host of the public URL, and the loopback hosts outside production

The Host headers that the server accepts

MCP_ALLOWED_ORIGIN_HOSTNAMES

The host of the public URL, and the loopback hosts outside production

The browser Origin headers that the server accepts

AUTH_MODE

none

none, bearer, or oauth. Production requires it.

BEARER_TOKEN

The shared token when AUTH_MODE=bearer. Store it as a secret.

OAUTH_*

The settings of your authorization server. Refer to docs/auth.md.

MCP_LEGACY_MODE

stateless

Set reject to accept only 2026-07-28 clients.

LOG_LEVEL

info

debug, info, warning, or error

Put your own settings, for example API keys, in src/settings.ts. The server validates them together with the other settings. The file .env.example describes all variables.

If the configuration is not valid, the server shows all problems at the same time:

  • Bun does not start.

  • A Worker records the problems in the log. It sends a 500 response to all requests until you correct the configuration.

Authentication

The server has three authentication modes:

  • none: The server accepts all requests.

  • bearer: All clients send the same secret token (BEARER_TOKEN) in the Authorization header.

  • oauth: The server is an OAuth resource server. The server publishes metadata that tells clients where your authorization server is. The server accepts only the tokens that your authorization server issued for this server URL.

The server can also be its own authorization server, for example in front of the OAuth of an external provider. For this procedure, refer to docs/auth.md.

To test OAuth without an authorization server, run bun run token. This command starts a local key server. It shows a token and the settings to use. For real providers and scopes for each tool, refer to docs/auth.md.

Scripts

Script

Function

bun run dev

Starts the server on Bun.

bun run dev:worker

Starts the server in the Cloudflare local runtime.

bun run check

Does the type check, the lint check, and the tests. It also checks the generated Worker types. CI runs this script.

bun run test:smoke

Starts the real server on Bun and on workerd, and sends requests through network sockets. It requires Node.js 22.18 or later.

bun run inspector

Starts MCP Inspector.

bun run token

Starts a local authorization server and shows a test token.

bun run deploy

Deploys to Cloudflare with the production settings in wrangler.jsonc.

bun run types:worker

Makes the Worker types again. Run it after you change wrangler.jsonc.

Documentation

License

MIT

Related MCP Connectors

  • Hosted MCP server with managed OAuth for 15+ toolkits: Google Workspace, Fitbit, Oura, Kalshi, etc.

  • Remote streamable-HTTP MCP server running on a single Cloudflare Worker. Your assistant gets live Airbnb, Amazon, Booking.com, Google Flights, Maps and Reddit data, social search on X, Instagram and TikTok, the Meta Ad Library, and image/video generation without any keys. Connect your own accounts to let it send WhatsApp or Telegram messages, work an IMAP inbox, manage Meta Ads campaigns and publish to X and LinkedIn. OAuth 2.1 with PKCE; stored credentials are AES-256-GCM encrypted.

  • Model Context Protocol server for the Apideck Unified API. Connect any MCP-compatible agent framework to 100+ accounting systems, HRIS platforms, file storage providers, and more through one integration. More information https://www.apideck.com/mcp-server

  • The Stytch MCP server is a reference implementation that demonstrates remote MCP server authentication and authorization using Stytch Connected Apps. It provides OAuth 2.1-compliant authorization (including PKCE), Dynamic Client Registration, and validates Stytch-issued access tokens to enable AI agents to securely interact with external services through permissioned access, supporting scopes like openid, email, profile, and manage:project_data.

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A comprehensive Model Context Protocol server template that implements HTTP-based transport with OAuth proxy for third-party authorization servers like Auth0, enabling AI tools to securely connect while supporting Dynamic Application Registration.
    12 npm
    7
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    A remote Model Context Protocol server template for Cloudflare Workers with built-in Clerk OAuth authentication and role-based access control. Enables secure deployment of MCP servers with user authentication and customizable tool access based on user roles.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    A template for deploying secure Model Context Protocol servers to Cloudflare Workers with built-in OAuth authentication. It enables hosting and connecting remote tools to Claude Desktop using SSE transport and a local proxy.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables deploying and running a Model Context Protocol (MCP) server on Cloudflare Workers with built-in OAuth authentication. It allows users to host and access tools remotely via Server-Sent Events (SSE) transport from clients like Claude Desktop.
    -