Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Comments

CTX7-971: Client Metrics#1305

Merged
enesgules merged 17 commits intomasterfrom
CTX7-971-v2
Jan 2, 2026
Merged

CTX7-971: Client Metrics#1305
enesgules merged 17 commits intomasterfrom
CTX7-971-v2

Conversation

@fahreddinozcan
Copy link
Contributor

@fahreddinozcan fahreddinozcan commented Dec 26, 2025

Summary by CodeRabbit

  • New Features

    • Added HTTP health check endpoint.
    • Enhanced client context/telemetry to include IDE and version, propagated through requests.
    • Improved HTTP session handling (randomized session IDs) and clientInfo caching for downstream calls.
  • Bug Fixes

    • Better JSON-RPC 2.0 error responses and more robust contextual error handling.
    • Improved telemetry/cache maintenance (probabilistic cleanup) to reduce stale entries.

✏️ Tip: You can customize this high-level summary in your review settings.

@linear
Copy link

linear bot commented Dec 26, 2025

CTX7-971 MCP Analytics

@coderabbitai
Copy link

coderabbitai bot commented Dec 26, 2025

📝 Walkthrough

Walkthrough

Introduces client telemetry and richer context propagation: a ClientContext object (clientInfo, clientIp, apiKey, transport), clientInfo caching with TTL and probabilistic cleanup, API key hashing, HTTP /ping and 404 handling, and updated library search/docs APIs to accept and forward the unified context.

Changes

Cohort / File(s) Summary
Telemetry & Request Context
packages/mcp/src/index.ts
Added SERVER_VERSION, RequestContextData (includes clientInfo), clientInfo cache (keying, TTL, cleanup), hashApiKey, sessionId generation for HTTP transport, extractClientInfoFromBody, probabilistic cache cleanup, HTTP server with /ping and 404 handling, and extended requestContext.run to include clientInfo.
ClientContext & API surface
packages/mcp/src/lib/api.ts
Added exported ClientContext interface and transport field. Updated searchLibraries and fetchLibraryDocumentation to accept ClientContext, enriched request headers with Server-Version, Client-IDE/Client-Version, transport and source, and updated error handling to use context.apiKey.
Integration points / handlers
packages/mcp/src/...
Propagated clientInfo through HTTP and stdio flows, updated tool handlers and downstream calls to include the richer context object instead of separate apiKey/clientIp arguments.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant HTTPServer as HTTP Server
    participant Cache as Client Info Cache
    participant LibraryAPI as Library Search/Docs API

    Client->>HTTPServer: POST /mcp (body includes clientInfo, apiKey, sessionId)
    HTTPServer->>HTTPServer: extractClientInfoFromBody()
    HTTPServer->>HTTPServer: gen cacheKey (sessionId / apiKey hash / clientIp)
    HTTPServer->>Cache: lookup(cacheKey)
    alt cache hit
        Cache-->>HTTPServer: clientInfo
    else cache miss
        HTTPServer-->>Cache: store(clientInfo, TTL)
    end
    HTTPServer->>HTTPServer: hashApiKey(apiKey)
    HTTPServer->>HTTPServer: build ClientContext (clientIp, apiKey, clientInfo, transport)
    HTTPServer->>LibraryAPI: searchLibraries / fetchLibraryDocumentation (ClientContext)
    LibraryAPI->>LibraryAPI: build headers (Server-Version, Client-IDE, Client-Version, Transport)
    LibraryAPI-->>HTTPServer: response
    HTTPServer-->>Client: MCP response
    Note over Cache,HTTPServer: probabilistic cache cleanup may run during request handling
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I cached the client info with care,
I hashed the keys so none would despair.
Headers hop along each networked track,
Ping replies and 404s keep us on track.
A little rabbit cheers: context carried everywhere!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'CTX7-971: Client Metrics' is vague and generic, using non-descriptive terms that don't convey the specific nature of the changes made in the pull request. Consider using a more descriptive title that captures the main change, such as 'Add client telemetry and context propagation enhancements' or 'Implement client info caching and HTTP transport context enrichment'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch CTX7-971-v2

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/mcp/src/index.ts (1)

13-15: LGTM!

Crypto imports are appropriate for the hashing and UUID generation functionality.

(SERVER_VERSION duplication already noted in api.ts review)

🧹 Nitpick comments (3)
packages/mcp/src/lib/api.ts (2)

7-7: SERVER_VERSION is duplicated across files.

This constant is also defined in packages/mcp/src/index.ts (line 15). Having duplicate version constants risks them drifting apart during updates. Consider exporting from a single source (e.g., a shared constants file or package.json).


153-171: Extract header construction to a shared helper.

