npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@tmcp/transport-http

v0.8.3

Published

Transport for TMCP using HTTP

Readme

@tmcp/transport-http

An HTTP transport implementation for TMCP (TypeScript Model Context Protocol) servers. This package provides HTTP Streaming based communication for MCP servers over HTTP, enabling web-based clients to interact with your MCP server through standard HTTP requests.

Installation

pnpm add @tmcp/transport-http tmcp

Usage

Basic Setup

import { McpServer } from 'tmcp';
import { HttpTransport } from '@tmcp/transport-http';

// Create your MCP server
const server = new McpServer(
	{
		name: 'my-http-server',
		version: '1.0.0',
		description: 'My HTTP MCP server',
	},
	{
		adapter: new YourSchemaAdapter(),
		capabilities: {
			tools: { listChanged: true },
			prompts: { listChanged: true },
			resources: { listChanged: true },
		},
	},
);

// Add your tools, prompts, and resources
server.tool(
	{
		name: 'example_tool',
		description: 'An example tool',
	},
	async () => {
		return {
			content: [{ type: 'text', text: 'Hello from HTTP!' }],
		};
	},
);

// Create the HTTP transport (defaults to '/mcp' path)
const transport = new HttpTransport(server);

// Use with your preferred HTTP server
// Example with Node.js built-in server + @remix-run/
import * as http from 'node:http';
import { createRequestListener } from '@remix-run/node-fetch-server';

let httpServer = http.createServer(createRequestListener((request)=>{
	const response = await transport.respond(request);
	if(response){
		return response;
	}
	return new Response(null, { status: 404 });
}));


httpServer.listen(3000, () => {
	console.log('MCP HTTP server listening on port 3000');
});

With Custom Configuration

const transport = new HttpTransport(server, {
	// Custom MCP endpoint path (default: '/mcp', use null to respond on every path)
	path: '/api/mcp',
	// Custom session ID generation
	getSessionId: () => {
		return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
	},
});

> [!NOTE]
> When the transport runs in development mode and you omit the `path` option, a warning is emitted. Future releases will treat an `undefined` path as "respond on every path", so set the property explicitly (for example `path: '/mcp'` or `path: null`) to lock in the behavior you want today.

With Custom Context

You can pass custom context data to your MCP server for each request. This is useful for authentication, user information, database connections, etc.

// Define your custom context type
interface MyContext {
    userId: string;
    permissions: string[];
    database: DatabaseConnection;
}

// Create server with custom context
const server = new McpServer(serverInfo, options).withContext<MyContext>();

server.tool(
    {
        name: 'get-user-profile',
        description: 'Get the current user profile',
    },
    async () => {
        // Access custom context in your handler
        const { userId, database } = server.ctx.custom!;
        const profile = await database.users.findById(userId);

        return {
            content: [
                { type: 'text', text: `User profile: ${JSON.stringify(profile)}` }
            ],
        };
    },
);

// Create transport (it will be typed to accept your custom context)
const transport = new HttpTransport(server);

// then in the handler
const response = await transport.respond(req, {
	userId,
	permissions,
	database: req.locals.db,
});

Session Management

The HTTP transport supports custom session managers for different deployment scenarios:

In-Memory Sessions (Default)

import {
	InMemoryStreamSessionManager,
	InMemoryInfoSessionManager,
} from '@tmcp/session-manager';

const transport = new HttpTransport(server, {
	sessionManager: {
		streams: new InMemoryStreamSessionManager(),
		info: new InMemoryInfoSessionManager(),
	},
});

Redis Sessions (Multi-Server/Serverless)

For deployments across multiple servers or serverless environments where sessions need to be shared:

import {
	RedisStreamSessionManager,
	RedisInfoSessionManager,
} from '@tmcp/session-manager-redis';

const transport = new HttpTransport(server, {
	sessionManager: {
		streams: new RedisStreamSessionManager('redis://localhost:6379'),
		info: new RedisInfoSessionManager('redis://localhost:6379'),
	},
});

When to use Redis sessions:

  • Multi-server deployments: When your application runs on multiple servers and clients might connect to different instances
  • Serverless deployments: When your transport is deployed on serverless platforms where instances are ephemeral (attention, serverless environment generally kills SSE request after a not-so-long amount of time, this means notification from the server will not reach the client after the shutdown)
  • Load balancing: When using load balancers that might route requests to different server instances

Features

  • 🌐 HTTP/SSE Communication: Uses Server-Sent Events for real-time bidirectional communication
  • 🔄 Session Management: Maintains client sessions with automatic session ID generation
  • 📡 Streaming Responses: Supports streaming responses through SSE
  • 🛤️ Configurable Path: Customizable MCP endpoint path with automatic filtering (set path to null to respond everywhere)
  • 🔧 Framework Agnostic: Works with any HTTP server framework (Fastify, Bun, Deno, etc.)
  • ⚡ Real-time Updates: Server can push notifications and updates to connected clients
  • 🛡️ Error Handling: Graceful error handling for malformed requests
  • 🔀 Multiple HTTP Methods: Supports GET (notifications), POST (messages), and DELETE (disconnect)
  • 🧠 Session Metadata: Automatically persists client capabilities, info, and log levels and exposes them via server.ctx.sessionInfo

