Skip to content

Commit 962760b

Browse files
committed
adding client and server attribute builders, updating span completion logic for initialize requests, and improving session data handling
1 parent 0f929fd commit 962760b

File tree

3 files changed

+82
-8
lines changed

3 files changed

+82
-8
lines changed

packages/core/src/integrations/mcp-server/correlation.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import { getClient } from '../../currentScopes';
1010
import { SPAN_STATUS_ERROR } from '../../tracing';
1111
import type { Span } from '../../types-hoist/span';
12+
import { MCP_PROTOCOL_VERSION_ATTRIBUTE } from './attributes';
1213
import { filterMcpPiiFromSpanData } from './piiFiltering';
1314
import { extractPromptResultAttributes, extractToolResultAttributes } from './resultExtraction';
15+
import { buildServerAttributesFromInfo, extractSessionDataFromInitializeResponse } from './sessionExtraction';
1416
import type { MCPTransport, RequestId, RequestSpanMapValue } from './types';
1517

1618
/**
@@ -51,18 +53,30 @@ export function storeSpanForRequest(transport: MCPTransport, requestId: RequestI
5153
}
5254

5355
/**
54-
* Completes span with tool results and cleans up correlation
56+
* Completes span with results and cleans up correlation
5557
* @param transport - MCP transport instance
5658
* @param requestId - Request identifier
57-
* @param result - Tool execution result for attribute extraction
59+
* @param result - Execution result for attribute extraction
5860
*/
5961
export function completeSpanWithResults(transport: MCPTransport, requestId: RequestId, result: unknown): void {
6062
const spanMap = getOrCreateSpanMap(transport);
6163
const spanData = spanMap.get(requestId);
6264
if (spanData) {
6365
const { span, method } = spanData;
6466

65-
if (method === 'tools/call') {
67+
if (method === 'initialize') {
68+
const sessionData = extractSessionDataFromInitializeResponse(result);
69+
const serverAttributes = buildServerAttributesFromInfo(sessionData.serverInfo);
70+
71+
const initAttributes: Record<string, string | number> = {
72+
...serverAttributes,
73+
};
74+
if (sessionData.protocolVersion) {
75+
initAttributes[MCP_PROTOCOL_VERSION_ATTRIBUTE] = sessionData.protocolVersion;
76+
}
77+
78+
span.setAttributes(initAttributes);
79+
} else if (method === 'tools/call') {
6680
const rawToolAttributes = extractToolResultAttributes(result);
6781
const client = getClient();
6882
const sendDefaultPii = Boolean(client?.getOptions().sendDefaultPii);

packages/core/src/integrations/mcp-server/sessionExtraction.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,27 @@ export function getClientAttributes(transport: MCPTransport): Record<string, str
105105
return attributes;
106106
}
107107

108+
/**
109+
* Build client attributes from PartyInfo directly
110+
* @param clientInfo - Client party info
111+
* @returns Client attributes for span instrumentation
112+
*/
113+
export function buildClientAttributesFromInfo(clientInfo?: PartyInfo): Record<string, string> {
114+
const attributes: Record<string, string> = {};
115+
116+
if (clientInfo?.name) {
117+
attributes['mcp.client.name'] = clientInfo.name;
118+
}
119+
if (clientInfo?.title) {
120+
attributes['mcp.client.title'] = clientInfo.title;
121+
}
122+
if (clientInfo?.version) {
123+
attributes['mcp.client.version'] = clientInfo.version;
124+
}
125+
126+
return attributes;
127+
}
128+
108129
/**
109130
* Build server attributes from stored server info
110131
* @param transport - MCP transport instance
@@ -127,6 +148,27 @@ export function getServerAttributes(transport: MCPTransport): Record<string, str
127148
return attributes;
128149
}
129150

151+
/**
152+
* Build server attributes from PartyInfo directly
153+
* @param serverInfo - Server party info
154+
* @returns Server attributes for span instrumentation
155+
*/
156+
export function buildServerAttributesFromInfo(serverInfo?: PartyInfo): Record<string, string> {
157+
const attributes: Record<string, string> = {};
158+
159+
if (serverInfo?.name) {
160+
attributes[MCP_SERVER_NAME_ATTRIBUTE] = serverInfo.name;
161+
}
162+
if (serverInfo?.title) {
163+
attributes[MCP_SERVER_TITLE_ATTRIBUTE] = serverInfo.title;
164+
}
165+
if (serverInfo?.version) {
166+
attributes[MCP_SERVER_VERSION_ATTRIBUTE] = serverInfo.version;
167+
}
168+
169+
return attributes;
170+
}
171+
130172
/**
131173
* Extracts client connection info from extra handler data
132174
* @param extra - Extra handler data containing connection info

packages/core/src/integrations/mcp-server/transport.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,21 @@
88
import { getIsolationScope, withIsolationScope } from '../../currentScopes';
99
import { startInactiveSpan, withActiveSpan } from '../../tracing';
1010
import { fill } from '../../utils/object';
11+
import { MCP_PROTOCOL_VERSION_ATTRIBUTE } from './attributes';
1112
import { cleanupPendingSpansForTransport, completeSpanWithResults, storeSpanForRequest } from './correlation';
1213
import { captureError } from './errorCapture';
13-
import { extractSessionDataFromInitializeRequest, extractSessionDataFromInitializeResponse } from './sessionExtraction';
14+
import {
15+
buildClientAttributesFromInfo,
16+
extractSessionDataFromInitializeRequest,
17+
extractSessionDataFromInitializeResponse,
18+
} from './sessionExtraction';
1419
import {
1520
cleanupSessionDataForTransport,
1621
storeSessionDataForTransport,
1722
updateSessionDataForTransport,
1823
} from './sessionManagement';
1924
import { buildMcpServerSpanConfig, createMcpNotificationSpan, createMcpOutgoingNotificationSpan } from './spans';
20-
import type { ExtraHandlerData, MCPTransport } from './types';
25+
import type { ExtraHandlerData, MCPTransport, SessionData } from './types';
2126
import { isJsonRpcNotification, isJsonRpcRequest, isJsonRpcResponse, isValidContentItem } from './validation';
2227

2328
/**
@@ -31,10 +36,13 @@ export function wrapTransportOnMessage(transport: MCPTransport): void {
3136
fill(transport, 'onmessage', originalOnMessage => {
3237
return function (this: MCPTransport, message: unknown, extra?: unknown) {
3338
if (isJsonRpcRequest(message)) {
34-
if (message.method === 'initialize') {
39+
const isInitialize = message.method === 'initialize';
40+
let initSessionData: SessionData | undefined;
41+
42+
if (isInitialize) {
3543
try {
36-
const sessionData = extractSessionDataFromInitializeRequest(message);
37-
storeSessionDataForTransport(this, sessionData);
44+
initSessionData = extractSessionDataFromInitializeRequest(message);
45+
storeSessionDataForTransport(this, initSessionData);
3846
} catch {
3947
// noop
4048
}
@@ -46,6 +54,16 @@ export function wrapTransportOnMessage(transport: MCPTransport): void {
4654
const spanConfig = buildMcpServerSpanConfig(message, this, extra as ExtraHandlerData);
4755
const span = startInactiveSpan(spanConfig);
4856

57+
// For initialize requests, add client info directly to span (works even for stateless transports)
58+
if (isInitialize && initSessionData) {
59+
span.setAttributes({
60+
...buildClientAttributesFromInfo(initSessionData.clientInfo),
61+
...(initSessionData.protocolVersion && {
62+
[MCP_PROTOCOL_VERSION_ATTRIBUTE]: initSessionData.protocolVersion,
63+
}),
64+
});
65+
}
66+
4967
storeSpanForRequest(this, message.id, span, message.method);
5068

5169
return withActiveSpan(span, () => {

0 commit comments

Comments
 (0)