@@ -32,6 +32,9 @@ import {
32
32
ServerRequest ,
33
33
ServerResult ,
34
34
SUPPORTED_PROTOCOL_VERSIONS ,
35
+ LoggingLevel ,
36
+ SetLevelRequestSchema ,
37
+ LoggingLevelSchema
35
38
} from "../types.js" ;
36
39
import Ajv from "ajv" ;
37
40
@@ -108,8 +111,36 @@ export class Server<
108
111
this . setNotificationHandler ( InitializedNotificationSchema , ( ) =>
109
112
this . oninitialized ?.( ) ,
110
113
) ;
114
+
115
+ if ( this . _capabilities . logging ) {
116
+ this . setRequestHandler ( SetLevelRequestSchema , async ( request , extra ) => {
117
+ const transportSessionId : string | undefined = extra . sessionId || extra . requestInfo ?. headers [ 'mcp-session-id' ] as string || undefined ;
118
+ const { level } = request . params ;
119
+ const parseResult = LoggingLevelSchema . safeParse ( level ) ;
120
+ if ( transportSessionId && parseResult . success ) {
121
+ this . _loggingLevels . set ( transportSessionId , parseResult . data ) ;
122
+ }
123
+ return { } ;
124
+ } )
125
+ }
111
126
}
112
127
128
+ // Map log levels by session id
129
+ private _loggingLevels = new Map < string , LoggingLevel > ( ) ;
130
+
131
+ // Map LogLevelSchema to severity index
132
+ private readonly LOG_LEVEL_SEVERITY = new Map (
133
+ LoggingLevelSchema . options . map ( ( level , index ) => [ level , index ] )
134
+ ) ;
135
+
136
+ // Is a message with the given level ignored in the log level set for the given session id?
137
+ private isMessageIgnored = ( level : LoggingLevel , sessionId : string ) : boolean => {
138
+ const currentLevel = this . _loggingLevels . get ( sessionId ) ;
139
+ return ( currentLevel )
140
+ ? this . LOG_LEVEL_SEVERITY . get ( level ) ! < this . LOG_LEVEL_SEVERITY . get ( currentLevel ) !
141
+ : false ;
142
+ } ;
143
+
113
144
/**
114
145
* Registers new capabilities. This can only be called before connecting to a transport.
115
146
*
@@ -121,7 +152,6 @@ export class Server<
121
152
"Cannot register capabilities after connecting to transport" ,
122
153
) ;
123
154
}
124
-
125
155
this . _capabilities = mergeCapabilities ( this . _capabilities , capabilities ) ;
126
156
}
127
157
@@ -324,10 +354,10 @@ export class Server<
324
354
if ( result . action === "accept" && result . content ) {
325
355
try {
326
356
const ajv = new Ajv ( ) ;
327
-
357
+
328
358
const validate = ajv . compile ( params . requestedSchema ) ;
329
359
const isValid = validate ( result . content ) ;
330
-
360
+
331
361
if ( ! isValid ) {
332
362
throw new McpError (
333
363
ErrorCode . InvalidParams ,
@@ -359,8 +389,19 @@ export class Server<
359
389
) ;
360
390
}
361
391
362
- async sendLoggingMessage ( params : LoggingMessageNotification [ "params" ] ) {
363
- return this . notification ( { method : "notifications/message" , params } ) ;
392
+ /**
393
+ * Sends a logging message to the client, if connected.
394
+ * Note: You only need to send the parameters object, not the entire JSON RPC message
395
+ * @see LoggingMessageNotification
396
+ * @param params
397
+ * @param sessionId optional for stateless and backward compatibility
398
+ */
399
+ async sendLoggingMessage ( params : LoggingMessageNotification [ "params" ] , sessionId ?: string ) {
400
+ if ( this . _capabilities . logging ) {
401
+ if ( ! sessionId || ! this . isMessageIgnored ( params . level , sessionId ) ) {
402
+ return this . notification ( { method : "notifications/message" , params} )
403
+ }
404
+ }
364
405
}
365
406
366
407
async sendResourceUpdated ( params : ResourceUpdatedNotification [ "params" ] ) {
0 commit comments