Skip to content

[Tests] Introduce client-server integration tests - #419

Merged
chr-hertel merged 3 commits into
modelcontextprotocol:mainfrom
chr-hertel:client-server-integration-tests
Aug 15, 2026
Merged

[Tests] Introduce client-server integration tests#419
chr-hertel merged 3 commits into
modelcontextprotocol:mainfrom
chr-hertel:client-server-integration-tests

Conversation

@chr-hertel

@chr-hertel chr-hertel commented Aug 14, 2026

Copy link
Copy Markdown
Member

Every other suite mocks one side of the conversation. This one runs a real client against a real server, so what it covers is the agreement between the two halves rather than either half against an expectation of the other.

The setup

The same wiring as examples/client: the client spawns a server script over the real StdioTransport and the two talk across its pipes. No test doubles on either side, and the transports carrying the exchange are the ones users get — framing, buffering and process lifecycle included.

The servers live in tests/Integration/Fixture, one script per scenario, written the way examples/server writes them. HandshakeTest pins the server's revision through the environment, since that is a property of the process here.

Client timeouts are pinned to 5s, so a stalled exchange fails the test instead of hanging the suite.

Coverage

  • Handshake — the negotiation matrix across both implementations, including counter-offers and the modern-era fallbacks
  • Elicitation — accept, decline, capability absent, advertised without a handler
  • Sampling — result, prompt contents, refusal
  • Roots — populated, empty, capability absent, list-changed
  • Notifications — progress delivery and the token-less skip, log delivery

27 tests in ~3s. Runs as its own CI job over PHP 8.1–8.5, in parallel with the rest of the pipeline; make integration-tests runs it locally.

* Add an in-process loopback that connects a real client transport to a real
  server transport, draining both Fiber loops in one synchronous pass instead
  of polling. A stalled exchange fails where it happened rather than hanging.
* Cover protocol version negotiation across both implementations, where the
  unit tests only ever drive one side against a canned counter-offer.
* Cover the server-to-client round-trips end to end: elicitation, sampling,
  roots, plus progress and logging notifications.
* Add the `integration` test suite and a `make integration-tests` target.
The unit job pins `--testsuite=unit`, so the new suite would never have run on
GitHub. It goes in that job rather than its own: the loopback leans on Fibers,
and the matrix is what covers them down to the PHP 8.1 floor.
@chr-hertel
chr-hertel force-pushed the client-server-integration-tests branch from 43a0828 to 0413e9f Compare August 14, 2026 23:45
Replaces the in-process loopback with the setup from examples/client: the
client spawns a fixture server over the real StdioTransport, so the tests
exercise the shipped transports and no longer nest both sides' Fibers.

Moves the suite into its own CI job, matrixed over PHP 8.1-8.5.
@chr-hertel
chr-hertel force-pushed the client-server-integration-tests branch from fb6268b to 867d25b Compare August 15, 2026 00:20
@chr-hertel
chr-hertel merged commit 7b12dc4 into modelcontextprotocol:main Aug 15, 2026
23 checks passed
@chr-hertel
chr-hertel deleted the client-server-integration-tests branch August 15, 2026 00:24
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.

1 participant