Skip to content

feat(transport): add logLevel; keep message traffic out of the console by default - #808

Open
AlmogBaku wants to merge 1 commit into
modelcontextprotocol:mainfrom
AlmogBaku:almogbaku/transport-log-level
Open

AlmogBaku wants to merge 1 commit into
modelcontextprotocol:mainfrom
AlmogBaku:almogbaku/transport-log-level

Conversation

@AlmogBaku

Copy link
Copy Markdown

Fixes #786.

Problem

PostMessageTransport logs every message it sends, receives, or ignores with console.debug, and a host can't turn that off. Each card's transport listens on the same window, so with N Apps on a page every View message produces N host lines. The full payloads, including tool-result _meta, also reach anything that records the console: test runners, Playwright, and error-reporting breadcrumbs (#741).

Change

A logLevel option, using MCP's own LoggingLevel names:

new PostMessageTransport(window.parent, window.parent, { logLevel: "debug" });
new App(appInfo, capabilities, { logLevel: "debug" }); // the transport connect() creates
useApp({ appInfo, capabilities, logLevel: "debug" });
  • Message traffic is logged at "debug". The default level is "warning", so traffic stays out of the console unless asked for.
  • A malformed JSON-RPC message is logged at "error" and still prints by default. onerror fires at every level.
  • Lines still go through console.debug / console.error, so DevTools filtering keeps working once logging is on.
  • An unrecognized level (for example "warn" from untyped code) falls back to the default instead of logging everything.
  • The tool-input-partial skip from fix: skip debug log for high-frequency tool-input-partial notifications #546 stays.
  • PostMessageTransportOptions is exported from . and ./app-bridge, and the class docs gain a Logging section with a type-checked example.

The issue first proposed a logger object. A level is a single plain value, so a server can pass its own log setting (an env variable or flag) into the View it serves, and it reuses names MCP already defines.

examples/integration-server opts in to "debug": tests/e2e/security.spec.ts ("app rejects messages from sources other than its parent") proves the source check by waiting for the transport's "Ignoring message from unknown source" line.

Behavior change

Code that relied on the transport's debug lines no longer sees them unless it sets logLevel: "debug". No API breaks; existing two-argument constructors still work.

Compared with #803

#803 makes the lines opt-in through a logger object. Differences here:

Testing

  • npm test: 446 pass, 2 skip, 0 fail. New cases in src/message-transport.test.ts: traffic stays silent at the default and at an unrecognized level; all four traffic lines log at "debug"; tool-input-partial is still skipped at "debug"; a malformed message prints at the default and at "error", is dropped at "critical", and calls onerror each time; App.connect() builds its transport at the App's level. Breaking each guarded line makes its test fail.
  • npm run build, tsc --noEmit, npm run prettier, typedoc --treatValidationWarningsAsErrors --emit none, and scripts/check-dependency-isolation.mjs pass. The pre-commit build:all passes.
  • EXAMPLE=integration-server npx playwright test tests/e2e/security.spec.ts --project=chromium --workers=2: 14 passed locally. The pinned Chromium download stalled, so this run used the newer cached build 1248.

🤖 Generated with Claude Code

…e by default

PostMessageTransport logged every message it sent, received, or ignored
with console.debug, and hosts had no way to turn it off. With several Apps
on a page, each View message produced one line per card, and full payloads
reached anything that records the console.

Add a logLevel option using MCP's LoggingLevel names. Message traffic is
logged at "debug" and the default is "warning", so it stays off unless
asked for. A malformed JSON-RPC message is logged at "error" and onerror
fires regardless of level. An unrecognized level falls back to the
default. App and useApp pass the level to the transport they create.

The integration example opts in to "debug": the cross-App injection e2e
test proves the source check by reading the transport's debug line.

Fixes modelcontextprotocol#786

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The focused changes preserve transport behavior and compatibility, with regression coverage and no unresolved findings.

0 open findings

What changed in this PR

Makes transport message logging opt-in, reducing console noise and default exposure of message payloads.

Changes:

  • Adds configurable logging levels, defaulting to "warning".
  • Exposes logging options through App, useApp, and package exports.
  • Adds regression tests, documentation, and explicit debug logging for security tests.
File Description
src/​react/​useApp.tsx Forwards the logging level to the transport.
src/​message-transport.ts Adds logging options and severity filtering.
src/​message-transport.test.ts Tests logging controls and App option forwarding.
src/​message-transport.examples.ts Adds a debug logging example.
src/​app.ts Exposes logging options and configures default transports.
src/​app-bridge.ts Exports the transport options type.
examples/​integration-server/​src/​mcp-app.tsx Enables debug output required by security tests.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

This branch has not been deployed

No deployments
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.

PostMessageTransport: make debug logging opt-in (or accept a logger)

2 participants