Class: PostHog::MCP::RackMiddleware
- Inherits:
-
Object
- Object
- PostHog::MCP::RackMiddleware
- Defined in:
- lib/posthog/mcp/rack_middleware.rb
Overview
Experimental. PostHog::MCP is not officially supported; see the
docs at https://posthog.com/docs/mcp-analytics.
Rack middleware for stateless / multi-pod MCP servers built on a custom
Rack stack (not the mcp gem's Streamable HTTP transport, which
instrument wires automatically).
It publishes the request's headers to RequestScope, so an instrumented
MCP::Server dispatched anywhere below it sees the HTTP context the gem's
own transport would have given it, and it carries the Mcp-Session-Id
token minted at initialize back onto the response. Clients replay that
token on every request, so any pod recovers $session_id and the client
identity from the header alone.
Neither the request nor the response body is read here. The token comes
from whoever handled the request and already knows it succeeded: the
instrumented server, or - for a hand-rolled dispatcher built on
Client - a call to the mint hook this middleware exposes as
env['posthog_mcp.mint'].
The decoded token (replayed or freshly minted) is exposed to the app as
env['posthog_mcp.session'] (SessionTokenPayload).
Constant Summary collapse
- ENV_KEY =
'posthog_mcp.session'- MINT_ENV_KEY =
'posthog_mcp.mint'
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app) ⇒ RackMiddleware
constructor
A new instance of RackMiddleware.
Constructor Details
#initialize(app) ⇒ RackMiddleware
Returns a new instance of RackMiddleware.
40 41 42 |
# File 'lib/posthog/mcp/rack_middleware.rb', line 40 def initialize(app) @app = app end |
Instance Method Details
#call(env) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/posthog/mcp/rack_middleware.rb', line 44 def call(env) replayed = SessionToken.decode(SessionToken.read_header(MCP_SESSION_HEADER => env['HTTP_MCP_SESSION_ID'])) env[ENV_KEY] = replayed if replayed RequestScope.with(headers: RequestScope.headers_from_env(env), transport: :http) do |scope| env[MINT_ENV_KEY] = mint_hook(scope, env) unless replayed status, headers, body = @app.call(env) settle_token(scope[:mint], status, headers, env, replayed) [status, headers, body] ensure env.delete(MINT_ENV_KEY) end end |