Skip to content

feat: Add Streamable HTTP Transport for MCP with AWS Lambda #191

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,20 @@

All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.

## [0.2.2](https://github.com/awslabs/run-model-context-protocol-servers-with-aws-lambda/compare/v0.2.1...v0.2.2) (2025-07-06)
## [0.3.0](https://github.com/awslabs/run-model-context-protocol-servers-with-aws-lambda/compare/v0.2.2...v0.3.0) (2025-06-24)

### Features

* **Streamable HTTP Transport**: Added new HTTP transport implementation for MCP with AWS Lambda
- Native HTTP communication without stdio bridging
- Flexible authentication: Built-in custom auth supporting SigV4, OAuth, transitive auth, or enterprise-specific frameworks
- Real-time streaming support with Server-Sent Events (SSE)
- Context passing mechanism for HTTP request metadata
- Comprehensive error handling and retry logic
- Support for both stateful and stateless modes
- Complete examples and documentation

## [0.2.2](https://github.com/awslabs/run-model-context-protocol-servers-with-aws-lambda/compare/v0.2.1...v0.2.2) (2025-07-06)

### Features

Expand All @@ -22,7 +34,6 @@ All notable changes to this project will be documented in this file. See [commit
* Typescript integ test support for OAuth client ([1f7492f](https://github.com/awslabs/run-model-context-protocol-servers-with-aws-lambda/commit/1f7492f880910be26bbbf0ff10951bf599b476f9))
* Typescript-based cat-facts MCP server accessible behind Lambda function URL using streamable HTTP transport and Sigv4 ([4a6e83f](https://github.com/awslabs/run-model-context-protocol-servers-with-aws-lambda/commit/4a6e83f356063298ef3bf07b030e533633400150))


### Bug Fixes

* Actually initialize the automated oauth clients ([21e76cc](https://github.com/awslabs/run-model-context-protocol-servers-with-aws-lambda/commit/21e76cce398e787566fe4203b54d005238494b5c))
Expand Down
57 changes: 57 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ flowchart LR
- This package currently supports MCP servers and clients written in Python and Typescript.
Other languages such as Kotlin are not supported.
- The server adapters only adapt stdio MCP servers, not servers written for other protocols such as SSE.
- **NEW**: This package now includes a Streamable HTTP transport for MCP that supports real-time streaming
with Server-Sent Events (SSE) for stateless applications that need streaming notifications during request processing.
- The server adapters do not maintain any MCP server state across Lambda function invocations.
Only stateless MCP servers are a good fit for using this adapter. For example, MCP servers
that invoke stateless tools like the [time MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/time)
Expand Down Expand Up @@ -200,6 +202,61 @@ const transport = new LambdaFunctionClientTransport(serverParams);
await client.connect(transport);
```

### Streamable HTTP Transport Example

This project now includes a Streamable HTTP transport implementation that supports real-time streaming with Server-Sent Events (SSE). This is useful for applications that need to receive streaming notifications during MCP tool execution.

The [streamable HTTP example](examples/streamable-http/) demonstrates:

- **Server**: Express.js server with MCP streaming support
- **Client**: TypeScript client that handles real-time notifications
- **Tools**: Calculator tool and streaming counter tool with live notifications

#### Quick Start

```bash
cd examples/streamable-http
npm install
npm run dev:server # Start server on http://localhost:8080
npm run dev:client # Run client demo in another terminal
```

#### Server Usage

```typescript
import { createMCPServer } from './server/mcp-server-factory.js';
import { StreamableHTTPServerTransport } from '@aws/mcp-streamable-http-transport';

const mcpServer = createMCPServer();
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => undefined,
enableJsonResponse: false
});

await mcpServer.connect(transport);
```

#### Client Usage

```typescript
import { MCPStreamingClient } from './client/mcp-streaming-client.js';

const client = new MCPStreamingClient({
serverName: 'mcp-streaming-server',
serverVersion: '1.0.0',
endpoint: 'http://localhost:8080/mcp'
});

await client.connect();

// Execute streaming tool with real-time notifications
const result = await client.executeStreamingTool('count-with-notifications', {
maxCount: 5
});
```

The streaming client automatically handles real-time notifications and displays them as they arrive from the server.

### Deploy and run the examples

See the [development guide](DEVELOP.md) for instructions to deploy and run the examples in this repository.
Expand Down
164 changes: 164 additions & 0 deletions STREAMABLE_HTTP_TRANSPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Streamable HTTP Transport for MCP

This repository now includes a **Streamable HTTP Transport** implementation that provides an alternative to the stdio-based approach for running MCP servers in AWS Lambda.

## Why Streamable HTTP Transport?

The original stdio-based approach requires creating child processes inside Lambda functions and bridging stdio communication. The Streamable HTTP transport eliminates this complexity by implementing native HTTP communication.

### Architecture Comparison

#### Original Stdio Approach
```
[MCP Client] → [Lambda Invoke API] → [Lambda Function]
→ [stdio bridge] → [Child Process MCP Server]
→ [stdio response] → [Lambda Response] → [MCP Client]
```

#### New Streamable HTTP Approach
```
[MCP Client] → [HTTP POST with SigV4] → [HTTP Endpoint]
→ [StreamableHTTPServerTransport] → [MCP Tools with Context]
→ [SSE/JSON Response] → [MCP Client]
```

## Key Advantages

- Better performance: No child process overhead, faster cold starts
- Flexible authentication: Built-in custom auth supporting SigV4, OAuth, transitive auth, or enterprise-specific frameworks
- Real-time streaming: Server-Sent Events for notifications
- Context passing: Clean mechanism to pass HTTP request metadata to tools
- Cost effective: Direct Lambda Function URLs reduce latency and cost (though API Gateway can be added for additional features like rate limiting, caching, and request transformation)
- Comprehensive error handling, retry logic, session management

## Quick Start

### 1. Install the Transport

```bash
cd src/typescript-streamable-http
npm install
npm run build
```

### 2. Run the Examples

```bash
cd examples/streamable-http
npm install

# Start server
npm run dev:server

# In another terminal, start client
npm run dev:client
```

### 3. Deploy to AWS Lambda

The examples include complete deployment instructions for AWS Lambda with Function URLs.

## Implementation Highlights

### Server Side
```typescript
import { StreamableHTTPServerTransport, extractContextFiled } from './src/typescript-streamable-http';

const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => undefined, // Stateless for Lambda
enableJsonResponse: false // Use SSE streaming
});

// Extract context in MCP tools
const context = extractContextFiled<UserContext>(mcpServer, 'context');
```

### Client Side
```typescript
import { StreamableHTTPClientTransport } from './src/typescript-streamable-http';

const transport = new StreamableHTTPClientTransport(
new URL('https://your-function-url.lambda-url.us-west-2.on.aws/mcp'),
{ context: { userId: '123', role: 'admin' } }, // Pass context
'us-west-2',
'lambda'
);
```

## Documentation

- **[Transport Library README](src/typescript-streamable-http/README.md)** - Complete API documentation
- **[Examples README](examples/streamable-http/README.md)** - Step-by-step examples
- **[Server Example](examples/streamable-http/server-example.ts)** - Complete server implementation
- **[Client Example](examples/streamable-http/client-example.ts)** - Client with streaming support

## Comparison with Existing Approach

| Feature | Stdio Transport | Streamable HTTP Transport |
|---------|----------------|---------------------------|
| **Architecture** | Child process + stdio bridge | Native HTTP communication |
| **Cold Start** | Slower (process spawning) | Faster (direct HTTP) |
| **Memory Usage** | Higher (multiple processes) | Lower (single process) |
| **Context Passing** | Complex (environment variables) | Clean (HTTP headers) |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like an opinion here,

I think we can still present this comparison table as feature list rather than making is "vs" ,
Both stdio and http have their own pros and cons in different scenarios.

| **Streaming** | Limited | Full SSE support |
| **Error Handling** | Basic | Comprehensive with retry |
| **AWS Integration** | Manual invoke API | Native SigV4 + Function URLs |
| **Scalability** | Limited by process limits | HTTP connection pooling |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this limitation here.

| **Cost** | Higher (API Gateway often needed) | Lower (direct Function URLs) |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing APIG also brings additional work on client to manage its own throttling, WAF, phased launches.
I am not sure if this is a right comparison here.


## Migration Guide

### From Stdio to Streamable HTTP

1. **Replace transport imports**:
```typescript
// Old
import { stdioServerAdapter } from '@aws/run-mcp-servers-with-aws-lambda';

// New
import { StreamableHTTPServerTransport } from './src/typescript-streamable-http';
```

2. **Update server initialization**:
```typescript
// Old - stdio adapter in Lambda handler
export const handler = (event, context) => {
return stdioServerAdapter(serverParams, event, context);
};

// New - Express app with HTTP transport
const app = express();
const transport = new StreamableHTTPServerTransport({...});
app.all('/mcp', (req, res) => transport.handleRequest(req, res));
```

3. **Update client connection**:
```typescript
// Old - Lambda invoke transport
const transport = new LambdaFunctionClientTransport({...});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to call this LamdaFunctionClientTransport, can we make it more generic that works for non lambda endpoints also.


// New - HTTP transport
const transport = new StreamableHTTPClientTransport(url, options, region, service);
```

## Production Deployments

The Streamable HTTP transport is already being used in production environments with:
- **Multi-stage deployments** (alpha, beta, gamma, prod)
- **Multiple MCP servers** running as separate Lambda functions
- **Real-time streaming** for long-running operations
- **Context-aware tools** that access user and request data
- **Automatic retry and reconnection** for reliability

## Contributing

This transport implementation represents a significant improvement over the stdio approach and is ready for community adoption. The code is production-tested and includes comprehensive examples and documentation.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets avoid such wide comparison languages IMO.


## Next Steps

1. **Test the examples** locally
2. **Deploy to AWS Lambda** using the provided instructions
3. **Integrate into your MCP applications**
4. **Contribute improvements** back to the community

The Streamable HTTP transport makes MCP with AWS Lambda more performant, scalable, and developer-friendly while maintaining full protocol compatibility.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.2
0.3.0
Loading