Module: FastMcpPubsub::CurrentClient

Defined in:
lib/fast_mcp_pubsub/current_client.rb

Overview

Thread-local record of which SSE client the request being served belongs to.

FastMcp answers a JSON-RPC request over the client's SSE stream rather than in the POST body, and MCP::Server#send_response has no idea which stream that is. The transport does know: the client id arrives as a query parameter on the POST. Stashing it here for the length of the request is what lets the response be addressed instead of broadcast.

A thread local is the right scope because FastMcp handles the POST synchronously — handle_request calls send_response on the very thread that entered handle_message_request_with_server, so the value set on the way in is still there on the way out.

Constant Summary collapse

KEY =
:fast_mcp_pubsub_client_id

Class Method Summary collapse

Class Method Details

.idObject

The client id of the request being served, or nil outside one — which is what a genuine notification looks like, and those really are for everyone.



22
23
24
# File 'lib/fast_mcp_pubsub/current_client.rb', line 22

def id
  Thread.current[KEY]
end

.with(client_id) ⇒ Object

Runs the block with client_id in scope, restoring whatever was there before. Restoring rather than clearing keeps nesting honest; Puma reuses its threads, and a stale id left behind would address the next request's response to the previous request's client.



30
31
32
33
34
35
36
# File 'lib/fast_mcp_pubsub/current_client.rb', line 30

def with(client_id)
  previous = Thread.current[KEY]
  Thread.current[KEY] = client_id
  yield
ensure
  Thread.current[KEY] = previous
end