@@ -12,17 +12,20 @@ import { type ServerCommand } from "./telemetry/types.js";
1212import {
1313 CallToolRequestSchema ,
1414 CallToolResult ,
15+ SetLevelRequestSchema ,
1516 SubscribeRequestSchema ,
1617 UnsubscribeRequestSchema ,
1718} from "@modelcontextprotocol/sdk/types.js" ;
1819import assert from "assert" ;
1920import { ToolBase } from "./tools/tool.js" ;
21+ import { LogLevel , McpLogger } from "./common/logger.js" ;
2022
2123export interface ServerOptions {
2224 session : Session ;
2325 userConfig : UserConfig ;
2426 mcpServer : McpServer ;
2527 telemetry : Telemetry ;
28+ mcpLogger ?: McpLogger ;
2629}
2730
2831export class Server {
@@ -33,13 +36,21 @@ export class Server {
3336 public readonly tools : ToolBase [ ] = [ ] ;
3437 private readonly startTime : number ;
3538 private readonly subscriptions = new Set < string > ( ) ;
39+ private minimumLogLevel : LogLevel = "info" ;
40+ private readonly mcpLogger ?: McpLogger ;
3641
37- constructor ( { session, mcpServer, userConfig, telemetry } : ServerOptions ) {
42+ constructor ( { session, mcpServer, userConfig, telemetry, mcpLogger } : ServerOptions ) {
3843 this . startTime = Date . now ( ) ;
3944 this . session = session ;
4045 this . telemetry = telemetry ;
4146 this . mcpServer = mcpServer ;
4247 this . userConfig = userConfig ;
48+ this . mcpLogger = mcpLogger ;
49+
50+ // Set up log level filtering for MCP logger
51+ if ( this . mcpLogger ) {
52+ this . mcpLogger . setShouldLogFunction ( ( level : LogLevel ) => this . shouldLog ( level ) ) ;
53+ }
4354 }
4455
4556 async connect ( transport : Transport ) : Promise < void > {
@@ -48,7 +59,7 @@ export class Server {
4859 this . registerResources ( ) ;
4960 await this . validateConfig ( ) ;
5061
51- this . mcpServer . server . registerCapabilities ( { resources : { listChanged : true , subscribe : true } } ) ;
62+ this . mcpServer . server . registerCapabilities ( { logging : { } , resources : { listChanged : true , subscribe : true } } ) ;
5263
5364 // TODO: Eventually we might want to make tools reactive too instead of relying on custom logic.
5465 this . registerTools ( ) ;
@@ -96,6 +107,16 @@ export class Server {
96107 return { } ;
97108 } ) ;
98109
110+ this . mcpServer . server . setRequestHandler ( SetLevelRequestSchema , ( { params } ) => {
111+ this . minimumLogLevel = params . level ;
112+ this . session . logger . debug ( {
113+ id : LogId . serverInitialized ,
114+ context : "logging" ,
115+ message : `Log level set to: ${ params . level } ` ,
116+ } ) ;
117+ return { } ;
118+ } ) ;
119+
99120 this . mcpServer . server . oninitialized = ( ) : void => {
100121 this . session . setAgentRunner ( this . mcpServer . server . getClientVersion ( ) ) ;
101122
@@ -137,6 +158,18 @@ export class Server {
137158 }
138159 }
139160
161+ /**
162+ * Checks if a log level meets the minimum threshold for logging
163+ * @param level - The log level to check
164+ * @returns true if the level should be logged, false otherwise
165+ */
166+ public shouldLog ( level : LogLevel ) : boolean {
167+ const levels : LogLevel [ ] = [ "debug" , "info" , "notice" , "warning" , "error" , "critical" , "alert" , "emergency" ] ;
168+ const currentIndex = levels . indexOf ( this . minimumLogLevel ) ;
169+ const levelIndex = levels . indexOf ( level ) ;
170+ return levelIndex >= currentIndex ;
171+ }
172+
140173 /**
141174 * Emits a server event
142175 * @param command - The server command (e.g., "start", "stop", "register", "deregister")
0 commit comments