The header construction logic (generating clientId, merging baseHeaders, adding conditional X-Context7-* headers) is duplicated nearly verbatim in fetchLibraryDocumentation (lines 224-242). Extract this to a helper function to reduce duplication and ensure consistency.

🔎 Proposed helper function
function buildTelemetryHeaders(context: ClientContext): Record<string, string> {
  const clientId = generateClientId(context);
  const baseHeaders = generateHeaders(context.clientIp, context.apiKey);

  const headers: Record<string, string> = {
    ...baseHeaders,
    "X-Context7-Source": "mcp-server",
    "X-Context7-Server-Version": SERVER_VERSION,
    "X-Context7-Client-Id": clientId,
  };

  if (context.clientInfo?.ide) {
    headers["X-Context7-Client-IDE"] = context.clientInfo.ide;
  }
  if (context.clientInfo?.version) {
    headers["X-Context7-Client-Version"] = context.clientInfo.version;
  }
  if (context.transport) {
    headers["X-Context7-Transport"] = context.transport;
  }

  return headers;
}

Then in both functions:

-    const clientId = generateClientId(context);
-    const baseHeaders = generateHeaders(context.clientIp, context.apiKey);
-
-    const headers: Record<string, string> = {
-      ...baseHeaders,
-      "X-Context7-Source": "mcp-server",
-      "X-Context7-Server-Version": SERVER_VERSION,
-      "X-Context7-Client-Id": clientId,
-    };
-
-    if (context.clientInfo?.ide) {
-      headers["X-Context7-Client-IDE"] = context.clientInfo.ide;
-    }
-    if (context.clientInfo?.version) {
-      headers["X-Context7-Client-Version"] = context.clientInfo.version;
-    }
-    if (context.transport) {
-      headers["X-Context7-Transport"] = context.transport;
-    }
+    const headers = buildTelemetryHeaders(context);
packages/mcp/src/index.ts (1)

83-84: Consider adding a size limit to the cache.

The clientInfoCache has no maximum size, which could lead to unbounded memory growth in high-traffic HTTP scenarios. Consider either:

  1. Adding a maximum entry limit with LRU eviction
  2. Using a size-bounded cache library

The 1% probabilistic cleanup (line 433) only removes expired entries, not excess entries.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2701b5d and 06995b0.

📒 Files selected for processing (2)
  • packages/mcp/src/index.ts
  • packages/mcp/src/lib/api.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/mcp/src/lib/api.ts (2)
packages/mcp/src/lib/types.ts (1)
  • SearchResponse (16-19)
packages/mcp/src/lib/encryption.ts (1)
  • generateHeaders (34-47)
packages/mcp/src/index.ts (3)
packages/mcp/src/lib/types.ts (1)
  • SearchResponse (16-19)
packages/mcp/src/lib/api.ts (1)
  • searchLibraries (145-189)
packages/sdk/src/http/index.ts (1)
  • request (124-186)
🪛 GitHub Actions: Test
packages/mcp/src/index.ts

[error] 123-123: Prettier formatting issue. Delete (prettier/prettier)

🔇 Additional comments (13)
packages/mcp/src/lib/api.ts (5)

9-20: LGTM!

The ClientContext interface is well-structured with appropriate optional fields for telemetry. The type constraints on transport are appropriately restrictive.


22-30: LGTM!

The lazy initialization pattern for stdio session ID is correct. The session persists for the process lifetime as intended for stdio mode.


32-50: Approve with minor observation.

The client ID generation logic is sound with proper privacy-preserving hashing. Note that similar API key hashing logic exists in index.ts (hashApiKey function at line 119). Consider extracting a shared utility if more hashing use cases emerge.


173-188: LGTM!

Error handling is comprehensive with proper use of context.apiKey for contextual error messages.


199-208: LGTM!

The function signature and default parameter handling are well-designed, maintaining backward compatibility with the empty object default.

packages/mcp/src/index.ts (8)

69-76: LGTM!

The RequestContextData interface extension is consistent with the ClientContext.clientInfo type in api.ts.


161-176: LGTM with minor note.

Good approach to capture client version from MCP SDK during initialization. The null check on ctx (line 170) correctly handles the case where this may be called outside an active request context.


208-218: LGTM!

Correct context propagation with appropriate fallback chain for clientInfo.


296-314: LGTM!

Consistent context propagation pattern matching the resolve-library-id handler.


394-411: LGTM!

The function correctly extracts client info from MCP initialize requests with appropriate null checks and type guards.


413-449: LGTM!

The client info caching logic correctly handles the initialize/subsequent request pattern. The cache key priority and TTL refresh on access are well-designed for session continuity.


433-435: LGTM!

Probabilistic cleanup is a reasonable approach to amortize the cleanup cost across requests.


496-506: LGTM!

