feat: add injectable SDK logger#2370
Conversation
🦋 Changeset detectedLatest commit: b5094b5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@modelcontextprotocol/client
@modelcontextprotocol/codemod
@modelcontextprotocol/core
@modelcontextprotocol/server
@modelcontextprotocol/server-legacy
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
63bb2b4 to
f2d0beb
Compare
There was a problem hiding this comment.
Both points from my earlier review are now addressed in this revision — the prompt argsSchema conversion path forwards the configured logger, and prose docs plus a sourced example were added for the new option. I didn't find any new issues, but since this introduces a new public API surface (the logger ProtocolOptions field and the exported SdkLogger type), a maintainer should sign off on the API shape.
Extended reasoning...
Overview
This PR adds an injectable SdkLogger to ProtocolOptions, threads it through Protocol, Client, and McpServer, and routes existing console.* SDK diagnostics (capability-gating debug messages, tool-name validation warnings, zod-fallback warnings) through it. It exports the SdkLogger type from the core public exports, adds a changeset, prose documentation in docs/client.md and docs/server.md, a sourced example in examples/client/src/clientGuide.examples.ts, and focused tests for the client, tool-name, prompt-conversion, and zod-fallback paths. The latest commit also addresses both items raised in my prior review: promptArgumentsFromStandardSchema now accepts and forwards a logger (with the prompts/list call site passing this._logger), and prose documentation for the option was added.
Security risks
None identified. The logger is a user-supplied callback object invoked only with diagnostic strings via optional chaining; it does not handle credentials, network input, or auth flows. The default remains console, preserving existing behavior for callers that don't opt in.
Level of scrutiny
Moderate. The mechanical changes (replacing console.warn/console.debug with this._logger.*?.() and threading a defaulted parameter) are low risk and well covered by the new tests, which also assert that console is no longer hit when a custom logger is configured. However, the PR introduces a new public API surface — a logger field on ProtocolOptions and a newly exported SdkLogger type — and this repository's conventions place the burden of proof on additions to the public API. Whether the shape (partial logger with all-optional methods, no level filtering, named SdkLogger, attached to ProtocolOptions rather than a narrower options type) is the right long-term design is a maintainer judgment call, so I'm not shadow-approving.
Other factors
The change has a concrete motivating issue (#1262), the changeset correctly marks core/client/server as minor, and existing behavior is unchanged when no logger is provided. The test coverage is reasonable: client capability-gating debug routing, tool-name warning routing, prompt argsSchema conversion routing, and the zod-fallback path all assert both the custom logger call and the absence of console output. No unresolved reviewer comments remain on the thread.
|
Hey @mattzcarey , we explored this in #1034 You could get some stuff from there, there are some caveats with Stdio, plus following SysLog - RFC5424 |
f2d0beb to
103073d
Compare
There was a problem hiding this comment.
The latest revision addresses my earlier findings (changeset now targets core-internal, prose docs/example added, and the prompts/list path now threads the configured logger with test coverage), and I didn't find new bugs — but this adds a new public API surface (ProtocolOptions.logger and the exported SdkLogger type) and there's an open maintainer comment pointing to prior design discussion in #1034 (stdio caveats, RFC5424 levels), so a human should weigh in on the API shape before merging.
Extended reasoning...
Overview
This PR adds an injectable SDK diagnostics logger: a new logger field on ProtocolOptions (consumed by Protocol, Client, and McpServer), a new SdkLogger type exported from the public surface of core-internal, and routing of existing console.* diagnostics (client capability-gating debug messages, tool-name validation warnings, zod JSON-schema fallback warnings) through that logger. It also adds prose docs in docs/client.md and docs/server.md, a sourced example, focused tests in all three packages, and a changeset bumping core-internal/client/server as minor.
Status of prior feedback
All three issues raised on earlier revisions are resolved in the current diff: the changeset frontmatter now lists @modelcontextprotocol/core-internal instead of the schemas-only core package; promptArgumentsFromStandardSchema now accepts and forwards a logger and McpServer passes this._logger at the prompts/list call site (with a regression test); and prose documentation plus an example were added. A grep of the modified packages shows no remaining un-routed console.* diagnostics in scope (the fetch-logging middleware has its own configurable RequestLogger and is unrelated).
Security risks
None identified. The logger is a passive sink for diagnostic strings; no auth, crypto, or transport behavior changes. The only minor consideration is that user-supplied logger callbacks now run inside SDK code paths, but they are invoked with optional chaining and a throwing logger would surface like any handler error.
Level of scrutiny
The implementation is small and well-tested, but this is a deliberate public API addition on a repo whose review conventions put the burden of proof on additions and ask for design-level sign-off first. There is also an unanswered maintainer comment referencing the earlier exploration in PR #1034 (stdio caveats, RFC5424/syslog level alignment), which bears directly on whether the minimal four-method SdkLogger shape is the right long-term surface. That design call belongs to a human maintainer, so I am deferring rather than approving despite finding no correctness issues.
Other factors
Test coverage is good (client logger routing, tool-name warning routing, prompt argsSchema fallback routing, direct standardSchema fallback test), and the docs additions correctly distinguish SDK-internal diagnostics from MCP protocol logging. The codemod versions.ts regeneration matches the corrected changeset targets.
Summary
loggerprotocol option shared by Client, Server, and McpServerSdkLoggertype and add focused coverageFixes #1262
Tests