@@ -104,7 +104,7 @@ type sessionTestClientWithLogging struct {
104104	sessionID            string 
105105	notificationChannel  chan  mcp.JSONRPCNotification 
106106	initialized          bool 
107- 	loggingLevel  		 atomic.Value 
107+ 	loggingLevel          atomic.Value 
108108}
109109
110110func  (f  * sessionTestClientWithLogging ) SessionID () string  {
@@ -136,9 +136,9 @@ func (f *sessionTestClientWithLogging) GetLogLevel() mcp.LoggingLevel {
136136
137137// Verify that all implementations satisfy their respective interfaces 
138138var  (
139- 	_  ClientSession  			 =  (* sessionTestClient )(nil )
140- 	_  SessionWithTools  			 =  (* sessionTestClientWithTools )(nil )
141- 	_  SessionWithLogging 		 =  (* sessionTestClientWithLogging )(nil )
139+ 	_  ClientSession        =  (* sessionTestClient )(nil )
140+ 	_  SessionWithTools     =  (* sessionTestClientWithTools )(nil )
141+ 	_  SessionWithLogging   =  (* sessionTestClientWithLogging )(nil )
142142)
143143
144144func  TestSessionWithTools_Integration (t  * testing.T ) {
@@ -1039,6 +1039,187 @@ func TestMCPServer_SetLevel(t *testing.T) {
10391039
10401040	// Check logging level 
10411041	if  session .GetLogLevel () !=  mcp .LoggingLevelCritical  {
1042- 		t .Errorf ("Expected critical level, got %v " , session .GetLogLevel ())
1042+ 		t .Errorf ("Expected critical level, got %s " , session .GetLogLevel ())
10431043	}
1044- }
1044+ }
1045+ 
1046+ func  TestMCPServer_SendLogMessageToClientDisabled (t  * testing.T ) {
1047+ 	// Create server without logging capability 
1048+ 	server  :=  NewMCPServer ("test-server" , "1.0.0" )
1049+ 
1050+ 	// Create and initialize a session 
1051+ 	sessionChan  :=  make (chan  mcp.JSONRPCNotification , 10 )
1052+ 	session  :=  & sessionTestClientWithLogging {
1053+ 		sessionID :           "session-1" ,
1054+ 		notificationChannel : sessionChan ,
1055+ 	}
1056+ 	session .Initialize ()
1057+ 
1058+ 	// Mock a request context 
1059+ 	ctx  :=  server .WithContext (context .Background (), session )
1060+ 
1061+ 	// Try to send a log message to client when capability is disabled 
1062+ 	require .Error (t , server .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevelCritical , "test logger" , "test data" )))
1063+ }
1064+ 
1065+ func  TestMCPServer_SendLogMessageToClient (t  * testing.T ) {
1066+ 	// Prepare a log message 
1067+ 	logMsg  :=  mcp .NewLoggingMessageNotification (
1068+ 		mcp .LoggingLevelAlert ,
1069+ 		"test logger" ,
1070+ 		"test data" ,
1071+ 	)
1072+ 
1073+ 	tests  :=  []struct  {
1074+ 		name            string 
1075+ 		contextPrepare  func (context.Context , * MCPServer ) context.Context 
1076+ 		validate        func (* testing.T , context.Context , * MCPServer )
1077+ 	}{
1078+ 		{
1079+ 			name : "no active session" ,
1080+ 			contextPrepare : func (ctx  context.Context , srv  * MCPServer ) context.Context  {
1081+ 				return  ctx 
1082+ 			},
1083+ 			validate : func (t  * testing.T , ctx  context.Context , srv  * MCPServer ) {
1084+ 				require .Error (t , srv .SendLogMessageToClient (ctx , logMsg ))
1085+ 			},
1086+ 		},
1087+ 		{
1088+ 			name : "uninit session" ,
1089+ 			contextPrepare : func (ctx  context.Context , srv  * MCPServer ) context.Context  {
1090+ 				logSession  :=  & sessionTestClientWithLogging {
1091+ 					sessionID :           "test" ,
1092+ 					notificationChannel : make (chan  mcp.JSONRPCNotification , 10 ),
1093+ 					initialized :         false ,
1094+ 				}
1095+ 				return  srv .WithContext (ctx , logSession )
1096+ 			},
1097+ 			validate : func (t  * testing.T , ctx  context.Context , srv  * MCPServer ) {
1098+ 				require .Error (t , srv .SendLogMessageToClient (ctx , logMsg ))
1099+ 				_ , ok  :=  ClientSessionFromContext (ctx ).(* sessionTestClientWithLogging )
1100+ 				require .True (t , ok , "session not found or of incorrect type" )
1101+ 			},
1102+ 		},
1103+ 		{
1104+ 			name : "session not supports logging" ,
1105+ 			contextPrepare : func (ctx  context.Context , srv  * MCPServer ) context.Context  {
1106+ 				logSession  :=  & sessionTestClientWithTools {
1107+ 					sessionID :           "test" ,
1108+ 					notificationChannel : make (chan  mcp.JSONRPCNotification , 10 ),
1109+ 					initialized :         false ,
1110+ 				}
1111+ 				return  srv .WithContext (ctx , logSession )
1112+ 			},
1113+ 			validate : func (t  * testing.T , ctx  context.Context , srv  * MCPServer ) {
1114+ 				require .Error (t , srv .SendLogMessageToClient (ctx , logMsg ))
1115+ 			},
1116+ 		},
1117+ 		{
1118+ 			name : "invalid log messages without level or data" ,
1119+ 			contextPrepare : func (ctx  context.Context , srv  * MCPServer ) context.Context  {
1120+ 				logSession  :=  & sessionTestClientWithLogging {
1121+ 					sessionID :           "test" ,
1122+ 					notificationChannel : make (chan  mcp.JSONRPCNotification , 10 ),
1123+ 					initialized :         false ,
1124+ 				}
1125+ 				logSession .Initialize ()
1126+ 				return  srv .WithContext (ctx , logSession )
1127+ 			},
1128+ 			validate : func (t  * testing.T , ctx  context.Context , srv  * MCPServer ) {
1129+ 				// Invalid message without level 
1130+ 				require .Error (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification ("" , "test logger" , "test data" )))
1131+ 				// Invalid message with illegal level 
1132+ 				require .Error (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevel ("invalid level" ), "test logger" , "test data" )))
1133+ 				// Invalid message without data 
1134+ 				require .Error (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevelCritical , "test logger" , nil )))
1135+ 			},
1136+ 		},
1137+ 		{
1138+ 			name : "active session" ,
1139+ 			contextPrepare : func (ctx  context.Context , srv  * MCPServer ) context.Context  {
1140+ 				logSession  :=  & sessionTestClientWithLogging {
1141+ 					sessionID :           "test" ,
1142+ 					notificationChannel : make (chan  mcp.JSONRPCNotification , 10 ),
1143+ 					initialized :         false ,
1144+ 				}
1145+ 				logSession .Initialize ()
1146+ 				return  srv .WithContext (ctx , logSession )
1147+ 			},
1148+ 			validate : func (t  * testing.T , ctx  context.Context , srv  * MCPServer ) {
1149+ 				for  range  10  {
1150+ 					require .NoError (t , srv .SendLogMessageToClient (ctx , logMsg ))
1151+ 				}
1152+ 				session , ok  :=  ClientSessionFromContext (ctx ).(* sessionTestClientWithLogging )
1153+ 				require .True (t , ok , "session not found or of incorrect type" )
1154+ 				for  range  10  {
1155+ 					select  {
1156+ 					case  msg  :=  <- session .notificationChannel :
1157+ 						assert .Equal (t , string (mcp .MethodNotificationMessage ), msg .Method )
1158+ 						assert .Equal (t , mcp .LoggingLevelAlert , msg .Params .AdditionalFields ["level" ])
1159+ 						assert .Equal (t , "test logger" , msg .Params .AdditionalFields ["logger" ])
1160+ 						assert .Equal (t , "test data" , msg .Params .AdditionalFields ["data" ])
1161+ 					default :
1162+ 						t .Errorf ("log message not sent" )
1163+ 					}
1164+ 				}
1165+ 			},
1166+ 		},
1167+ 		{
1168+ 			name : "session with blocked channel" ,
1169+ 			contextPrepare : func (ctx  context.Context , srv  * MCPServer ) context.Context  {
1170+ 				logSession  :=  & sessionTestClientWithLogging {
1171+ 					sessionID :           "test" ,
1172+ 					notificationChannel : make (chan  mcp.JSONRPCNotification , 1 ),
1173+ 					initialized :         false ,
1174+ 				}
1175+ 				logSession .Initialize ()
1176+ 				return  srv .WithContext (ctx , logSession )
1177+ 			},
1178+ 			validate : func (t  * testing.T , ctx  context.Context , srv  * MCPServer ) {
1179+ 				require .NoError (t , srv .SendLogMessageToClient (ctx , logMsg ))
1180+ 				require .Error (t , srv .SendLogMessageToClient (ctx , logMsg ))
1181+ 			},
1182+ 		},
1183+ 		{
1184+ 			name : "send log messages of different levels" ,
1185+ 			contextPrepare : func (ctx  context.Context , srv  * MCPServer ) context.Context  {
1186+ 				logSession  :=  & sessionTestClientWithLogging {
1187+ 					sessionID :           "test" ,
1188+ 					notificationChannel : make (chan  mcp.JSONRPCNotification , 10 ),
1189+ 					initialized :         false ,
1190+ 				}
1191+ 				logSession .Initialize ()
1192+ 				// Set client log level to "Error" 
1193+ 				logSession .SetLogLevel (mcp .LoggingLevelError )
1194+ 				return  srv .WithContext (ctx , logSession )
1195+ 			},
1196+ 			validate : func (t  * testing.T , ctx  context.Context , srv  * MCPServer ) {
1197+ 				// Log messages of higher level than client level could be sent 
1198+ 				require .NoError (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevelEmergency , "test logger" , "" )))
1199+ 				require .NoError (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevelAlert , "test logger" , "" )))
1200+ 				require .NoError (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevelCritical , "test logger" , "" )))
1201+ 				require .NoError (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevelError , "test logger" , "" )))
1202+ 
1203+ 				// Log messages of lower level than client level could not be sent 
1204+ 				require .Error (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevelWarning , "test logger" , "" )))
1205+ 				require .Error (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevelNotice , "test logger" , "" )))
1206+ 				require .Error (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevelInfo , "test logger" , "" )))
1207+ 				require .Error (t , srv .SendLogMessageToClient (ctx , mcp .NewLoggingMessageNotification (mcp .LoggingLevelDebug , "test logger" , "" )))
1208+ 
1209+ 				logSession , ok  :=  ClientSessionFromContext (ctx ).(* sessionTestClientWithLogging )
1210+ 				require .True (t , ok , "session not found or of incorrect type" )
1211+ 
1212+ 				// Confirm four log messages were received 
1213+ 				require .Equal (t , len (logSession .notificationChannel ), 4 )
1214+ 			},
1215+ 		},
1216+ 	}
1217+ 	for  _ , tt  :=  range  tests  {
1218+ 		t .Run (tt .name , func (t  * testing.T ) {
1219+ 			server  :=  NewMCPServer ("test-server" , "1.0.0" , WithLogging ())
1220+ 			ctx  :=  tt .contextPrepare (context .Background (), server )
1221+ 
1222+ 			tt .validate (t , ctx , server )
1223+ 		})
1224+ 	}
1225+ }
0 commit comments