Class: PostHog::MCP::Instrumentation Private
- Inherits:
-
Object
- Object
- PostHog::MCP::Instrumentation
- Defined in:
- lib/posthog/mcp/instrumentation.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
One JSON-RPC request's analytics lifecycle. Created by ServerExtension
around the dispatch lambda MCP::Server#handle_request returns, so it
sees the raw request, the params Hash the handler will receive (and may
strip injected arguments from it), the session, the result, and any
raised error. Everything it needs travels through its own instance
variables; nothing is read from the gem's @instrumentation_data.
Analytics failures are logged and swallowed: the handler's result or exception is always returned or re-raised unchanged.
Constant Summary collapse
- TRACKED_METHODS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
{ 'initialize' => :initialize, 'tools/list' => :tools_list, 'tools/call' => :tools_call, 'prompts/get' => :prompts_get, 'prompts/list' => :prompts_list, 'resources/read' => :resources_read, 'resources/list' => :resources_list }.freeze
- GENERIC_EVENT_TYPES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
{ prompts_get: EventType::MCP_PROMPTS_GET, prompts_list: EventType::MCP_PROMPTS_LIST, resources_read: EventType::MCP_RESOURCES_READ, resources_list: EventType::MCP_RESOURCES_LIST }.freeze
- MODERN_PROTOCOL_REVISION =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'2026-07-28'- REVISION_SHAPE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
/\A\d{4}-\d{2}-\d{2}\z/- DRAFT_REVISION =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'draft'- META_CLIENT_INFO_KEY =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'io.modelcontextprotocol/clientInfo'- META_PROTOCOL_VERSION_KEY =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'io.modelcontextprotocol/protocolVersion'- INJECTED_PARAMS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
['context', ConversationId::PARAM_NAME, ModelCapture::PARAM_NAME].freeze
- UNRESOLVED_ACTOR =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Passed as
actor:by a caller that has no request identity to offer, and is distinct from an explicitnil(a request that resolved to nobody). Object.new.freeze
Class Method Summary collapse
-
.capture_event(data, input, actor: UNRESOLVED_ACTOR) ⇒ Object
private
Enrich an event with session/identity/server metadata and hand it to the sink.
- .legacy_era?(protocol_version) ⇒ Boolean private
- .monotonic_now ⇒ Object private
- .tracked?(method) ⇒ Boolean private
Instance Method Summary collapse
-
#dispatch(&handler) ⇒ Object
private
Runs the wrapped handler and records the request.
-
#initialize(server, data, method:, request:, params:, session: nil, request_id: nil) ⇒ Instrumentation
constructor
private
A new instance of Instrumentation.
Constructor Details
#initialize(server, data, method:, request:, params:, session: nil, request_id: nil) ⇒ Instrumentation
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Instrumentation.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/posthog/mcp/instrumentation.rb', line 93 def initialize(server, data, method:, request:, params:, session: nil, request_id: nil) @server = server @data = data @options = data. @kind = TRACKED_METHODS.fetch(method) @method = method @request = request.is_a?(Hash) ? request : {} @params = params.is_a?(Hash) ? params : {} @session = session @request_id = request_id @scope = RequestScope.current @headers = @scope ? (@scope[:headers] || {}) : {} @token = SessionToken.decode(header_session_id) @data.http_transport_seen = true if http? @identified_in_request = {} end |
Class Method Details
.capture_event(data, input, actor: UNRESOLVED_ACTOR) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Enrich an event with session/identity/server metadata and hand it to the sink.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/posthog/mcp/instrumentation.rb', line 57 def capture_event(data, input, actor: UNRESOLVED_ACTOR) sink = data.sink return nil if sink.nil? session_id = input['session_id'] || data.session_id actor = (session_id ? data.identified_sessions.get(session_id) : nil) if actor.equal?(UNRESOLVED_ACTOR) = input['timestamp'] || Time.now.utc duration = input['duration'] duration = (Time.now - ) * 1000.0 if duration.nil? && input['timestamp'] full = input.merge( 'session_id' => session_id, 'event_type' => input['event_type'] || EventType::CUSTOM, 'timestamp' => , 'duration' => duration, 'server_name' => data.server_name, 'server_version' => data.server_version, 'identify_actor_given_id' => actor&.distinct_id, 'identify_actor_data' => actor ? (actor.properties || {}) : {}, 'groups' => actor&.groups ) sink.capture(full, data.) end |
.legacy_era?(protocol_version) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
85 86 87 88 89 90 |
# File 'lib/posthog/mcp/instrumentation.rb', line 85 def legacy_era?(protocol_version) return true unless protocol_version.is_a?(String) && !protocol_version.empty? return false if protocol_version == DRAFT_REVISION !(REVISION_SHAPE.match?(protocol_version) && protocol_version >= MODERN_PROTOCOL_REVISION) end |
.monotonic_now ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
81 82 83 |
# File 'lib/posthog/mcp/instrumentation.rb', line 81 def monotonic_now Process.clock_gettime(Process::CLOCK_MONOTONIC) end |
.tracked?(method) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
46 47 48 |
# File 'lib/posthog/mcp/instrumentation.rb', line 46 def tracked?(method) TRACKED_METHODS.key?(method) end |
Instance Method Details
#dispatch(&handler) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Runs the wrapped handler and records the request.
111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/posthog/mcp/instrumentation.rb', line 111 def dispatch(&handler) @start = self.class.monotonic_now return dispatch_kind(&handler) if @scope # Only the Streamable HTTP transport publishes a scope. Opening one for # every other transport too (stdio, a custom dispatcher) means the session # settled before the tool body runs is the one {Analytics#capture} reads # inside it, whatever the request is anchored on. RequestScope.with(headers: {}, transport: :other) do |scope| @scope = scope dispatch_kind(&handler) end end |