Skip to content

feat(mcp): add client identity to tool spans#2700

Merged
kodiakhq[bot] merged 2 commits into
mainfrom
brandon/brandon-mcp-attributes
Jul 21, 2026
Merged

feat(mcp): add client identity to tool spans#2700
kodiakhq[bot] merged 2 commits into
mainfrom
brandon/brandon-mcp-attributes

Conversation

@brandon-pereira

@brandon-pereira brandon-pereira commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

MCP tool spans now identify the calling client application and version, making MCP traffic segmentable by clients such as Claude Code, OpenCode, and Cursor. Because the HTTP endpoint is stateless, identity is derived from a bounded first-product token in each request's User-Agent rather than relying on initialization state. Missing or malformed headers safely omit the attributes, and client values remain telemetry-only.

Screenshot 2026-07-21 at 12 28 59 PM Screenshot 2026-07-21 at 12 28 41 PM

Test Plan

  • yarn ci:unit src/mcp
  • yarn tsc --noEmit
  • Live MCP calls verified mcp.client.name=opencode and mcp.client.version=1.18.0 on mcp.tool.* spans

@github-actions

Copy link
Copy Markdown
Contributor

🔵 Tier 2 — Low Risk

Small, isolated change with no API route or data model modifications.

Why this tier:

  • Standard feature/fix — introduces new logic or modifies core functionality

Review process: AI review + quick human skim (target: 5–15 min). Reviewer validates AI assessment and checks for domain-specific concerns.
SLA: Resolve within 4 business hours.

Stats
  • Production files changed: 4
  • Production lines changed: 46 (+ 134 in test files, excluded from tier calculation)
  • Branch: brandon/brandon-mcp-attributes
  • Author: brandon-pereira

To override this classification, remove the review/tier-2 label and apply a different review/tier-* label. Manual overrides are preserved on subsequent pushes.

@github-actions github-actions Bot added the review/tier-2 Low risk — AI review + quick human skim label Jul 21, 2026
@changeset-bot

changeset-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e071959

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/api Patch
@hyperdx/app Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview, Comment Jul 21, 2026 8:20pm
hyperdx-storybook Ready Ready Preview, Comment Jul 21, 2026 8:20pm

Request Review

@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds MCP client identity to tool tracing. The main changes are:

  • Parses the first User-Agent product into a bounded client name and version.
  • Carries client identity through the MCP request context.
  • Adds client name and version attributes to MCP tool spans when available.
  • Adds unit coverage for parsing and tracing behavior.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
packages/api/src/mcp/utils/mcpClient.ts Adds bounded parsing for MCP client name and version from User-Agent.
packages/api/src/mcp/app.ts Adds parsed client identity to the per-request MCP context.
packages/api/src/mcp/utils/tracing.ts Adds optional client identity fields to MCP tool span attributes and logs.
packages/api/src/mcp/tools/types.ts Extends McpContext with optional MCP client identity.
packages/api/src/mcp/tests/mcpClient.test.ts Adds parser tests for known clients, missing headers, malformed values, and bounds.
packages/api/src/mcp/tests/tracing.test.ts Adds tests for client span attributes and missing client identity.

Reviews (2): Last reviewed commit: "Merge branch 'main' into brandon/brandon..." | Re-trigger Greptile

Comment thread packages/api/src/mcp/utils/mcpClient.ts
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

E2E Test Results

All tests passed • 243 passed • 1 skipped • 1035s

Status Count
✅ Passed 243
❌ Failed 0
⚠️ Flaky 0
⏭️ Skipped 1

Tests ran across 4 shards in parallel.

View full report →

@brandon-pereira
brandon-pereira requested review from a team and pulpdrew and removed request for a team July 21, 2026 19:05
@github-actions

Copy link
Copy Markdown
Contributor

Deep Review

No critical issues found. This is a small, fully additive telemetry change: a bounded User-Agent parser (userAgentClientInfo) feeds an optional mcpClient field on McpContext, and withToolTracing conditionally sets mcp.client.name / mcp.client.version span attributes. The user-controlled User-Agent value is verified telemetry-only — it reaches span attributes and structured-log fields, never a query, command, filesystem path, or HTML sink. Auth (validateUserAccessKey) runs before the parser, both fields are capped at 32 chars, and client name/version are deliberately kept out of metric labels (only tool and error_category are used), so there is no cardinality-explosion or injection path. The parser is total over its string | undefined input — every empty/whitespace/slash-only case is guarded before any .slice, so it cannot throw.

No P2-level findings survive re-grading.

🔵 P3 nitpicks (2)
  • packages/api/src/mcp/utils/mcpClient.ts:24 — The branch where a separator is present but the version segment is empty (input like cursor/, which correctly yields version: undefined) is never exercised by a test; only the no-separator falsy-version path (node) is covered.
    • Fix: Add a table case asserting userAgentClientInfo('cursor/') returns { name: 'cursor', version: undefined }.
    • correctness, testing
  • packages/api/src/mcp/app.ts:46 — The req.get('User-Agent')McpContext.mcpClient wiring has no test; the parser and the tracing consumer are each tested in isolation, so a wrong header name or a dropped assignment on this glue line would not be caught.
    • Fix: Add a lightweight route/unit test asserting the context passed to createServer carries mcpClient derived from the request User-Agent header.

Reviewers (4): correctness, security, testing, maintainability.

Testing gaps:

  • packages/api/src/mcp/utils/mcpClient.ts:24 — trailing-slash / empty-version negative case not covered.
  • packages/api/src/mcp/app.ts:46req.get('User-Agent')McpContext.mcpClient wiring is untested (no app.test.ts).

Environment note: bash, network, and grep/glob tooling were unavailable in this run (sandbox init failure), so the review was performed against the full working-tree contents of the changed files via the Read tool rather than a line-level git diff. The change is a single additive commit and its full import graph was traced; findings above reflect the current file state.

@kodiakhq
kodiakhq Bot merged commit 641175d into main Jul 21, 2026
27 checks passed
@kodiakhq
kodiakhq Bot deleted the brandon/brandon-mcp-attributes branch July 21, 2026 20:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automerge review/tier-2 Low risk — AI review + quick human skim

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants