From 50595e63cec66a52feb56e8a6795edb7caf2bb81 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Sat, 5 Sep 2026 09:09:54 +0200 Subject: [PATCH] fix(mcp): report the Python package version --- .sampo/changesets/somber-runesinger-tuonetar.md | 5 +++++ posthog/mcp/README.md | 8 ++++---- posthog/mcp/_lib_identity.py | 4 ++-- posthog/test/mcp/test_no_crash.py | 4 ++-- posthog/test/mcp/test_posthog_mcp.py | 16 ++++++++-------- 5 files changed, 21 insertions(+), 16 deletions(-) create mode 100644 .sampo/changesets/somber-runesinger-tuonetar.md diff --git a/.sampo/changesets/somber-runesinger-tuonetar.md b/.sampo/changesets/somber-runesinger-tuonetar.md new file mode 100644 index 000000000..8a4f93cc5 --- /dev/null +++ b/.sampo/changesets/somber-runesinger-tuonetar.md @@ -0,0 +1,5 @@ +--- +pypi/posthog: patch +--- + +Report the Python package version in MCP event metadata and request headers so SDK Health can assess the installed package. diff --git a/posthog/mcp/README.md b/posthog/mcp/README.md index 4ae3d5319..a8dcd1020 100644 --- a/posthog/mcp/README.md +++ b/posthog/mcp/README.md @@ -16,10 +16,10 @@ analytics = instrument(server, posthog) Install is just `pip install posthog`. `instrument()` needs the MCP SDK at runtime, but anyone wrapping a server already has it. -MCP analytics events report `$lib: "posthog-python-mcp"`. Because `$lib` is a -client-level identity, `instrument()` relabels every event sent by the client passed -to it. Use a client dedicated to MCP analytics if the application also captures -unrelated events. +MCP analytics events report `$lib: "posthog-python-mcp"` and the installed `posthog` package version in `$lib_version`. +Request headers use the same identity and package version, so SDK Health can compare MCP traffic with Python SDK releases. +Because `$lib` is a client-level identity, `instrument()` relabels every event sent by the client passed to it. +Use a client dedicated to MCP analytics if the application also captures unrelated events. ## Stateless / multi-pod servers diff --git a/posthog/mcp/_lib_identity.py b/posthog/mcp/_lib_identity.py index 0f83380b0..02bb11e57 100644 --- a/posthog/mcp/_lib_identity.py +++ b/posthog/mcp/_lib_identity.py @@ -3,13 +3,13 @@ from __future__ import annotations from ..client import Client +from ..version import VERSION from .constants import POSTHOG_MCP_LIB_NAME -from .version import __version__ def apply_mcp_lib_identity(client: Client) -> None: """Relabel every event sent by ``client`` as coming from ``posthog.mcp``.""" set_identity = getattr(client, "_set_library_identity", None) if set_identity is not None: - set_identity(POSTHOG_MCP_LIB_NAME, __version__) + set_identity(POSTHOG_MCP_LIB_NAME, VERSION) diff --git a/posthog/test/mcp/test_no_crash.py b/posthog/test/mcp/test_no_crash.py index 60701f2a9..ffe0f4a3d 100644 --- a/posthog/test/mcp/test_no_crash.py +++ b/posthog/test/mcp/test_no_crash.py @@ -11,8 +11,8 @@ from posthog.client import Client from posthog.mcp import instrument -from posthog.mcp.version import __version__ as MCP_VERSION from posthog.test.mcp._helpers import MCP_MAJOR, FakeClient +from posthog.version import VERSION async def test_unsupported_server_returns_noop_handle(): @@ -75,7 +75,7 @@ def before_send(event): client.capture("after instrumentation") assert captured[0]["properties"]["$lib"] == "posthog-python-mcp" - assert captured[0]["properties"]["$lib_version"] == MCP_VERSION + assert captured[0]["properties"]["$lib_version"] == VERSION @pytest.mark.parametrize( diff --git a/posthog/test/mcp/test_posthog_mcp.py b/posthog/test/mcp/test_posthog_mcp.py index 177c4e0ad..cf1456e95 100644 --- a/posthog/test/mcp/test_posthog_mcp.py +++ b/posthog/test/mcp/test_posthog_mcp.py @@ -4,11 +4,11 @@ from posthog.capture_mode import CaptureMode from posthog.mcp import PostHogMCP -from posthog.mcp.version import __version__ as MCP_VERSION from posthog.test.mcp._helpers import ( events_named as _events, flush_background as _flush, ) +from posthog.version import VERSION def make_client(): @@ -73,7 +73,7 @@ def before_send(event): assert {event["event"] for event in captured} == {"$mcp_tool_call", "$exception"} assert all( event["properties"]["$lib"] == "posthog-python-mcp" - and event["properties"]["$lib_version"] == MCP_VERSION + and event["properties"]["$lib_version"] == VERSION for event in captured ) @@ -86,7 +86,7 @@ def test_mcp_library_identity_reaches_capture_v0_header(): client.capture("$mcp_custom") assert post.call_args.kwargs["headers"]["User-Agent"] == ( - f"posthog-python-mcp/{MCP_VERSION}" + f"posthog-python-mcp/{VERSION}" ) @@ -95,10 +95,10 @@ def test_mcp_library_identity_reaches_capture_v1_header(): with mock.patch("posthog.client._send_v1_batch") as send: client.capture("$mcp_custom") - assert send.call_args.kwargs["sdk_info"] == f"posthog-python-mcp/{MCP_VERSION}" + assert send.call_args.kwargs["sdk_info"] == f"posthog-python-mcp/{VERSION}" event = send.call_args.args[2][0] assert event["properties"]["$lib"] == "posthog-python-mcp" - assert event["properties"]["$lib_version"] == MCP_VERSION + assert event["properties"]["$lib_version"] == VERSION def test_mcp_library_identity_reaches_feature_flag_requests(): @@ -112,7 +112,7 @@ def test_mcp_library_identity_reaches_feature_flag_requests(): client.evaluate_flags("user_1") assert post.call_args.kwargs["headers"]["User-Agent"] == ( - f"posthog-python-mcp/{MCP_VERSION}" + f"posthog-python-mcp/{VERSION}" ) @@ -130,7 +130,7 @@ def test_mcp_library_identity_reaches_feature_flag_definition_requests(): client.load_feature_flags() assert get.call_args.kwargs["headers"]["User-Agent"] == ( - f"posthog-python-mcp/{MCP_VERSION}" + f"posthog-python-mcp/{VERSION}" ) client.shutdown() @@ -144,7 +144,7 @@ def test_mcp_library_identity_reaches_remote_config_requests(): assert client.get_remote_config_payload("flag-key") == "payload" assert get.call_args.kwargs["headers"]["User-Agent"] == ( - f"posthog-python-mcp/{MCP_VERSION}" + f"posthog-python-mcp/{VERSION}" )