Skip to content

Commit 8c126a0

Browse files
committed
fix: route logs to mcp log format
1 parent 947ca35 commit 8c126a0

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

src/common/atlas/openapi.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,6 +1735,11 @@ export interface components {
17351735
* @example 32b6e34b3d91647abb20e7b8
17361736
*/
17371737
readonly roleId?: string;
1738+
/**
1739+
* @description Provision status of the service account.
1740+
* @enum {string}
1741+
*/
1742+
readonly status?: "IN_PROGRESS" | "COMPLETE" | "FAILED" | "NOT_INITIATED";
17381743
} & {
17391744
/**
17401745
* @description discriminator enum property added by openapi-typescript

src/common/logger.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,18 +244,32 @@ export class DiskLogger extends LoggerBase<{ initialized: [] }> {
244244
}
245245

246246
export class McpLogger extends LoggerBase {
247+
private shouldLogFunction?: (level: LogLevel) => boolean;
248+
247249
public constructor(private readonly server: McpServer) {
248250
super();
249251
}
250252

251253
protected readonly type: LoggerType = "mcp";
252254

255+
/**
256+
* Sets the function to check if a log level should be sent
257+
*/
258+
public setShouldLogFunction(shouldLog: (level: LogLevel) => boolean): void {
259+
this.shouldLogFunction = shouldLog;
260+
}
261+
253262
protected logCore(level: LogLevel, payload: LogPayload): void {
254263
// Only log if the server is connected
255264
if (!this.server?.isConnected()) {
256265
return;
257266
}
258267

268+
// Check if this log level should be sent
269+
if (this.shouldLogFunction && !this.shouldLogFunction(level)) {
270+
return;
271+
}
272+
259273
void this.server.server.sendLoggingMessage({
260274
level,
261275
data: `[${payload.context}]: ${payload.message}`,

src/server.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,20 @@ import { type ServerCommand } from "./telemetry/types.js";
1212
import {
1313
CallToolRequestSchema,
1414
CallToolResult,
15+
SetLevelRequestSchema,
1516
SubscribeRequestSchema,
1617
UnsubscribeRequestSchema,
1718
} from "@modelcontextprotocol/sdk/types.js";
1819
import assert from "assert";
1920
import { ToolBase } from "./tools/tool.js";
21+
import { LogLevel, McpLogger } from "./common/logger.js";
2022

2123
export interface ServerOptions {
2224
session: Session;
2325
userConfig: UserConfig;
2426
mcpServer: McpServer;
2527
telemetry: Telemetry;
28+
mcpLogger?: McpLogger;
2629
}
2730

2831
export 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")

src/transports/base.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ export abstract class TransportRunnerBase {
3737
});
3838

3939
const loggers = [this.logger];
40+
let mcpLogger: McpLogger | undefined;
4041
if (userConfig.loggers.includes("mcp")) {
41-
loggers.push(new McpLogger(mcpServer));
42+
mcpLogger = new McpLogger(mcpServer);
43+
loggers.push(mcpLogger);
4244
}
4345

4446
const logger = new CompositeLogger(...loggers);
@@ -61,6 +63,7 @@ export abstract class TransportRunnerBase {
6163
session,
6264
telemetry,
6365
userConfig,
66+
mcpLogger,
6467
});
6568
}
6669

0 commit comments

Comments
 (0)