Stdio mode correctly initializes with API key from CLI/env, and client info is populated via the oninitialized handler when the client connects.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/mcp/src/lib/api.ts (1)

124-178: Add missing transport header in fetchLibraryDocumentation.

The searchLibraries function includes a conditional X-Context7-Transport header (lines 106-108) for telemetry, but fetchLibraryDocumentation omits it. Add the same block after the version header check to maintain consistency and ensure complete backend telemetry:

if (context.transport) {
  headers["X-Context7-Transport"] = context.transport;
}
♻️ Duplicate comments (1)
packages/mcp/src/index.ts (1)

119-121: Address the Prettier formatting issue.

A past review flagged a formatting error after this function (reported at line 123). Ensure there's only a single newline after the closing brace and run Prettier to resolve the issue.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06995b0 and b73da6e.

📒 Files selected for processing (2)
  • packages/mcp/src/index.ts
  • packages/mcp/src/lib/api.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/mcp/src/index.ts (3)
packages/mcp/src/lib/types.ts (1)
  • SearchResponse (16-19)
packages/mcp/src/lib/api.ts (1)
  • searchLibraries (85-122)
packages/sdk/src/http/index.ts (1)
  • request (124-186)
packages/mcp/src/lib/api.ts (2)
packages/mcp/src/lib/types.ts (2)
  • SearchResponse (16-19)
  • DocumentationMode (32-32)
packages/mcp/src/lib/encryption.ts (1)
  • generateHeaders (34-47)
🔇 Additional comments (11)
packages/mcp/src/lib/api.ts (2)

11-19: LGTM: Well-structured context interface.

The ClientContext interface provides a clean, unified way to propagate telemetry and authentication data. Optional fields are appropriate for flexibility across different transport modes.


85-122: LGTM: Context-based header enrichment implemented correctly.

The refactored searchLibraries function properly extracts telemetry fields from the ClientContext and conditionally populates headers. Error handling correctly uses context.apiKey for tailored messaging.

packages/mcp/src/index.ts (9)

13-13: LGTM: Appropriate crypto imports.

The addition of createHash and randomUUID supports the new API key hashing and session ID generation features.


69-76: LGTM: Context data structure properly extended.

The RequestContextData interface now includes clientInfo, maintaining consistency with the ClientContext interface in api.ts.


83-113: LGTM: Sensible clientInfo caching with TTL.

The caching strategy is well-designed:

  • 30-minute TTL balances freshness and cache hit rate
  • Key priority (session → hashed API key → IP) is logical
  • Probabilistic cleanup (1% per request, see line 432) avoids blocking overhead

160-175: Verify globalClientInfo handling in concurrent scenarios.

Setting globalClientInfo in the oninitialized handler creates shared state. In HTTP mode with concurrent requests from different clients, verify that:

  1. Each request's requestContext correctly isolates per-client info
  2. globalClientInfo only serves as a fallback (confirmed in tool handlers at lines 210, 298)

The current implementation appears correct (context takes precedence), but ensure this behavior is intentional.


207-216: LGTM: Tool handler properly propagates clientInfo.

The handler correctly retrieves clientInfo with fallback logic and passes it to searchLibraries via the new ClientContext parameter.


295-313: LGTM: Consistent clientInfo propagation in docs handler.

The docs tool handler follows the same fallback pattern and properly forwards clientInfo to fetchLibraryDocumentation.


393-410: LGTM: Safe clientInfo extraction from MCP initialize.

The function correctly parses the MCP initialize request structure and safely extracts client metadata. Type guards and null checks are appropriate.


412-459: LGTM: Robust HTTP transport with caching and context propagation.

The HTTP handler effectively:

  • Extracts and caches clientInfo per session/API key/IP
  • Updates cache timestamps on hits (line 428)
  • Triggers probabilistic cleanup (line 432-434)
  • Uses secure randomUUID() for session IDs (line 437)
  • Properly isolates each request via requestContext.run

461-471: LGTM: Useful HTTP endpoints added.

The /ping health-check endpoint and informative 404 handler improve operational visibility and developer experience.

Resolved conflicts by integrating 2.0.0 API changes with simplified context handling:
- Updated searchLibraries to use new query+libraryName params with ClientContext
- Updated fetchLibraryContext (new in 2.0.0) with ClientContext support
- Kept getClientContext() helper for simplified tool handler context passing
- All tool handlers now use getClientContext() for cleaner code
enesgules and others added 6 commits January 2, 2026 12:09
…ion in workflows

Moved SERVER_VERSION constant from index.ts to lib/constants.ts for better organization. Updated GitHub workflows to inject version into the new location during ECR deployment and release processes.
@enesgules enesgules merged commit 368b143 into master Jan 2, 2026
3 checks passed
@enesgules enesgules deleted the CTX7-971-v2 branch January 2, 2026 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants