@@ -18,15 +18,18 @@ import {
18
18
MCP_NOTIFICATION_CLIENT_TO_SERVER_OP_VALUE ,
19
19
MCP_NOTIFICATION_ORIGIN_VALUE ,
20
20
MCP_NOTIFICATION_SERVER_TO_CLIENT_OP_VALUE ,
21
+ MCP_PROMPT_NAME_ATTRIBUTE ,
21
22
MCP_REQUEST_ID_ATTRIBUTE ,
23
+ MCP_RESOURCE_URI_ATTRIBUTE ,
22
24
MCP_ROUTE_SOURCE_VALUE ,
23
25
MCP_SERVER_OP_VALUE ,
24
26
MCP_SESSION_ID_ATTRIBUTE ,
27
+ MCP_TOOL_NAME_ATTRIBUTE ,
25
28
MCP_TRANSPORT_ATTRIBUTE ,
26
29
NETWORK_PROTOCOL_VERSION_ATTRIBUTE ,
27
30
NETWORK_TRANSPORT_ATTRIBUTE ,
28
31
} from './attributes' ;
29
- import type { ExtraHandlerData , JsonRpcNotification , JsonRpcRequest , McpSpanConfig , MCPTransport } from './types' ;
32
+ import type { ExtraHandlerData , JsonRpcNotification , JsonRpcRequest , McpSpanConfig , MCPTransport , MethodConfig } from './types' ;
30
33
31
34
/** Validates if a message is a JSON-RPC request */
32
35
export function isJsonRpcRequest ( message : unknown ) : message is JsonRpcRequest {
@@ -68,65 +71,82 @@ export function validateMcpServerInstance(instance: unknown): boolean {
68
71
return false ;
69
72
}
70
73
74
+ /** Configuration for MCP methods to extract targets and arguments */
75
+ const METHOD_CONFIGS : Record < string , MethodConfig > = {
76
+ 'tools/call' : {
77
+ targetField : 'name' ,
78
+ targetAttribute : MCP_TOOL_NAME_ATTRIBUTE ,
79
+ captureArguments : true ,
80
+ argumentsField : 'arguments' ,
81
+ } ,
82
+ 'resources/read' : {
83
+ targetField : 'uri' ,
84
+ targetAttribute : MCP_RESOURCE_URI_ATTRIBUTE ,
85
+ captureUri : true ,
86
+ } ,
87
+ 'resources/subscribe' : {
88
+ targetField : 'uri' ,
89
+ targetAttribute : MCP_RESOURCE_URI_ATTRIBUTE ,
90
+ } ,
91
+ 'resources/unsubscribe' : {
92
+ targetField : 'uri' ,
93
+ targetAttribute : MCP_RESOURCE_URI_ATTRIBUTE ,
94
+ } ,
95
+ 'prompts/get' : {
96
+ targetField : 'name' ,
97
+ targetAttribute : MCP_PROMPT_NAME_ATTRIBUTE ,
98
+ captureName : true ,
99
+ captureArguments : true ,
100
+ argumentsField : 'arguments' ,
101
+ } ,
102
+ } ;
103
+
71
104
/** Extracts target info from method and params based on method type */
72
105
function extractTargetInfo ( method : string , params : Record < string , unknown > ) : {
73
106
target ?: string ;
74
107
attributes : Record < string , string >
75
108
} {
76
- let target : string | undefined ;
77
- let attributeKey : string | undefined ;
78
-
79
- switch ( method ) {
80
- case 'tools/call' :
81
- target = typeof params ?. name === 'string' ? params . name : undefined ;
82
- attributeKey = 'mcp.tool.name' ;
83
- break ;
84
- case 'resources/read' :
85
- case 'resources/subscribe' :
86
- case 'resources/unsubscribe' :
87
- target = typeof params ?. uri === 'string' ? params . uri : undefined ;
88
- attributeKey = 'mcp.resource.uri' ;
89
- break ;
90
- case 'prompts/get' :
91
- target = typeof params ?. name === 'string' ? params . name : undefined ;
92
- attributeKey = 'mcp.prompt.name' ;
93
- break ;
109
+ const config = METHOD_CONFIGS [ method as keyof typeof METHOD_CONFIGS ] ;
110
+ if ( ! config ) {
111
+ return { attributes : { } } ;
94
112
}
95
113
114
+ const target = config . targetField && typeof params ?. [ config . targetField ] === 'string'
115
+ ? params [ config . targetField ] as string
116
+ : undefined ;
117
+
96
118
return {
97
119
target,
98
- attributes : target && attributeKey ? { [ attributeKey ] : target } : { }
120
+ attributes : target && config . targetAttribute ? { [ config . targetAttribute ] : target } : { }
99
121
} ;
100
122
}
101
123
102
124
/** Extracts request arguments based on method type */
103
125
function getRequestArguments ( method : string , params : Record < string , unknown > ) : Record < string , string > {
104
126
const args : Record < string , string > = { } ;
127
+ const config = METHOD_CONFIGS [ method as keyof typeof METHOD_CONFIGS ] ;
128
+
129
+ if ( ! config ) {
130
+ return args ;
131
+ }
105
132
106
- // Argument capture for different methods
107
- switch ( method ) {
108
- case 'tools/call' :
109
- if ( params ?. arguments && typeof params . arguments === 'object' ) {
110
- for ( const [ key , value ] of Object . entries ( params . arguments as Record < string , unknown > ) ) {
111
- args [ `mcp.request.argument.${ key . toLowerCase ( ) } ` ] = JSON . stringify ( value ) ;
112
- }
133
+ // Capture arguments from the configured field
134
+ if ( config . captureArguments && config . argumentsField && params ?. [ config . argumentsField ] ) {
135
+ const argumentsObj = params [ config . argumentsField ] ;
136
+ if ( typeof argumentsObj === 'object' && argumentsObj !== null ) {
137
+ for ( const [ key , value ] of Object . entries ( argumentsObj as Record < string , unknown > ) ) {
138
+ args [ `mcp.request.argument.${ key . toLowerCase ( ) } ` ] = JSON . stringify ( value ) ;
113
139
}
114
- break ;
115
- case 'resources/read' :
116
- if ( params ?. uri ) {
117
- args [ 'mcp.request.argument.uri' ] = JSON . stringify ( params . uri ) ;
118
- }
119
- break ;
120
- case 'prompts/get' :
121
- if ( params ?. name ) {
122
- args [ 'mcp.request.argument.name' ] = JSON . stringify ( params . name ) ;
123
- }
124
- if ( params ?. arguments && typeof params . arguments === 'object' ) {
125
- for ( const [ key , value ] of Object . entries ( params . arguments as Record < string , unknown > ) ) {
126
- args [ `mcp.request.argument.${ key . toLowerCase ( ) } ` ] = JSON . stringify ( value ) ;
127
- }
128
- }
129
- break ;
140
+ }
141
+ }
142
+
143
+ // Capture specific fields as arguments
144
+ if ( config . captureUri && params ?. uri ) {
145
+ args [ 'mcp.request.argument.uri' ] = JSON . stringify ( params . uri ) ;
146
+ }
147
+
148
+ if ( config . captureName && params ?. name ) {
149
+ args [ 'mcp.request.argument.name' ] = JSON . stringify ( params . name ) ;
130
150
}
131
151
132
152
return args ;
0 commit comments