diff --git a/.sampo/changesets/mcp-interface-server-events.md b/.sampo/changesets/mcp-interface-server-events.md new file mode 100644 index 000000000..d057795ba --- /dev/null +++ b/.sampo/changesets/mcp-interface-server-events.md @@ -0,0 +1,5 @@ +--- +pypi/posthog: patch +--- + +Set `$mcp_interface` to `mcp` on events from MCP servers. diff --git a/posthog/mcp/_posthog_events.py b/posthog/mcp/_posthog_events.py index 90040011a..7113bd2cb 100644 --- a/posthog/mcp/_posthog_events.py +++ b/posthog/mcp/_posthog_events.py @@ -59,7 +59,10 @@ def build_posthog_capture_events( def _build_capture_event(event: Event) -> PostHogCaptureEvent: - properties: Dict[str, Any] = {_P.SOURCE: POSTHOG_MCP_ANALYTICS_SOURCE} + properties: Dict[str, Any] = { + _P.INTERFACE: "mcp", + _P.SOURCE: POSTHOG_MCP_ANALYTICS_SOURCE, + } _add_session_id(event, properties) _add_conversation_id(event, properties) _add_person_processing(event, properties) @@ -260,7 +263,7 @@ def _add_server_build(event: Event, properties: Dict[str, Any]) -> None: def _build_exception_event(event: Event) -> PostHogCaptureEvent: - properties: Dict[str, Any] = {} + properties: Dict[str, Any] = {_P.INTERFACE: "mcp"} _add_session_id(event, properties) _add_conversation_id(event, properties) _add_person_processing(event, properties) diff --git a/posthog/mcp/constants.py b/posthog/mcp/constants.py index ee8cf96ae..ab5dd363e 100644 --- a/posthog/mcp/constants.py +++ b/posthog/mcp/constants.py @@ -84,6 +84,7 @@ class PostHogMCPAnalyticsProperty: FEEDBACK_TASK_COMPLETED = "$mcp_feedback_task_completed" FEEDBACK_TOOL = "$mcp_feedback_tool" FEEDBACK_TYPE = "$mcp_feedback_type" + INTERFACE = "$mcp_interface" IS_ERROR = "$mcp_is_error" INTENT = "$mcp_intent" INTENT_SOURCE = "$mcp_intent_source" diff --git a/posthog/test/mcp/test_pipeline.py b/posthog/test/mcp/test_pipeline.py index 81b6db644..c3e39f2cf 100644 --- a/posthog/test/mcp/test_pipeline.py +++ b/posthog/test/mcp/test_pipeline.py @@ -885,6 +885,7 @@ def test_build_tool_call_event_properties(): props = capture["properties"] assert capture["event"] == PostHogMCPAnalyticsEvent.TOOL_CALL assert capture["distinct_id"] == "ses_abc" + assert props[PostHogMCPAnalyticsProperty.INTERFACE] == "mcp" assert props[PostHogMCPAnalyticsProperty.SOURCE] == POSTHOG_MCP_ANALYTICS_SOURCE assert props[PostHogMCPAnalyticsProperty.TOOL_NAME] == "search_events" assert props[PostHogMCPAnalyticsProperty.TOOL_CATEGORY] == "Logs" @@ -912,6 +913,7 @@ def test_protocol_version_on_primary_and_exception_events(): # Both the primary $mcp_tool_call and the $exception sibling carry it. assert len(captures) == 2 for capture in captures: + assert capture["properties"][PostHogMCPAnalyticsProperty.INTERFACE] == "mcp" assert ( capture["properties"][PostHogMCPAnalyticsProperty.PROTOCOL_VERSION] == "2025-06-18" diff --git a/references/public_api_snapshot.txt b/references/public_api_snapshot.txt index 51ee00d9d..3e2926e5a 100644 --- a/references/public_api_snapshot.txt +++ b/references/public_api_snapshot.txt @@ -909,6 +909,7 @@ attribute posthog.mcp.constants.PostHogMCPAnalyticsProperty.INPUT_ALIASES_USED = attribute posthog.mcp.constants.PostHogMCPAnalyticsProperty.INPUT_KEYS = '$mcp_input_keys' attribute posthog.mcp.constants.PostHogMCPAnalyticsProperty.INTENT = '$mcp_intent' attribute posthog.mcp.constants.PostHogMCPAnalyticsProperty.INTENT_SOURCE = '$mcp_intent_source' +attribute posthog.mcp.constants.PostHogMCPAnalyticsProperty.INTERFACE = '$mcp_interface' attribute posthog.mcp.constants.PostHogMCPAnalyticsProperty.IS_ERROR = '$mcp_is_error' attribute posthog.mcp.constants.PostHogMCPAnalyticsProperty.LISTED_TOOL_NAMES = '$mcp_listed_tool_names' attribute posthog.mcp.constants.PostHogMCPAnalyticsProperty.LLM_MODEL = '$mcp_llm_model'