Skip to content

Opt Modern backends into log notifications via logLevel _meta - #6140

Open
JAORMX wants to merge 1 commit into
mainfrom
vmcp-modern-logging-meta
Open

Opt Modern backends into log notifications via logLevel _meta#6140
JAORMX wants to merge 1 commit into
mainfrom
vmcp-modern-logging-meta

Conversation

@JAORMX

@JAORMX JAORMX commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

The 2026-07-28 (Modern) MCP revision removed the logging/setLevel RPC — the per-request io.modelcontextprotocol/logLevel _meta key replaces it. modelcontextprotocol/go-sdk#1116 confirmed go-sdk's SetLoggingLevel is wont-fix-by-design on Modern sessions, so a Modern-classified backend never emitted notifications/message through vMCP: the Legacy-only enableBackendLogging RPC doesn't run on the Modern path, and the Modern tools/call never set the logLevel opt-in (a conformant backend MUST NOT emit logs without it).

This adds Modern logging parity with the Legacy path, in two halves (opt-in alone would elicit notifications that were then silently dropped):

  • Opt-in: when server→client forwarding is bound, modernCallTool overlays logLevel: debug onto the request _meta it mints — the Modern analogue of enableBackendLogging. Unbound, the key is omitted so the backend does not emit. All other modernCall sites (discover, list, resources/read, prompts/get, completion) are unchanged.
  • Relay: modernCall/readModernSSE accept an onNotification callback; interleaved SSE notifications are handed to it instead of dropped. modernCallTool wires it to a new newModernNotificationForwarder, relaying notifications/messageNotifyLog and notifications/progressNotifyProgress downstream. A nil listener preserves the prior drop behavior, so non-tool callers are unaffected.

Also exports mcp.MetaKeyLogLevel for the overlay, and reframes two pin comments that attributed the -32020 rejection to a transient upstream bug — it is the standing contract for a removed RPC.

Closes #6130

Type of change

  • Bug fix

Test plan

  • Unit tests (task test)
  • Linting (task lint-fix)

New unit coverage: TestModernCall_LogLevelMeta (key injected / omitted), TestModernCall_SSENotificationRelay (notification delivered AND response still matched), TestModernCallTool_LogLevelGating (bound vs unbound forwarders). Full pkg/vmcp/... and pkg/mcp suites pass.

Changes

File Change
pkg/vmcp/client/modern.go modernCall/readModernEnvelope/readModernSSE/mergeModernMeta take logLevel + onNotification; relay interleaved SSE notifications
pkg/vmcp/client/client.go modernCallTool injects logLevel: debug + wires the notification forwarder when forwarding is bound; other callers pass ""/nil
pkg/vmcp/client/forwarding.go New newModernNotificationForwarder (raw method+params → NotifyLog/NotifyProgress)
pkg/mcp/revision.go Export MetaKeyLogLevel
pkg/vmcp/server/*_integration_test.go Reframe the two logging/setLevel pin comments to go-sdk#1116's wont-fix resolution
docs/arch/10-virtual-mcp-architecture.md Extend the logging limitation with the Modern dimension

Does this introduce a user-facing change?

Yes. vMCP now relays backend log (notifications/message) and progress (notifications/progress) notifications from Modern (2026-07-28) backends to the downstream client when server→client forwarding is bound — previously these were never emitted (no logLevel opt-in) and dropped (no relay). Behavior for Legacy backends and for unbound deployments is unchanged.

Special notes for reviewers

  • Why two halves: injecting logLevel only asks the backend to emit; without the relay, readModernSSE dropped every interleaved notification (env.Method != ""). The opt-in without the relay is a silent no-op, so both land together.
  • SSE-only delivery: the relay fires only on the text/event-stream path; a single JSON 200 body carries no notifications. This is the same inherent limitation as the Legacy standalone-stream design and is documented in the modernCall doc comment.
  • Level is always debug when bound: mirrors the documented limitation (docs/arch/10) that downstream level preferences are not yet applied to the relayed stream — vMCP strips the downstream per-hop logLevel and overlays its own.

The 2026-07-28 (Modern) MCP revision removed the logging/setLevel RPC;
the per-request io.modelcontextprotocol/logLevel _meta key replaces it.
modelcontextprotocol/go-sdk#1116 confirmed go-sdk's SetLoggingLevel is
wont-fix-by-design on Modern sessions, so a Modern backend never emits
notifications/message through vMCP.

When server->client forwarding is bound, modernCallTool now overlays
logLevel: debug onto the request _meta (the Modern analogue of the Legacy
enableBackendLogging) and relays interleaved notifications/message and
notifications/progress from the backend's SSE stream to the downstream
client. The logLevel key and listener are omitted when forwarding is
unbound, and every other Modern call site is unchanged.

Also export mcp.MetaKeyLogLevel for the overlay, and reframe the two
pin comments that attributed the -32020 rejection to a transient upstream
bug — it is the standing contract for a removed RPC.

Closes #6130
@github-actions github-actions Bot added the size/M Medium PR: 300-599 lines changed label Jul 29, 2026
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 44.89796% with 27 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.46%. Comparing base (0a0cbd9) to head (9736750).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
pkg/vmcp/client/forwarding.go 7.69% 23 Missing and 1 partial ⚠️
pkg/vmcp/client/client.go 75.00% 0 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6140      +/-   ##
==========================================
- Coverage   72.56%   72.46%   -0.10%     
==========================================
  Files         734      734              
  Lines       75912    75952      +40     
==========================================
- Hits        55084    55042      -42     
- Misses      16920    17015      +95     
+ Partials     3908     3895      -13     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

size/M Medium PR: 300-599 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vMCP: Modern backends never emit notifications/message — no per-request logLevel _meta opt-in

1 participant