GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Send JSON-RPC error response when a request handler completes empty by ZYZ666-RGB · Pull Request #1099 · modelcontextprotocol/java-sdk

Conversation

@ZYZ666-RGB

@ZYZ666-RGB ZYZ666-RGB commented Aug 18, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

When a server-side request handler returns a Mono that completes empty, the SDK previously sent no response at all for that request, leaving the client waiting indefinitely. This violates JSON-RPC 2.0's one-response-per-request contract.

Motivation and Context

MCP rides on JSON-RPC 2.0, which requires that every request carrying an id receives exactly one response (a result or an error). Two server-side dispatch paths had the gap:

  • McpServerSession.handleIncomingRequest (stateful servers): the empty Mono flowed through .map(...) (no emission) and .onErrorResume(...) (no error), so handle()'s .flatMap(this.transport::sendMessage) was never invoked and no bytes went over the wire.
  • DefaultMcpStatelessServerHandler.handleRequest (stateless servers): same empty propagation; callers doing .block() received null instead of a JSON-RPC response.

An empty completion is a common Reactor idiom (e.g. a reactive repository's get(id) completing empty when nothing matches), so this is a realistic failure mode, not a theoretical one. Fixes #1081.

Both paths now append .switchIfEmpty(...): an empty completion produces exactly one JSON-RPC error response (-32603 Internal error) naming the method, plus a WARN log. Normal result and error behavior is unchanged — switchIfEmpty only fires on empty completion.

How Has This Been Tested?

  • Added regression tests covering all three paths in both dispatch layers:
    • McpServerSessionTests (new): empty completion → exactly one error response with matching id; normal result → result response; failing handler → error response.
    • DefaultMcpStatelessServerHandlerTests (extended): empty handler result → INTERNAL_ERROR response; failing handler → error response.
  • Verified locally with mvn -pl mcp-core test — 6/6 new tests pass, module builds clean with spring-javaformat validation.
  • Full-suite integration tests require Docker and are covered by CI on GitHub.

Breaking Changes

None. This is an additive fix for a previously-broken path (empty handler completion previously produced no response; it now produces an error response). Existing successful/error behavior is byte-for-byte unchanged.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Root cause: Mono.map() does not emit for an empty source and onErrorResume does not trigger without an error, so the empty completion propagated silently through both dispatch chains. The fix converts that silent empty completion into a contract-compliant error response.


Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@ZYZ666-RGB
Send JSON-RPC error response when a request handler completes empty
b9ec3d8
When a server-side request handler returns a Mono that completes empty, McpServerSession.handleIncomingRequest and DefaultMcpStatelessServerHandler.handleRequest propagated the empty completion, so no JSON-RPC response was ever sent for the request. This violates JSON-RPC 2.0's one-response-per-request contract and leaves the client waiting indefinitely.

Both dispatch paths now complete with an internal error (-32603) response when the handler completes without a result, and log a warning naming the method. Normal result and error behavior is unchanged.

Adds regression tests for the empty-completion, normal-result and error paths in both the stateful (McpServerSession) and stateless (DefaultMcpStatelessServerHandler) dispatch layers.

Fixes modelcontextprotocol#1081

Signed-off-by: zhaoyuzhe <[email protected]>
@ZYZ666-RGB ZYZ666-RGB mentioned this pull request Aug 18, 2026
McpServerSession never sends a response when a request handler's Mono completes empty — violates JSON-RPC 2.0's one-response-per-request contract #1081
Open
@ZYZ666-RGB
chore: add required AI contribution disclosure
b75cdfa
This was referenced Sep 3, 2026
Client request handlers that complete empty send no JSON-RPC response #1124
Open
fix(client): respond when request handlers complete empty #1125
Open
@ZYZ666-RGB
Merge branch 'main' into fix/1081-empty-handler-response
97d06f3

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

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

McpServerSession never sends a response when a request handler's Mono completes empty — violates JSON-RPC 2.0's one-response-per-request contract

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@ZYZ666-RGB
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.