Logging updates (including reported SonicBoom error)#1158
Logging updates (including reported SonicBoom error)#1158BobDickinson wants to merge 3 commits intomodelcontextprotocol:v1.5/mainfrom
Conversation
…ated 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).
|
@claude review |
|
Claude finished @BobDickinson's task in 1m 35s —— View job Code Review
Overall this is a well-structured improvement. The core fix (awaiting the SonicBoom Issues1. Browser components importing from
// clients/web/src/components/AuthDebugger.tsx
import { silentLogger } from "@modelcontextprotocol/inspector-core/logging/node";The The old 2. Missing logger
// clients/web/src/web.ts:260
const logger = process.env.MCP_LOG_FILE
? await createFileLogger({
dest: process.env.MCP_LOG_FILE,
append: true,
mkdir: true,
level: "info",
// missing: name: "mcp-inspector-web"
})
: silentLogger;Log lines from the web runner won't have a Minor Observations
What Works Well
|
|
Claude review feedback implemented. |
|
@BobDickinson is this one ready for review? |
Yes, ready for review. |
There was a problem hiding this comment.
Pull request overview
This PR standardizes logging across the Inspector clients by introducing explicit Node vs browser logging entrypoints in @modelcontextprotocol/inspector-core, adding an async file logger initializer to avoid early-exit SonicBoom issues, and updating clients/docs to use MCP_LOG_FILE consistently.
Changes:
- Split
corelogging intologging/nodeandlogging/browserexports (and updated imports accordingly). - Added
createFileLogger()(async, awaits destination readiness) and adopted it in CLI/Web/TUI whenMCP_LOG_FILEis set. - Updated web dev/standalone bootstrapping to support async config creation and adjusted CLI error handling / readmes.
Reviewed changes
Copilot reviewed 18 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| core/package.json | Replaces generic ./logging export with explicit ./logging/node and ./logging/browser subpath exports. |
| core/mcp/inspectorClient.ts | Switches default logger import to the Node logging module. |
| core/logging/node/logger.ts | Introduces Node silentLogger implementation. |
| core/logging/node/index.ts | Exports Node logging utilities (silentLogger, createFileLogger). |
| core/logging/node/fileLogger.ts | Adds async createFileLogger() that waits for destination readiness. |
| core/logging/browser/logger.ts | Introduces browser silentLogger implementation. |
| core/logging/browser/index.ts | Exports browser silentLogger. |
| core/auth/index.ts | Re-exports silentLogger from Node logging. |
| clients/web/src/web.ts | Creates a file logger from MCP_LOG_FILE and injects it into the web server config. |
| clients/web/src/web-server-config.ts | Makes logger required and makes env-based config builder async to await file logger readiness. |
| clients/web/src/vite-hono-plugin.ts | Accepts `WebServerConfig |
| clients/web/src/server.ts | Awaits async env config builder; logs startup. |
| clients/web/src/components/OAuthCallback.tsx | Switches to browser logging import to avoid pulling Node logging into the UI bundle. |
| clients/web/src/components/AuthDebugger.tsx | Switches to browser logging import to avoid pulling Node logging into the UI bundle. |
| clients/web/README.md | Documents that MCP_LOG_FILE captures both server and InspectorClient logs. |
| clients/tui/tui.tsx | Initializes TUI logging asynchronously before startup work. |
| clients/tui/src/logger.ts | Replaces hardcoded ~/.mcp-inspector/auth.log logger with MCP_LOG_FILE + async init. |
| clients/tui/README.md | Documents MCP_LOG_FILE for TUI logging. |
| clients/cli/src/cli.ts | Uses MCP_LOG_FILE + async file logger; wraps runCli in error handler. |
| clients/cli/README.md | Documents MCP_LOG_FILE for CLI logging. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Logging (re-exported from core/logging/node) | ||
| export { silentLogger } from "../logging/node/index.js"; |
There was a problem hiding this comment.
core/auth/index.ts is part of the package’s default (isomorphic) auth entrypoint (exports["./auth"]). Re-exporting silentLogger from ../logging/node makes every import of @modelcontextprotocol/inspector-core/auth / auth/* pull in the Node logging module (and its pino Node entry), which can break browser bundling even when silentLogger is not used. Consider removing this re-export from the shared auth index and instead exporting it from auth/node (and/or auth/browser) or requiring callers to import from logging/node vs logging/browser directly.
| // Logging (re-exported from core/logging/node) | |
| export { silentLogger } from "../logging/node/index.js"; |
| dest.once("ready", resolve); | ||
| dest.once("error", reject); |
There was a problem hiding this comment.
In createFileLogger, the dest.once("error", reject) listener remains attached after the Promise resolves on ready. If the destination emits an error later (disk full, permission change, etc.), that error will be effectively swallowed (the Promise is already resolved), and the presence of the listener may prevent the process from surfacing the failure. Consider removing the error listener once ready fires, or attaching a persistent error handler that reports/propagates errors in a way callers can observe.
| dest.once("ready", resolve); | |
| dest.once("error", reject); | |
| const handleReady = () => { | |
| dest.off("error", handleError); | |
| resolve(); | |
| }; | |
| const handleError = (error: Error) => { | |
| dest.off("ready", handleReady); | |
| reject(error); | |
| }; | |
| dest.once("ready", handleReady); | |
| dest.once("error", handleError); |
| /** | ||
| * 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<Logger> { |
There was a problem hiding this comment.
createFileLogger introduces new async behavior (waiting for the destination ready event) and error handling around the destination stream, but there are no tests validating that it actually waits for readiness and produces a writable logger (or that errors are handled as expected). Adding a small vitest that creates a temp log file, awaits createFileLogger, writes a log line, flushes/closes, and asserts the file contains output would help prevent regressions (and would specifically cover the SonicBoom early-exit scenario this PR is addressing).
Summary
Made logging consistent between all clients (using MCP_LOG_FILE), updated client readmes. Made logging initialization async so we have logging ready before app startup processing or 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). Made logger required throughout using silentLogger (null logger) as default.
Testing
Checklist
npm run prettier-fix)