Skip to content

Make StreamableHTTPTransport a Rack application#263

Merged
koic merged 1 commit intomodelcontextprotocol:mainfrom
koic:make_streamable_http_transport_a_standard_rack_app
Apr 15, 2026
Merged

Make StreamableHTTPTransport a Rack application#263
koic merged 1 commit intomodelcontextprotocol:mainfrom
koic:make_streamable_http_transport_a_standard_rack_app

Conversation

@koic
Copy link
Copy Markdown
Member

@koic koic commented Mar 18, 2026

Motivation and Context

Add call(env) to StreamableHTTPTransport, making it a Rack application that works with mount, run, and Rack middleware.

Refactor examples to use Rack middleware classes for MCP logging instead of proc wrappers, demonstrating idiomatic Rack composition with the new run(transport) pattern.

Update README.md with mount and controller integration patterns.

Closes #59, #60

How Has This Been Tested?

Added tests for call(env) as a Rack app. All tests pass.

Breaking Change

No breaking changes. All existing APIs are preserved:

  • StreamableHTTPTransport.new(server) continues to work as before.
  • handle_request(request) is unchanged. The new call(env) is a purely additive public method.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

@koic koic force-pushed the make_streamable_http_transport_a_standard_rack_app branch 2 times, most recently from 06f5b81 to 361288f Compare March 18, 2026 19:06
@koic koic changed the title Make StreamableHTTPTransport a standard Rack application Make StreamableHTTPTransport a Rack application Mar 18, 2026
@koic koic force-pushed the make_streamable_http_transport_a_standard_rack_app branch 5 times, most recently from 0912d7d to f4961a8 Compare March 22, 2026 14:53
@koic koic force-pushed the make_streamable_http_transport_a_standard_rack_app branch 2 times, most recently from 880daa9 to 40767ff Compare April 5, 2026 10:14
@koic koic force-pushed the make_streamable_http_transport_a_standard_rack_app branch from 40767ff to 11f3534 Compare April 5, 2026 18:29
koic added a commit that referenced this pull request Apr 7, 2026
The following two points have been updated:

## 1. Use ActionController::API in README controller example

`ActionController::Base` includes CSRF protection which rejects POST requests
without an authenticity token. MCP clients do not send CSRF tokens,
so the controller example should inherit from `ActionController::API` instead.

## 2. Use `stateless: true` for `StreamableHTTPTransport.new`

The controller creates a new transport per request,
so the session stored on the previous transport is lost.
Without `stateless: true`, the second request with `Mcp-Session-Id`
returns 404 because the new transport has an empty session map.

To share sessions via `Mcp-Session-Id` across requests, there are two approaches.
One is persisting the transport in a class variable. The other is mounting
the transport as a Rack app via #263.

Both approaches maintain sessions, so features that depend on `server_context`
within the SDK (Progress, Sampling) work correctly. However, per-request
user-specific context such as `server_context: { user_id: current_user.id }`
cannot be passed since the server is shared across all requests.
## Motivation and Context

Add `call(env)` to `StreamableHTTPTransport`, making it a Rack application
that works with `mount`, `run`, and Rack middleware.

Refactor examples to use Rack middleware classes for MCP logging instead of proc wrappers,
demonstrating idiomatic Rack composition with the new `run(transport)` pattern.

Update README.md with mount and controller integration patterns.

Closes modelcontextprotocol#59, modelcontextprotocol#60

## How Has This Been Tested?

Added tests for `call(env)` as a Rack app. All tests pass.

## Breaking Change

No breaking changes. All existing APIs are preserved:

- `StreamableHTTPTransport.new(server)` continues to work as before.
- `handle_request(request)` is unchanged. The new `call(env)` is a purely additive public method.
@koic koic force-pushed the make_streamable_http_transport_a_standard_rack_app branch from 11f3534 to af99a30 Compare April 9, 2026 19:55
@koic
Copy link
Copy Markdown
Member Author

koic commented Apr 14, 2026

@modelcontextprotocol/ruby-sdk In practice, when using stateful Streamable HTTP with Mcp-Session-Id in Rails, functionality like this is necessary.

It would be possible to provide a separate Rack app API that wraps StreamableHTTPTransport. However, this PR takes a simpler approach by making StreamableHTTPTransport Rack-compatible.

If this can be merged, it should lower the barrier to implementing servers with the MCP Ruby SDK.

A review would be appreciated when convenient.

Copy link
Copy Markdown
Member

@jonathanhefner jonathanhefner left a comment

Choose a reason for hiding this comment

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

Vibe-reviewed. Claude says: "This is a well-scoped, well-tested PR. The core change is a 3-line method that follows a standard Ruby pattern (Rack app interface). The frozen-headers fix addresses a real bug. The example refactoring to proper middleware classes is more idiomatic. The README additions clearly explain both integration patterns."

@koic koic merged commit 66d0722 into modelcontextprotocol:main Apr 15, 2026
11 checks passed
@koic koic deleted the make_streamable_http_transport_a_standard_rack_app branch April 15, 2026 02:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

conventional drop-in Rack MCP servers with StreamableHTTP transport

2 participants