Skip to content

feat: add injectable SDK logger#2370

Open
mattzcarey wants to merge 4 commits into
mainfrom
feat/injectable-logger
Open

feat: add injectable SDK logger#2370
mattzcarey wants to merge 4 commits into
mainfrom
feat/injectable-logger

Conversation

@mattzcarey

Copy link
Copy Markdown
Contributor

Summary

  • add a logger protocol option shared by Client, Server, and McpServer
  • route client capability diagnostics, tool-name warnings, and zod fallback warnings through the configured logger
  • export the SdkLogger type and add focused coverage

Fixes #1262

Tests

  • pnpm --filter @modelcontextprotocol/client test -- logger.test.ts
  • pnpm --filter @modelcontextprotocol/core test -- standardSchema.zodFallback.test.ts
  • pnpm --filter @modelcontextprotocol/server test -- mcp.compat.test.ts
  • pnpm run typecheck:all
  • pnpm run lint:all
  • pnpm run build:all

@mattzcarey mattzcarey requested a review from a team as a code owner June 25, 2026 13:02
@changeset-bot

changeset-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b5094b5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@modelcontextprotocol/core-internal Minor
@modelcontextprotocol/client Minor
@modelcontextprotocol/server Minor
@modelcontextprotocol/express Major
@modelcontextprotocol/fastify Major
@modelcontextprotocol/hono Major
@modelcontextprotocol/node Major

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

@pkg-pr-new

pkg-pr-new Bot commented Jun 25, 2026

Copy link
Copy Markdown

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@2370

@modelcontextprotocol/codemod

npm i https://pkg.pr.new/@modelcontextprotocol/codemod@2370

@modelcontextprotocol/core

npm i https://pkg.pr.new/@modelcontextprotocol/core@2370

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@2370

@modelcontextprotocol/server-legacy

npm i https://pkg.pr.new/@modelcontextprotocol/server-legacy@2370

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@2370

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@2370

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@2370

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@2370

commit: b5094b5

Comment thread packages/core-internal/src/util/standardSchema.ts
Comment thread packages/core-internal/src/shared/protocol.ts
@mattzcarey mattzcarey force-pushed the feat/injectable-logger branch from 63bb2b4 to f2d0beb Compare June 25, 2026 13:38

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@KKonstantinov

Copy link
Copy Markdown
Contributor

Hey @mattzcarey , we explored this in #1034

You could get some stuff from there, there are some caveats with Stdio, plus following SysLog - RFC5424

@mattzcarey mattzcarey force-pushed the feat/injectable-logger branch from f2d0beb to 103073d Compare June 25, 2026 21:52
Comment thread .changeset/injectable-sdk-logger.md

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inject your own logger

2 participants