Skip to main content
Glama
log.ts3.48 kB
import { LoggingLevel, RequestId } from '@modelcontextprotocol/sdk/types.js'; import { Server } from '../server.js'; import { ToolName } from '../tools/toolName.js'; import { ServerLogger } from './serverLogger.js'; type Logger = 'rest-api' | (string & {}); type LogType = LoggingLevel | 'request' | 'response' | 'tool'; type LogMessage = { type: LogType; [key: string]: any; }; export const loggingLevels = [ 'debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency', ] as const; let currentLogLevel: LoggingLevel = 'debug'; let serverLogger: ServerLogger | undefined; export function isLoggingLevel(level: unknown): level is LoggingLevel { return !!loggingLevels.find((l) => l === level); } export const setLogLevel = ( server: Server, level: LoggingLevel, { silent = false }: { silent?: boolean } = {}, ): void => { if (currentLogLevel === level) { return; } currentLogLevel = level; if (!silent) { log.notice(server, `Logging level set to: ${level}`); } }; export const setServerLogger = (logger: ServerLogger): void => { serverLogger = logger; }; type LogMethodOptions = Partial<{ logger: Logger; requestId: RequestId }>; export const log = { debug: getSendLoggingMessageFn('debug'), info: getSendLoggingMessageFn('info'), notice: getSendLoggingMessageFn('notice'), warning: getSendLoggingMessageFn('warning'), error: getSendLoggingMessageFn('error'), critical: getSendLoggingMessageFn('critical'), alert: getSendLoggingMessageFn('alert'), emergency: getSendLoggingMessageFn('emergency'), } satisfies { [level in LoggingLevel]: ( server: Server, message: string | LogMessage, { logger, requestId }: LogMethodOptions, ) => Promise<void>; }; export const shouldLogWhenLevelIsAtLeast = (level = currentLogLevel): boolean => { return loggingLevels.indexOf(level) >= loggingLevels.indexOf(currentLogLevel); }; export const writeToStderr = (message: string): void => { if (process.env.TABLEAU_MCP_TEST === 'true') { // Silence logging when running in test mode return; } message = message.endsWith('\n') ? message : `${message}\n`; process.stderr.write(message); }; export const getToolLogMessage = ({ requestId, toolName, args, username, }: { requestId: RequestId; toolName: ToolName; args: unknown; username?: string; }): LogMessage => { return { type: 'tool', requestId, ...(username ? { username } : {}), tool: { name: toolName, ...(args !== undefined ? { args } : {}), }, }; }; function getSendLoggingMessageFn(level: LoggingLevel) { return async ( server: Server, message: string | LogMessage, { logger, requestId }: LogMethodOptions = { logger: server.name, }, ) => { serverLogger?.log({ message, level, logger }); if (!shouldLogWhenLevelIsAtLeast(level)) { return; } // server.sendNotification doesn't provide a way to provide the relatedRequestId // so we're using server.notification directly. return server.server.notification( { method: 'notifications/message', params: { level, logger, data: JSON.stringify( { timestamp: new Date().toISOString(), currentLogLevel, message, }, null, 2, ), }, }, { relatedRequestId: requestId, }, ); }; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/datalabs89/tableau-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server