Skip to content

Commit 683587c

Browse files
robbie-cclaude
andauthored
feat(mcp): Track report_user_action from MCP separately if it's from the wizard (#49196)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 05ad94b commit 683587c

File tree

6 files changed

+24
-4
lines changed

6 files changed

+24
-4
lines changed

posthog/event_usage.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,16 @@ class EventSource(StrEnum):
265265
POSTHOG_AI = "posthog_ai"
266266
TERRAFORM = "terraform"
267267
MCP = "mcp"
268+
WIZARD = "wizard"
268269

269270

270271
def get_event_source(request) -> EventSource:
271272
"""Determine the source of an API request for analytics."""
272273
user_agent = request.META.get("HTTP_USER_AGENT", "")
273274
if "posthog/terraform-provider" in user_agent:
274275
return EventSource.TERRAFORM
276+
if "posthog/wizard" in user_agent:
277+
return EventSource.WIZARD
275278
if "posthog/mcp-server" in user_agent:
276279
return EventSource.MCP
277280
if isinstance(getattr(request, "successful_authenticator", None), SessionAuthentication):

services/mcp/src/api/client.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { z } from 'zod'
22

3-
import { USER_AGENT } from '@/lib/constants'
3+
import { getUserAgent } from '@/lib/constants'
44
import { ErrorCode } from '@/lib/errors'
55
import { getSearchParamsFromRecord } from '@/lib/utils.js'
66
import {
@@ -125,6 +125,7 @@ export type Result<T, E = Error> = { success: true; data: T } | { success: false
125125
export interface ApiConfig {
126126
apiToken: string
127127
baseUrl: string
128+
clientIdentifier?: string | undefined
128129
}
129130

130131
type Endpoint = Record<string, any>
@@ -154,7 +155,7 @@ export class ApiClient {
154155
// TODO: should we move rate limiting from `fetchWithSchema` to here?
155156
const defaultHeaders: HeadersInit = {
156157
Authorization: `Bearer ${this.config.apiToken}`,
157-
'User-Agent': USER_AGENT,
158+
'User-Agent': getUserAgent(this.config.clientIdentifier),
158159
}
159160
if (options?.body) {
160161
defaultHeaders['Content-Type'] = 'application/json'

services/mcp/src/api/fetcher.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { USER_AGENT } from '@/lib/constants'
1+
import { getUserAgent } from '@/lib/constants'
22

33
import type { ApiConfig } from './client'
44
import type { createApiClient } from './generated'
@@ -18,7 +18,7 @@ export const buildApiFetcher: (config: ApiConfig) => Parameters<typeof createApi
1818

1919
const headers = new Headers()
2020
headers.set('Authorization', `Bearer ${config.apiToken}`)
21-
headers.set('User-Agent', USER_AGENT)
21+
headers.set('User-Agent', getUserAgent(config.clientIdentifier))
2222

2323
// Handle query parameters
2424
if (input.urlSearchParams) {

services/mcp/src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,19 @@ const handleRequest = async (
202202
request.headers.get('x-posthog-organization-id') || url.searchParams.get('organization_id') || undefined
203203
const projectId = request.headers.get('x-posthog-project-id') || url.searchParams.get('project_id') || undefined
204204

205+
// Extract posthog/foo identifier from the client's User-Agent (e.g. "posthog/wizard")
206+
// so we can forward it in outgoing API requests for source attribution
207+
const clientUserAgent = request.headers.get('User-Agent') || ''
208+
const clientIdentifierMatch = clientUserAgent.match(/posthog\/([\w-]+)/)
209+
const clientIdentifier = clientIdentifierMatch ? clientIdentifierMatch[0] : undefined
210+
205211
Object.assign(ctx.props, {
206212
apiToken: token,
207213
userHash: hash(token),
208214
sessionId: sessionId || undefined,
209215
organizationId,
210216
projectId,
217+
clientIdentifier,
211218
})
212219

213220
// Search params are used to build up the list of available tools. If no features are provided, all tools are available.

services/mcp/src/lib/constants.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ import packageJson from '../../package.json'
66

77
export const USER_AGENT = `posthog/mcp-server; version: ${packageJson.version}`
88

9+
export function getUserAgent(clientIdentifier?: string): string {
10+
if (clientIdentifier) {
11+
return `${USER_AGENT}; for ${clientIdentifier}`
12+
}
13+
return USER_AGENT
14+
}
15+
916
// Region-specific PostHog API base URLs
1017
export const POSTHOG_US_BASE_URL = 'https://us.posthog.com'
1118
export const POSTHOG_EU_BASE_URL = 'https://eu.posthog.com'

services/mcp/src/mcp.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export type RequestProperties = {
4141
version?: number
4242
organizationId?: string
4343
projectId?: string
44+
clientIdentifier?: string
4445
}
4546

4647
export class MCP extends McpAgent<Env> {
@@ -137,6 +138,7 @@ export class MCP extends McpAgent<Env> {
137138
this._api = new ApiClient({
138139
apiToken: this.requestProperties.apiToken,
139140
baseUrl,
141+
clientIdentifier: this.requestProperties.clientIdentifier,
140142
})
141143
}
142144

0 commit comments

Comments
 (0)