@@ -11,6 +11,7 @@ import {
11
11
isJsonRpcRequest ,
12
12
validateMcpServerInstance ,
13
13
} from './utils/mcp-server/utils' ;
14
+ import { fill } from './utils/object' ;
14
15
15
16
const wrappedMcpServerInstances = new WeakSet ( ) ;
16
17
@@ -31,75 +32,50 @@ export function wrapMcpServerWithSentry<S extends object>(mcpServerInstance: S):
31
32
32
33
const serverInstance = mcpServerInstance as MCPServerInstance ;
33
34
34
- // Wrap connect() to intercept AFTER Protocol sets up transport handlers
35
- const originalConnect = serverInstance . connect . bind ( serverInstance ) ;
36
- serverInstance . connect = new Proxy ( originalConnect , {
37
- async apply ( target , thisArg , argArray ) {
38
- const [ transport , ...restArgs ] = argArray as [ MCPTransport , ...unknown [ ] ] ;
35
+ fill ( serverInstance , 'connect' , ( originalConnect ) => {
36
+ return async function ( this : MCPServerInstance , transport : MCPTransport , ...restArgs : unknown [ ] ) {
37
+ const result = await originalConnect . call ( this , transport , ...restArgs ) ;
39
38
40
- // Call the original connect first to let Protocol set up its handlers
41
- const result = await Reflect . apply ( target , thisArg , [ transport , ...restArgs ] ) ;
42
-
43
- // Intercept incoming messages via onmessage
44
39
if ( transport . onmessage ) {
45
- const protocolOnMessage = transport . onmessage . bind ( transport ) ;
46
-
47
- transport . onmessage = new Proxy ( protocolOnMessage , {
48
- apply ( onMessageTarget , onMessageThisArg , onMessageArgs ) {
49
- const [ jsonRpcMessage , extra ] = onMessageArgs ;
50
-
51
- // Instrument both requests and notifications
40
+ fill ( transport , 'onmessage' , ( originalOnMessage ) => {
41
+ return function ( this : MCPTransport , jsonRpcMessage : unknown , extra ?: unknown ) {
52
42
if ( isJsonRpcRequest ( jsonRpcMessage ) ) {
53
- return createMcpServerSpan ( jsonRpcMessage , transport , extra as ExtraHandlerData , ( ) => {
54
- return Reflect . apply ( onMessageTarget , onMessageThisArg , onMessageArgs ) ;
43
+ return createMcpServerSpan ( jsonRpcMessage , this , extra as ExtraHandlerData , ( ) => {
44
+ return originalOnMessage . call ( this , jsonRpcMessage , extra ) ;
55
45
} ) ;
56
46
}
57
47
if ( isJsonRpcNotification ( jsonRpcMessage ) ) {
58
- return createMcpNotificationSpan ( jsonRpcMessage , transport , extra as ExtraHandlerData , ( ) => {
59
- return Reflect . apply ( onMessageTarget , onMessageThisArg , onMessageArgs ) ;
48
+ return createMcpNotificationSpan ( jsonRpcMessage , this , extra as ExtraHandlerData , ( ) => {
49
+ return originalOnMessage . call ( this , jsonRpcMessage , extra ) ;
60
50
} ) ;
61
51
}
62
-
63
- return Reflect . apply ( onMessageTarget , onMessageThisArg , onMessageArgs ) ;
64
- } ,
52
+ return originalOnMessage . call ( this , jsonRpcMessage , extra ) ;
53
+ } ;
65
54
} ) ;
66
55
}
67
56
68
- // Intercept outgoing messages via send
69
57
if ( transport . send ) {
70
- const originalSend = transport . send . bind ( transport ) ;
71
-
72
- transport . send = new Proxy ( originalSend , {
73
- async apply ( sendTarget , sendThisArg , sendArgs ) {
74
- const [ message ] = sendArgs ;
75
-
76
- // Instrument outgoing notifications (but not requests/responses)
58
+ fill ( transport , 'send' , ( originalSend ) => {
59
+ return async function ( this : MCPTransport , message : unknown ) {
77
60
if ( isJsonRpcNotification ( message ) ) {
78
- return createMcpOutgoingNotificationSpan ( message , transport , ( ) => {
79
- return Reflect . apply ( sendTarget , sendThisArg , sendArgs ) ;
61
+ return createMcpOutgoingNotificationSpan ( message , this , ( ) => {
62
+ return originalSend . call ( this , message ) ;
80
63
} ) ;
81
64
}
82
-
83
- return Reflect . apply ( sendTarget , sendThisArg , sendArgs ) ;
84
- } ,
65
+ return originalSend . call ( this , message ) ;
66
+ } ;
85
67
} ) ;
86
68
}
87
69
88
- // Handle transport lifecycle events
89
70
if ( transport . onclose ) {
90
- const originalOnClose = transport . onclose . bind ( transport ) ;
91
- transport . onclose = new Proxy ( originalOnClose , {
92
- apply ( onCloseTarget , onCloseThisArg , onCloseArgs ) {
93
- // TODO(bete): session and request correlation (methods at the bottom of this file)
94
- // if (transport.sessionId) {
95
- // handleTransportOnClose(transport.sessionId);
96
- // }
97
- return Reflect . apply ( onCloseTarget , onCloseThisArg , onCloseArgs ) ;
98
- } ,
71
+ fill ( transport , 'onclose' , ( originalOnClose ) => {
72
+ return function ( this : MCPTransport , ...args : unknown [ ] ) {
73
+ return originalOnClose . call ( this , ...args ) ;
74
+ } ;
99
75
} ) ;
100
76
}
101
77
return result ;
102
- } ,
78
+ } ;
103
79
} ) ;
104
80
105
81
wrappedMcpServerInstances . add ( mcpServerInstance ) ;
0 commit comments