API

HttpTransport

Constructor

new HttpTransport(server: McpServer, options?: HttpTransportOptions)

Creates a new HTTP transport instance.

Parameters:

  • server - A TMCP server instance to handle incoming requests
  • options - Optional configuration for the transport

Options:

interface HttpTransportOptions {
	getSessionId: () => string; // Custom session ID generator
	path?: string | null; // MCP endpoint path (default: '/mcp', null responds on every path)
	oauth?: OAuth; // an oauth provider generated from @tmcp/auth
	sessionManager?: {
		streams?: StreamSessionManager;
		info?: InfoSessionManager;
	}; // Provide custom managers; defaults to in-memory implementations
}

If you omit sessionManager the transport creates InMemoryStreamSessionManager and InMemoryInfoSessionManager instances for you. You can override either field independently (for example, Redis streams with in-memory metadata during development).

Methods

respond(request: Request, customContext?: T): Promise<Response | null>

Processes an HTTP request and returns a Response with Server-Sent Events, or null if the request path doesn't match the configured MCP path.

Parameters:

  • request - A Web API Request object containing the JSON-RPC message
  • customContext - Optional custom context data to pass to the MCP server for this request

Returns:

  • A Response object with SSE stream for ongoing communication, or null if the request path doesn't match the MCP endpoint

HTTP Methods:

  • POST: Processes MCP messages and returns short-lived event stream responses
  • GET: Establishes long-lived connections for server notifications
  • DELETE: Disconnects sessions and cleans up resources

Protocol Details

HTTP Methods

The transport supports three HTTP methods:

POST - Message Processing

Clients send JSON-RPC messages via HTTP POST requests:

POST /mcp HTTP/1.1
Content-Type: application/json
mcp-session-id: optional-session-id

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}

Response: Short-lived event stream that closes after sending the response:

HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
mcp-session-id: generated-or-provided-session-id

data: {"jsonrpc":"2.0","id":1,"result":{"tools":[...]}}

GET - Notification Stream

Establishes long-lived connections for server notifications:

GET /mcp HTTP/1.1
mcp-session-id: optional-session-id

Response: Long-lived event stream for server notifications:

HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
mcp-session-id: generated-or-provided-session-id

data: {"jsonrpc":"2.0","method":"notifications/initialized","params":{}}

DELETE - Session Disconnect

Disconnects a session and cleans up resources:

DELETE /mcp HTTP/1.1
mcp-session-id: session-to-disconnect

Response:

HTTP/1.1 204 No Content
mcp-session-id: session-to-disconnect

Session Management

  • Session ID Header: mcp-session-id
  • Automatic Generation: If no session ID is provided, one is generated automatically
  • Session Persistence: Sessions persist across multiple requests until the client disconnects
  • Server Notifications: Server can send notifications to all active sessions

Framework Examples

Bun

import { McpServer } from 'tmcp';
import { HttpTransport } from '@tmcp/transport-http';

const server = new McpServer(/* ... */);
const transport = new HttpTransport(server);

Bun.serve({
	port: 3000,
	async fetch(req) {
		const response = await transport.respond(req);
		if (response === null) {
			return new Response('Not Found', { status: 404 });
		}
		return response;
	},
});

Deno

import { McpServer } from 'tmcp';
import { HttpTransport } from '@tmcp/transport-http';

const server = new McpServer(/* ... */);
const transport = new HttpTransport(server);

Deno.serve({ port: 3000 }, async (req) => {
	const response = await transport.respond(req);
	if (response === null) {
		return new Response('Not Found', { status: 404 });
	}
	return response;
});

srvx

If you want the same experience across Deno, Bun, and Node.js, you can use srvx.

import { McpServer } from 'tmcp';
import { HttpTransport } from '@tmcp/transport-http';
import { serve } from 'srvx';

const server = new McpServer(/* ... */);
const transport = new HttpTransport(server);

serve({
	async fetch(req) {
		const response = await transport.respond(req);
		if (response === null) {
			return new Response('Not Found', { status: 404 });
		}
		return response;
	},
});

Error Handling

The transport includes comprehensive error handling:

  • Malformed JSON: Invalid JSON requests return appropriate error responses
  • Session Management: Automatic cleanup of disconnected sessions
  • Server Errors: Server processing errors are propagated to clients

Development

# Install dependencies
pnpm install

# Generate TypeScript declarations
pnpm generate:types

# Lint the code
pnpm lint

Requirements

  • Node.js 16+ (for native ES modules and Web API support)
  • A TMCP server instance
  • An HTTP server framework or runtime
  • A schema adapter (Zod, Valibot, etc.)

Related Packages

Acknowledgments

Huge thanks to Sean O'Bannon that provided us with the @tmcp scope on npm.

License

MIT