Module: PostHog::MCP
- Defined in:
- lib/posthog/mcp.rb,
lib/posthog/mcp/ids.rb,
lib/posthog/mcp/log.rb,
lib/posthog/mcp/sink.rb,
lib/posthog/mcp/tools.rb,
lib/posthog/mcp/client.rb,
lib/posthog/mcp/intent.rb,
lib/posthog/mcp/options.rb,
lib/posthog/mcp/session.rb,
lib/posthog/mcp/identity.rb,
lib/posthog/mcp/analytics.rb,
lib/posthog/mcp/constants.rb,
lib/posthog/mcp/exceptions.rb,
lib/posthog/mcp/truncation.rb,
lib/posthog/mcp/sanitization.rb,
lib/posthog/mcp/event_builder.rb,
lib/posthog/mcp/request_scope.rb,
lib/posthog/mcp/session_token.rb,
lib/posthog/mcp/tracking_data.rb,
lib/posthog/mcp/conversation_id.rb,
lib/posthog/mcp/instrumentation.rb,
lib/posthog/mcp/rack_middleware.rb,
lib/posthog/mcp/schema_mutation.rb,
lib/posthog/mcp/server_extension.rb
Overview
Experimental and not officially supported: no support is provided for this integration, and its API and the captured event schema may change in a minor release. A warning is logged when this file is required. Docs: https://posthog.com/docs/mcp-analytics
PostHog MCP analytics for servers built on the official Ruby mcp gem.
Wrap an MCP::Server so every tool call, handshake, listing, prompt,
resource read, and failure is captured to PostHog as a $mcp_* event.
Defined Under Namespace
Modules: Callbacks, ConversationId, Event, EventBuilder, EventType, Exceptions, Identity, Ids, Intent, Log, ModelCapture, Property, RequestScope, Sanitization, SchemaMutation, ServerExtension, Session, SessionToken, Tools, TransportExtension, TransportIdentity, Truncation Classes: Analytics, Client, ContextOptions, IdentityCache, Instrumentation, ModelOptions, NoopAnalytics, Options, PreparedToolCall, RackMiddleware, SessionTokenPayload, Sink, TrackingData, UserIdentity
Constant Summary collapse
- EXPERIMENTAL_NOTICE =
'PostHog::MCP is experimental and not officially supported: no support is provided for it, and its ' \ 'API and the captured $mcp_* event schema may change in a minor release. Docs: ' \ 'https://posthog.com/docs/mcp-analytics. Feedback welcome at https://github.com/PostHog/posthog-ruby/issues.'
- SOURCE =
Value of
$mcp_sourceon every primary$mcp_*event. 'posthog_mcp_analytics'- LIB_NAME =
$libstamped on MCP analytics events (per event, never on the client). 'posthog-ruby-mcp'- INACTIVITY_TIMEOUT_MINUTES =
Generated (in-memory) sessions roll over after this much inactivity.
30- MCP_SESSION_HEADER =
Header carrying the transport session id, and our self-encoded token.
'mcp-session-id'- DEFAULT_CONTEXT_PARAMETER_DESCRIPTION =
Description of the injected
contextargument. 'Explain in 15-25 words, in third person, why this tool is called and how it supports ' \ "the user's goal. For analytics only. You MUST describe only the abstract purpose of the " \ 'tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying ' \ 'information from the user request or tool results, including names, emails, phone numbers, ' \ 'IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", ' \ '"the customer", or "an account". Example: "Retrieving a customer\'s recent orders to ' \ 'investigate a billing issue and help support determine the appropriate resolution."'
- DEFAULT_MODEL_PARAMETER_DESCRIPTION =
Description of the injected
llm_modelargument. 'The exact model identifier you (the assistant) are running as, taken from your system ' \ 'prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you ' \ 'do not know your model identifier with certainty, pass "unknown" — never guess.'
- DEFAULT_CONVERSATION_ID_DESCRIPTION =
Description of the injected
conversation_idargument. "Echo the conversation_id from the server's previous response. The server provides it on " \ 'the first call — never invent one, and do not issue parallel tool calls until you have it.'
Class Method Summary collapse
-
.decode_session_id(value) ⇒ PostHog::MCP::SessionTokenPayload?
Decode an
Mcp-Session-Idvalue; nil for anything that is not one of our tokens. -
.derive_session_id_from_conversation(conversation_id) ⇒ String
Deterministic
$session_idfor an agent conversation handle. -
.derive_session_id_from_mcp_session(mcp_session_id) ⇒ String
Deterministic
$session_idfor a transport session id (stable across restarts). -
.encode_session_id(payload) ⇒ String
Encode a session token for a custom HTTP layer's
Mcp-Session-Idresponse header. - .experimental_notice!(options = nil) ⇒ Object private
-
.get_more_tools_result ⇒ Hash
The canned
get_more_toolsresult for custom dispatchers. -
.instrument(server, client = nil, options: nil, **kwargs) ⇒ PostHog::MCP::Analytics
Instrument an
MCP::Server. - .mcp_sdk_available? ⇒ Boolean private
- .reset_for_tests! ⇒ Object private
- .tracking_data(server) ⇒ PostHog::MCP::TrackingData? private
Class Method Details
.decode_session_id(value) ⇒ PostHog::MCP::SessionTokenPayload?
Decode an Mcp-Session-Id value; nil for anything that is not one of our tokens.
116 117 118 |
# File 'lib/posthog/mcp.rb', line 116 def decode_session_id(value) SessionToken.decode(value) end |
.derive_session_id_from_conversation(conversation_id) ⇒ String
Deterministic $session_id for an agent conversation handle.
130 131 132 |
# File 'lib/posthog/mcp.rb', line 130 def derive_session_id_from_conversation(conversation_id) Session.derive_session_id_from_conversation(conversation_id) end |
.derive_session_id_from_mcp_session(mcp_session_id) ⇒ String
Deterministic $session_id for a transport session id (stable across restarts).
123 124 125 |
# File 'lib/posthog/mcp.rb', line 123 def derive_session_id_from_mcp_session(mcp_session_id) Session.derive_session_id_from_mcp_session(mcp_session_id) end |
.encode_session_id(payload) ⇒ String
Encode a session token for a custom HTTP layer's Mcp-Session-Id response header.
109 110 111 |
# File 'lib/posthog/mcp.rb', line 109 def encode_session_id(payload) SessionToken.encode(payload) end |
.experimental_notice!(options = nil) ⇒ 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.
147 148 149 150 151 152 153 |
# File 'lib/posthog/mcp.rb', line 147 def experimental_notice!( = nil) Log.debug(, EXPERIMENTAL_NOTICE) return if @experimental_notice_shown @experimental_notice_shown = true Kernel.warn("[posthog-ruby] #{EXPERIMENTAL_NOTICE}") end |
.get_more_tools_result ⇒ Hash
The canned get_more_tools result for custom dispatchers.
137 138 139 |
# File 'lib/posthog/mcp.rb', line 137 def get_more_tools_result # rubocop:disable Naming/AccessorMethodName -- public API name Tools.result end |
.instrument(server, client = nil, options: nil, **kwargs) ⇒ PostHog::MCP::Analytics
Instrument an MCP::Server.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/posthog/mcp.rb', line 66 def instrument(server, client = nil, options: nil, **kwargs) opts = .is_a?(Options) ? : Options.new(**kwargs) ensure_mcp_sdk! experimental_notice!(opts) begin unless server.is_a?(::MCP::Server) raise TypeError, "Unsupported server type: #{server.class}. Pass an MCP::Server." end existing = tracking_data(server) if existing Log.debug(opts, 'instrument() - server already instrumented, skipping initialization') return Analytics.new(server) end resolved_client = resolve_client(client) Log.warn(opts, 'Warning: no PostHog client available; MCP events will not be sent.') if resolved_client.nil? sink = resolved_client ? Sink.new(resolved_client) : nil data = TrackingData.new(options: opts, sink: sink, server_name: safe_call(server, :name), server_version: safe_call(server, :version)) install_extensions! server.instance_variable_set(:@__posthog_mcp, data) register_missing_capability_tool(server, data) Analytics.new(server) rescue StandardError => e Log.warn(opts, "Warning: failed to instrument server - #{e.class}: #{e.}") NoopAnalytics.new end end |
.mcp_sdk_available? ⇒ 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.
142 143 144 |
# File 'lib/posthog/mcp.rb', line 142 def mcp_sdk_available? defined?(::MCP::Server) ? true : false end |
.reset_for_tests! ⇒ 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.
156 157 158 |
# File 'lib/posthog/mcp.rb', line 156 def reset_for_tests! @experimental_notice_shown = false end |
.tracking_data(server) ⇒ PostHog::MCP::TrackingData?
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.
99 100 101 102 103 |
# File 'lib/posthog/mcp.rb', line 99 def tracking_data(server) return nil unless server.instance_variable_defined?(:@__posthog_mcp) server.instance_variable_get(:@__posthog_mcp) end |