Skip to content

[Server][Client] Remove JSON-RPC batch support - #680

Merged
chr-hertel merged 2 commits into
mainfrom
remove-batch-support
Nov 8, 2026
Merged

chr-hertel merged 2 commits into
mainfrom
remove-batch-support

Conversation

@chr-hertel

Copy link
Copy Markdown
Member

MCP removed batching in 2025-06-18, so a JSON array is refused with -32600 for every protocol version - that includes 2025-03-26, which requires batches and which we still negotiate. I didn't find a well-adopted client that sends them, but can't see into the closed-source ones.

[BC Break] MessageFactory::create() returns one message and throws on invalid input, $maxBatchSize is gone - see CHANGELOG.md.

MCP removed batching in 2025-06-18. A JSON array is refused with -32600
for every protocol version, and MessageFactory::create() returns one
message and throws on invalid input.
@chr-hertel chr-hertel added Server Issues & PRs related to the Server component Client Issues & PRs related to the Client component breaking change Breaking the Backwards Compatibility Promise labels Nov 8, 2026
@chr-hertel chr-hertel added this to the 0.10.0 milestone Nov 8, 2026
@chr-hertel
chr-hertel requested a balanced review from Copilot November 8, 2026 12:22

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.

🟡 Changes recommended

An empty JSON array bypasses rejection, allowing a POST with a valid handshake session to return HTTP 200 or SSE instead of the documented HTTP 400.

1 open issue
What changed in this PR

Removes JSON-RPC batch support from the PHP SDK’s server and client, including for negotiated 2025-03-26 connections.

Changes:

  • Changes MessageFactory::create() to return one message and throw on invalid input.
  • Simplifies dispatch, HTTP responses, notification buses, and scope handling for single messages.
  • Updates tests and documentation, and records the breaking changes.
File Description
tests/​Unit/​Server/​Wire/​InboundClassifierTest.php Updates batch classification expectations.
tests/​Unit/​Server/​Transport/​StreamableHttpTransportTest.php Tests batch rejection and single-response ordering.
tests/​Unit/​Server/​Transport/​StdioDualEraTest.php Tests rejection without settling the protocol era.
tests/​Unit/​Server/​Transport/​Http/​OAuth/​ScopePolicyTest.php Tests default scopes for non-message inputs.
tests/​Unit/​Server/​Transport/​Http/​Middleware/​AuthorizationMiddlewareTest.php Removes batch scope-union coverage.
tests/​Unit/​Server/​Transport/​AccessTokenFlowTest.php Verifies rejected batches cannot execute tools.
tests/​Unit/​Server/​Subscription/​NotificationBusTest.php Tests skipping unreadable cached entries.
tests/​Unit/​Server/​ProtocolTest.php Replaces batch processing tests with rejection coverage.
tests/​Unit/​Server/​ProtocolSessionLockTest.php Removes batch-specific lock tests.
tests/​Unit/​Server/​BuilderTest.php Adapts extension assertions to single messages.
tests/​Unit/​JsonRpc/​MessageFactoryTest.php Tests single-message returns and thrown exceptions.
tests/​Unit/​JsonRpc/​MalformedInputTest.php Expects exceptions for malformed input.
tests/​Unit/​Client/​Transport/​StdioTransportTest.php Retains notification ordering coverage without batches.
tests/​Unit/​Client/​Transport/​HttpTransportTest.php Replaces batch fixtures in stream coverage.
tests/​Unit/​Client/​ProtocolTest.php Tests dropping server batches with a warning.
src/​Server/​Wire/​InboundClassifier.php Rejects batches across protocol eras.
src/​Server/​Transport/​TransportInterface.php Updates single-response documentation.
src/​Server/​Transport/​StreamableHttpTransport.php Stores and returns one JSON-RPC response.
src/​Server/​Transport/​StdioTransport.php Adapts routing and cancellation parsing.
src/​Server/​Transport/​Http/​OAuth/​ScopePolicy.php Computes scopes for one decoded message.
src/​Server/​Subscription/​Psr6NotificationBus.php Parses one notification per cached entry.
src/​Server/​Subscription/​Psr16NotificationBus.php Parses one notification per cached entry.
src/​Server/​Stateless/​StatelessProtocol.php Handles factory validation exceptions.
src/​Server/​Protocol.php Simplifies dispatch and session resolution.
src/​JsonRpc/​MessageFactory.php Removes batch parsing and size configuration.
src/​Client/​Transport/​HttpTransport.php Matches individual stream responses only.
src/​Client/​Protocol.php Dispatches one message and logs invalid input.
docs/​run/​protocol-eras.md Documents batch rejection across eras.
docs/​run/​http.md Replaces batch-limit guidance with rejection behavior.
CHANGELOG.md Records server, client, and factory breaking changes.

Review effort: Balanced

Comment thread src/Server/Wire/InboundClassifier.php Resolved
It decoded like {} and got past the classifier, which answered it with HTTP 200 in a session.
@chr-hertel
chr-hertel merged commit 5d026c4 into main Nov 8, 2026
34 checks passed
@chr-hertel
chr-hertel deleted the remove-batch-support branch November 8, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Breaking the Backwards Compatibility Promise Client Issues & PRs related to the Client component Server Issues & PRs related to the Server component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants