From b318070b163991887caaa68437cc9b0df3f83f6b Mon Sep 17 00:00:00 2001 From: Bob Dickinson Date: Wed, 18 Mar 2026 12:02:57 -0700 Subject: [PATCH 1/3] Made logging consistent between all clients (using MCP_LOG_FILE), updated client readmes. Made logging initializaiton async so we have logging ready before app runs or does an early exit (this addresses the SonicBoom errors seen on early app termination). Reorganized shared logging code (which is node code) into core/logging/node. Fixed CLI error reporting through launcher (just error message now, no stack trace). --- clients/cli/README.md | 6 +++ clients/cli/src/cli.ts | 24 ++++++++++- clients/tui/README.md | 6 +++ clients/tui/src/logger.ts | 45 +++++++++++--------- clients/tui/tui.tsx | 4 ++ clients/web/README.md | 2 +- clients/web/src/components/AuthDebugger.tsx | 2 +- clients/web/src/components/OAuthCallback.tsx | 2 +- clients/web/src/server.ts | 3 +- clients/web/src/vite-hono-plugin.ts | 33 ++++++++------ clients/web/src/web-server-config.ts | 23 +++++----- clients/web/src/web.ts | 18 +++++++- core/auth/index.ts | 4 +- core/logging/index.ts | 1 - core/logging/node/fileLogger.ts | 36 ++++++++++++++++ core/logging/node/index.ts | 5 +++ core/logging/{ => node}/logger.ts | 0 core/mcp/inspectorClient.ts | 2 +- core/package.json | 4 +- 19 files changed, 164 insertions(+), 56 deletions(-) delete mode 100644 core/logging/index.ts create mode 100644 core/logging/node/fileLogger.ts create mode 100644 core/logging/node/index.ts rename core/logging/{ => node}/logger.ts (100%) diff --git a/clients/cli/README.md b/clients/cli/README.md index fd3d8f87f..2e7be7630 100644 --- a/clients/cli/README.md +++ b/clients/cli/README.md @@ -98,6 +98,12 @@ Options that specify the MCP server (config file, ad-hoc command/URL, env vars, | `--metadata ` | General metadata (key=value); applied to all methods. | | `--tool-metadata ` | Tool-specific metadata for `tools/call`. | +### Logging (env) + +| Env var | Description | +| -------------- | --------------------------------------------------------------- | +| `MCP_LOG_FILE` | If set, CLI and InspectorClient logs are appended to this file. | + ## Why use the CLI? While the Web Client provides a rich visual interface, the CLI is designed for: diff --git a/clients/cli/src/cli.ts b/clients/cli/src/cli.ts index 51014d0e6..d8995b648 100644 --- a/clients/cli/src/cli.ts +++ b/clients/cli/src/cli.ts @@ -18,6 +18,10 @@ import { parseKeyValuePair as parseEnvPair, parseHeaderPair, } from "@modelcontextprotocol/inspector-core/mcp/node/index.js"; +import { + createFileLogger, + silentLogger, +} from "@modelcontextprotocol/inspector-core/logging/node"; import type { JsonValue } from "@modelcontextprotocol/inspector-core/mcp/index.js"; import { LoggingLevelSchema, @@ -58,9 +62,21 @@ async function callMethod( const version = packageJson.version; const clientIdentity = { name, version }; + const logger = process.env.MCP_LOG_FILE + ? await createFileLogger({ + dest: process.env.MCP_LOG_FILE, + append: true, + mkdir: true, + level: "info", + name: "mcp-inspector-cli", + }) + : silentLogger; + logger.info("CLI starting"); + const inspectorClient = new InspectorClient(serverConfig, { environment: { transport: createTransportNode, + logger, }, clientIdentity, initialLoggingLevel: "debug", @@ -413,8 +429,12 @@ function parseArgs(argv?: string[]): { } export async function runCli(argv?: string[]): Promise { - const { serverConfig, methodArgs } = parseArgs(argv ?? process.argv); - await callMethod(serverConfig, methodArgs); + try { + const { serverConfig, methodArgs } = parseArgs(argv ?? process.argv); + await callMethod(serverConfig, methodArgs); + } catch (error) { + handleError(error); + } } export async function main(): Promise { diff --git a/clients/tui/README.md b/clients/tui/README.md index e050f9b46..9f6ec5975 100644 --- a/clients/tui/README.md +++ b/clients/tui/README.md @@ -39,6 +39,12 @@ When connecting to SSE or Streamable HTTP servers that use OAuth, you can pass: | `--client-metadata-url ` | OAuth Client ID Metadata Document URL (CIMD). | | `--callback-url ` | OAuth redirect/callback listener URL (default: `http://127.0.0.1:0/oauth/callback`). | +### Logging (env) + +| Env var | Description | +| -------------- | --------------------------------------------------------------- | +| `MCP_LOG_FILE` | If set, TUI and InspectorClient logs are appended to this file. | + ## Features The TUI provides terminal-native tabs and panes for interacting with your MCP server: diff --git a/clients/tui/src/logger.ts b/clients/tui/src/logger.ts index fe64650f6..1aff08d4f 100644 --- a/clients/tui/src/logger.ts +++ b/clients/tui/src/logger.ts @@ -1,23 +1,30 @@ -import path from "node:path"; -import pino from "pino"; +import type { Logger } from "pino"; +import { + silentLogger, + createFileLogger, +} from "@modelcontextprotocol/inspector-core/logging/node"; -const logDir = - process.env.MCP_INSPECTOR_LOG_DIR ?? - path.join( - process.env.HOME || process.env.USERPROFILE || ".", - ".mcp-inspector", - ); -const logPath = path.join(logDir, "auth.log"); +/** + * TUI logger (InspectorClient events, auth, etc.). + * File logger when MCP_LOG_FILE is set, else silentLogger. + */ +export let tuiLogger: Logger = silentLogger; /** - * TUI file logger for auth and InspectorClient events. - * Writes to ~/.mcp-inspector/auth.log so TUI console output is not corrupted. - * The app controls logger creation and configuration. + * If MCP_LOG_FILE is set, creates a file logger (awaits destination ready); + * otherwise uses silentLogger. Call at the start of runTui() before any work + * that might call process.exit(). */ -export const tuiLogger = pino( - { - name: "mcp-inspector-tui", - level: process.env.LOG_LEVEL ?? "info", - }, - pino.destination({ dest: logPath, append: true, mkdir: true }), -); +export async function initTuiLogger(): Promise { + if (process.env.MCP_LOG_FILE) { + tuiLogger = await createFileLogger({ + dest: process.env.MCP_LOG_FILE, + append: true, + mkdir: true, + level: "info", + name: "mcp-inspector-tui", + }); + } else { + tuiLogger = silentLogger; + } +} diff --git a/clients/tui/tui.tsx b/clients/tui/tui.tsx index 093c79dd7..ab01ab375 100755 --- a/clients/tui/tui.tsx +++ b/clients/tui/tui.tsx @@ -9,9 +9,13 @@ import { parseKeyValuePair, parseHeaderPair, } from "@modelcontextprotocol/inspector-core/mcp/node/index.js"; +import { initTuiLogger, tuiLogger } from "./src/logger.js"; import App from "./src/App.js"; export async function runTui(args?: string[]): Promise { + await initTuiLogger(); + tuiLogger.info("TUI starting"); + const program = new Command(); program diff --git a/clients/web/README.md b/clients/web/README.md index e30bc5001..564e2a3f1 100644 --- a/clients/web/README.md +++ b/clients/web/README.md @@ -72,7 +72,7 @@ All of these are set via **environment variables**; the web app has no command-l | **Sandbox port** (MCP Apps) | Env: `MCP_SANDBOX_PORT`; if unset, `SERVER_PORT` (legacy). Use `0` or leave unset for an automatic port. | automatic | | **Storage directory** (e.g. OAuth) | Env: `MCP_STORAGE_DIR` | (unset) | | **Allowed origins** (CORS) | Env: `ALLOWED_ORIGINS` (comma-separated) | client origin only | -| **Log file** | Env: `MCP_LOG_FILE` — if set, server logs are appended to this file. | (unset) | +| **Log file** | Env: `MCP_LOG_FILE` — if set, server and InspectorClient logs are appended to this file. | (unset) | | **Open browser on start** | Env: `MCP_AUTO_OPEN_ENABLED` — set to `false` to disable. | `true` | | **Development mode** | CLI only: `--dev` (Vite with HMR). No env var. | off | diff --git a/clients/web/src/components/AuthDebugger.tsx b/clients/web/src/components/AuthDebugger.tsx index ad164451a..a4f16b355 100644 --- a/clients/web/src/components/AuthDebugger.tsx +++ b/clients/web/src/components/AuthDebugger.tsx @@ -2,7 +2,7 @@ import { useCallback, useEffect, useState } from "react"; import { Button } from "@/components/ui/button"; import { AlertCircle } from "lucide-react"; import type { InspectorClient } from "@modelcontextprotocol/inspector-core/mcp/index.js"; -import { silentLogger } from "@modelcontextprotocol/inspector-core/logging"; +import { silentLogger } from "@modelcontextprotocol/inspector-core/logging/node"; import type { AuthGuidedState } from "@modelcontextprotocol/inspector-core/auth/types.js"; import type { WebEnvironmentResult } from "@/lib/adapters/environmentFactory"; import { OAuthFlowProgress } from "./OAuthFlowProgress"; diff --git a/clients/web/src/components/OAuthCallback.tsx b/clients/web/src/components/OAuthCallback.tsx index 0f2b19ce0..16ac7761e 100644 --- a/clients/web/src/components/OAuthCallback.tsx +++ b/clients/web/src/components/OAuthCallback.tsx @@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import type { InspectorClient } from "@modelcontextprotocol/inspector-core/mcp/index.js"; import type { WebEnvironmentResult } from "@/lib/adapters/environmentFactory"; import { parseOAuthState } from "@modelcontextprotocol/inspector-core/auth/index.js"; -import { silentLogger } from "@modelcontextprotocol/inspector-core/logging"; +import { silentLogger } from "@modelcontextprotocol/inspector-core/logging/node"; import useTheme from "@/lib/hooks/useTheme"; import { useToast } from "@/lib/hooks/useToast"; import { diff --git a/clients/web/src/server.ts b/clients/web/src/server.ts index ab64dcc08..f19626ec8 100644 --- a/clients/web/src/server.ts +++ b/clients/web/src/server.ts @@ -34,6 +34,7 @@ export interface WebServerHandle { export async function startHonoServer( config: WebServerConfig, ): Promise { + config.logger.info("Web server starting"); const sandboxController = createSandboxController({ port: config.sandboxPort, host: config.sandboxHost, @@ -131,7 +132,7 @@ export async function startHonoServer( /** Run when this file is executed as the main module (e.g. node dist/server.js). */ async function runStandalone(): Promise { - const config = buildWebServerConfigFromEnv(); + const config = await buildWebServerConfigFromEnv(); const handle = await startHonoServer(config); const shutdown = () => { void handle.close().then(() => process.exit(0)); diff --git a/clients/web/src/vite-hono-plugin.ts b/clients/web/src/vite-hono-plugin.ts index 7081a0fda..ff141f994 100644 --- a/clients/web/src/vite-hono-plugin.ts +++ b/clients/web/src/vite-hono-plugin.ts @@ -15,15 +15,20 @@ import { } from "./web-server-config.js"; /** - * Plugin factory. Caller must pass a WebServerConfig (runner builds it from argv; vite.config builds it from env via buildWebServerConfigFromEnv). + * Plugin factory. Caller must pass a WebServerConfig or Promise + * (runner builds from argv; vite.config passes buildWebServerConfigFromEnv() which is async). */ -export function honoMiddlewarePlugin(config: WebServerConfig): Plugin { +export function honoMiddlewarePlugin( + config: WebServerConfig | Promise, +): Plugin { return { name: "hono-api-middleware", async configureServer(server) { + const resolvedConfig = await Promise.resolve(config); + resolvedConfig.logger.info("Web server starting (dev)"); const sandboxController = createSandboxController({ - port: config.sandboxPort, - host: config.sandboxHost, + port: resolvedConfig.sandboxPort, + host: resolvedConfig.sandboxHost, }); await sandboxController.start(); @@ -40,13 +45,15 @@ export function honoMiddlewarePlugin(config: WebServerConfig): Plugin { }; const { app: honoApp, authToken: resolvedToken } = createRemoteApp({ - authToken: config.dangerouslyOmitAuth ? undefined : config.authToken, - dangerouslyOmitAuth: config.dangerouslyOmitAuth, - storageDir: config.storageDir, - allowedOrigins: config.allowedOrigins, + authToken: resolvedConfig.dangerouslyOmitAuth + ? undefined + : resolvedConfig.authToken, + dangerouslyOmitAuth: resolvedConfig.dangerouslyOmitAuth, + storageDir: resolvedConfig.storageDir, + allowedOrigins: resolvedConfig.allowedOrigins, sandboxUrl: sandboxController.getUrl() ?? undefined, - logger: config.logger, - initialConfig: webServerConfigToInitialPayload(config), + logger: resolvedConfig.logger, + initialConfig: webServerConfigToInitialPayload(resolvedConfig), }); const sandboxUrl = sandboxController.getUrl(); @@ -56,16 +63,16 @@ export function honoMiddlewarePlugin(config: WebServerConfig): Plugin { const actualPort = typeof address === "object" && address !== null ? address.port - : config.port; + : resolvedConfig.port; const url = printServerBanner( - config, + resolvedConfig, actualPort, resolvedToken, sandboxUrl ?? undefined, ); - if (config.autoOpen) { + if (resolvedConfig.autoOpen) { open(url); } }; diff --git a/clients/web/src/web-server-config.ts b/clients/web/src/web-server-config.ts index e02a3aafe..704e6e933 100644 --- a/clients/web/src/web-server-config.ts +++ b/clients/web/src/web-server-config.ts @@ -2,9 +2,12 @@ * Config object for the web server (dev and prod). Passed in-process; no env handoff. */ -import pino from "pino"; import type { Logger } from "pino"; import type { MCPServerConfig } from "@modelcontextprotocol/inspector-core/mcp/types.js"; +import { + createFileLogger, + silentLogger, +} from "@modelcontextprotocol/inspector-core/logging/node"; import { API_SERVER_ENV_VARS, LEGACY_AUTH_TOKEN_ENV, @@ -24,7 +27,7 @@ export interface WebServerConfig { /** Sandbox port (0 = dynamic). */ sandboxPort: number; sandboxHost: string; - logger: Logger | undefined; + logger: Logger; /** When true, open browser after server starts. */ autoOpen: boolean; /** Root directory for static files (index.html, assets). When runner starts server in-process, pass path to dist/. */ @@ -148,8 +151,9 @@ export function printServerBanner( /** * Build WebServerConfig from process.env. Used when running server as standalone (e.g. node dist/server.js). + * When MCP_LOG_FILE is set, returns a Promise (file logger destination must be awaited). */ -export function buildWebServerConfigFromEnv(): WebServerConfig { +export async function buildWebServerConfigFromEnv(): Promise { const port = parseInt(process.env.CLIENT_PORT ?? "6274", 10); const hostname = process.env.HOST ?? "localhost"; const baseUrl = `http://${hostname}:${port}`; @@ -164,17 +168,14 @@ export function buildWebServerConfigFromEnv(): WebServerConfig { const sandboxPort = resolveSandboxPort(); - let logger: Logger | undefined; - if (process.env.MCP_LOG_FILE) { - logger = pino( - { level: "info" }, - pino.destination({ + const logger = process.env.MCP_LOG_FILE + ? await createFileLogger({ dest: process.env.MCP_LOG_FILE, append: true, mkdir: true, - }), - ); - } + level: "info", + }) + : silentLogger; return { port, diff --git a/clients/web/src/web.ts b/clients/web/src/web.ts index 5865d58a6..002db3b7d 100644 --- a/clients/web/src/web.ts +++ b/clients/web/src/web.ts @@ -2,6 +2,7 @@ import { resolve, join, dirname } from "path"; import { fileURLToPath } from "url"; import { randomBytes } from "crypto"; import { Command } from "commander"; +import type { Logger } from "pino"; import type { MCPServerConfig, StreamableHttpServerConfig, @@ -16,6 +17,10 @@ import { parseHeaderPair, type ServerConfigOptions, } from "@modelcontextprotocol/inspector-core/mcp/node/config.js"; +import { + createFileLogger, + silentLogger, +} from "@modelcontextprotocol/inspector-core/logging/node"; import { resolveSandboxPort } from "./sandbox-controller.js"; import type { WebServerConfig } from "./web-server-config.js"; import { startViteDevServer } from "./start-vite-dev-server.js"; @@ -93,6 +98,7 @@ function buildWebServerConfig( hostname: string, authToken: string, dangerouslyOmitAuth: boolean, + logger: Logger, ): WebServerConfig { const baseUrl = `http://${hostname}:${port}`; const initialMcpConfig: MCPServerConfig | null = @@ -136,7 +142,7 @@ function buildWebServerConfig( ], sandboxPort: resolveSandboxPort(), sandboxHost: hostname, - logger: undefined, + logger, autoOpen: process.env.MCP_AUTO_OPEN_ENABLED !== "false", }; } @@ -252,12 +258,22 @@ export async function runWeb(argv: string[]): Promise { (process.env[LEGACY_AUTH_TOKEN_ENV] as string | undefined) ?? randomBytes(32).toString("hex")); + const logger = process.env.MCP_LOG_FILE + ? await createFileLogger({ + dest: process.env.MCP_LOG_FILE, + append: true, + mkdir: true, + level: "info", + }) + : silentLogger; + const webConfig = buildWebServerConfig( clientOptions, port, hostname, authToken, dangerouslyOmitAuth, + logger, ); if (!clientOptions.isDev) { webConfig.staticRoot = join(__dirname, "..", "dist"); diff --git a/core/auth/index.ts b/core/auth/index.ts index 467b55a49..a4f1fc76d 100644 --- a/core/auth/index.ts +++ b/core/auth/index.ts @@ -40,8 +40,8 @@ export type { OAuthStateMode } from "./utils.js"; // Discovery export { discoverScopes } from "./discovery.js"; -// Logging (re-exported from core/logging) -export { silentLogger } from "../logging/index.js"; +// Logging (re-exported from core/logging/node) +export { silentLogger } from "../logging/node/index.js"; // State Machine export type { StateMachineContext, StateTransition } from "./state-machine.js"; export { oauthTransitions, OAuthStateMachine } from "./state-machine.js"; diff --git a/core/logging/index.ts b/core/logging/index.ts deleted file mode 100644 index 6abcce77a..000000000 --- a/core/logging/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { silentLogger } from "./logger.js"; diff --git a/core/logging/node/fileLogger.ts b/core/logging/node/fileLogger.ts new file mode 100644 index 000000000..fd3146a2f --- /dev/null +++ b/core/logging/node/fileLogger.ts @@ -0,0 +1,36 @@ +import pino from "pino"; +import type { Logger } from "pino"; + +export interface CreateFileLoggerOptions { + dest: string; + append?: boolean; + mkdir?: boolean; + level?: string; + name?: string; +} + +/** + * Creates a pino file logger whose destination is ready before use. + * Waits for the destination's `ready` event so exit handlers can flush safely. + * Use this instead of pino.destination({ dest }) + pino() when the process may exit early. + */ +export async function createFileLogger( + options: CreateFileLoggerOptions, +): Promise { + const dest = pino.destination({ + dest: options.dest, + append: options.append ?? true, + mkdir: options.mkdir ?? true, + }); + await new Promise((resolve, reject) => { + dest.once("ready", resolve); + dest.once("error", reject); + }); + return pino( + { + level: options.level ?? "info", + ...(options.name !== undefined && { name: options.name }), + }, + dest, + ); +} diff --git a/core/logging/node/index.ts b/core/logging/node/index.ts new file mode 100644 index 000000000..5725f0007 --- /dev/null +++ b/core/logging/node/index.ts @@ -0,0 +1,5 @@ +export { silentLogger } from "./logger.js"; +export { + createFileLogger, + type CreateFileLoggerOptions, +} from "./fileLogger.js"; diff --git a/core/logging/logger.ts b/core/logging/node/logger.ts similarity index 100% rename from core/logging/logger.ts rename to core/logging/node/logger.ts diff --git a/core/mcp/inspectorClient.ts b/core/mcp/inspectorClient.ts index 26b4fb0a2..3c01d1602 100644 --- a/core/mcp/inspectorClient.ts +++ b/core/mcp/inspectorClient.ts @@ -95,7 +95,7 @@ import { ElicitationCreateMessage } from "./elicitationCreateMessage.js"; import type { AuthGuidedState, OAuthStep } from "../auth/types.js"; import type { OAuthTokens } from "@modelcontextprotocol/sdk/shared/auth.js"; import type pino from "pino"; -import { silentLogger } from "../logging/logger.js"; +import { silentLogger } from "../logging/node/logger.js"; import { createFetchTracker } from "./fetchTracking.js"; import { OAuthManager, type OAuthManagerConfig } from "./oauthManager.js"; diff --git a/core/package.json b/core/package.json index dcc5daaf0..88214c5f2 100644 --- a/core/package.json +++ b/core/package.json @@ -18,8 +18,8 @@ "./mcp/node/*": "./build/mcp/node/*", "./auth/browser": "./build/auth/browser/index.js", "./auth/browser/*": "./build/auth/browser/*", - "./logging": "./build/logging/index.js", - "./logging/*": "./build/logging/*", + "./logging/node": "./build/logging/node/index.js", + "./logging/node/*": "./build/logging/node/*", "./mcp/remote": "./build/mcp/remote/index.js", "./mcp/remote/*": "./build/mcp/remote/*", "./mcp/remote/node": "./build/mcp/remote/node/index.js", From 212988bfc5b7af68a2100e3425cf2eb7469e7f18 Mon Sep 17 00:00:00 2001 From: Bob Dickinson Date: Wed, 18 Mar 2026 12:51:55 -0700 Subject: [PATCH 2/3] Impplemented separate silentLogger for browser usage where needed. --- clients/web/src/components/AuthDebugger.tsx | 2 +- clients/web/src/components/OAuthCallback.tsx | 2 +- core/logging/browser/index.ts | 1 + core/logging/browser/logger.ts | 10 ++++++++++ core/package.json | 2 ++ 5 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 core/logging/browser/index.ts create mode 100644 core/logging/browser/logger.ts diff --git a/clients/web/src/components/AuthDebugger.tsx b/clients/web/src/components/AuthDebugger.tsx index a4f16b355..7347568f2 100644 --- a/clients/web/src/components/AuthDebugger.tsx +++ b/clients/web/src/components/AuthDebugger.tsx @@ -2,7 +2,7 @@ import { useCallback, useEffect, useState } from "react"; import { Button } from "@/components/ui/button"; import { AlertCircle } from "lucide-react"; import type { InspectorClient } from "@modelcontextprotocol/inspector-core/mcp/index.js"; -import { silentLogger } from "@modelcontextprotocol/inspector-core/logging/node"; +import { silentLogger } from "@modelcontextprotocol/inspector-core/logging/browser"; import type { AuthGuidedState } from "@modelcontextprotocol/inspector-core/auth/types.js"; import type { WebEnvironmentResult } from "@/lib/adapters/environmentFactory"; import { OAuthFlowProgress } from "./OAuthFlowProgress"; diff --git a/clients/web/src/components/OAuthCallback.tsx b/clients/web/src/components/OAuthCallback.tsx index 16ac7761e..6594edb41 100644 --- a/clients/web/src/components/OAuthCallback.tsx +++ b/clients/web/src/components/OAuthCallback.tsx @@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import type { InspectorClient } from "@modelcontextprotocol/inspector-core/mcp/index.js"; import type { WebEnvironmentResult } from "@/lib/adapters/environmentFactory"; import { parseOAuthState } from "@modelcontextprotocol/inspector-core/auth/index.js"; -import { silentLogger } from "@modelcontextprotocol/inspector-core/logging/node"; +import { silentLogger } from "@modelcontextprotocol/inspector-core/logging/browser"; import useTheme from "@/lib/hooks/useTheme"; import { useToast } from "@/lib/hooks/useToast"; import { diff --git a/core/logging/browser/index.ts b/core/logging/browser/index.ts new file mode 100644 index 000000000..6abcce77a --- /dev/null +++ b/core/logging/browser/index.ts @@ -0,0 +1 @@ +export { silentLogger } from "./logger.js"; diff --git a/core/logging/browser/logger.ts b/core/logging/browser/logger.ts new file mode 100644 index 000000000..c267a5ac0 --- /dev/null +++ b/core/logging/browser/logger.ts @@ -0,0 +1,10 @@ +/** + * Silent logger for browser contexts. Satisfies pino.Logger; does not output anything. + * Use when no logger is passed (e.g. OAuth callback with no client). Web components + * that need a fallback import from logging/browser so they don't pull in Node logging. + */ +// @ts-expect-error - pino/browser.js exists but TypeScript doesn't have types for the .js extension +import pino from "pino/browser.js"; +import type { Logger } from "pino"; + +export const silentLogger: Logger = pino({ level: "silent" }); diff --git a/core/package.json b/core/package.json index 88214c5f2..210aa98e2 100644 --- a/core/package.json +++ b/core/package.json @@ -18,6 +18,8 @@ "./mcp/node/*": "./build/mcp/node/*", "./auth/browser": "./build/auth/browser/index.js", "./auth/browser/*": "./build/auth/browser/*", + "./logging/browser": "./build/logging/browser/index.js", + "./logging/browser/*": "./build/logging/browser/*", "./logging/node": "./build/logging/node/index.js", "./logging/node/*": "./build/logging/node/*", "./mcp/remote": "./build/mcp/remote/index.js", From 81d3cf631e0a39a1080d9c29f7c177cb2a2cda15 Mon Sep 17 00:00:00 2001 From: Bob Dickinson Date: Wed, 18 Mar 2026 12:53:51 -0700 Subject: [PATCH 3/3] Added missing web log file logger name --- clients/web/src/web-server-config.ts | 1 + clients/web/src/web.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/clients/web/src/web-server-config.ts b/clients/web/src/web-server-config.ts index 704e6e933..3b8bb8669 100644 --- a/clients/web/src/web-server-config.ts +++ b/clients/web/src/web-server-config.ts @@ -174,6 +174,7 @@ export async function buildWebServerConfigFromEnv(): Promise { append: true, mkdir: true, level: "info", + name: "mcp-inspector-web", }) : silentLogger; diff --git a/clients/web/src/web.ts b/clients/web/src/web.ts index 002db3b7d..d5a73133f 100644 --- a/clients/web/src/web.ts +++ b/clients/web/src/web.ts @@ -264,6 +264,7 @@ export async function runWeb(argv: string[]): Promise { append: true, mkdir: true, level: "info", + name: "mcp-inspector-web", }) : silentLogger;