Skip to content

fix: include required result members in 2026-07-28 mock responses#341

Merged
pcarleton merged 1 commit into
mainfrom
fweinberger/2026-mock-result-type
Jun 16, 2026
Merged

fix: include required result members in 2026-07-28 mock responses#341
pcarleton merged 1 commit into
mainfrom
fweinberger/2026-mock-result-type

Conversation

@felixweinberger

Copy link
Copy Markdown
Collaborator

The mock servers used for client-direction scenarios return results that are not valid for the 2026-07-28 revision: they omit resultType, and the cacheable results also omit ttlMs/cacheScope. This makes those results spec-valid so the suite can no longer fail a strictly-conforming client because of its own mock.

Motivation and Context

At 2026-07-28, results from servers must include resultType ("The result MUST include a resultType field", basic/index §Result responses; Result.resultType in schema/draft/schema.ts: "Servers implementing this protocol version MUST include this field"), and the six cacheable operations (server/discover, tools/list, prompts/list, resources/list, resources/templates/list, resources/read) must also include ttlMs and cacheScope (CacheableResult, server/utilities/caching). The suite's own server-direction check sep-2322-result-type-included already enforces the resultType MUST against servers under test.

The client-direction mocks don't follow it themselves: the stateless mock wraps scenario handler results verbatim and its built-in server/discover result has none of these members, and the hand-rolled per-scenario servers (SEP-2243/2575/2322 scenarios, the auth helper) build results without them. The absent⇒complete bridge in the spec is explicitly scoped to earlier-revision servers, so a client that validates 2026-07-28 results strictly is correct to reject these — and then can't pass tools_call (or other carry-forward scenarios) at --spec-version 2026-07-28 even though the non-conformant party is the mock.

What changed

  • src/mock-server/stateless.ts: new withRequiredDraftResultFields(method, result) helper (exported via src/mock-server/index.ts) fills resultType: "complete" on every result and ttlMs: 0 / cacheScope: "private" on cacheable-method results, preserving anything the handler set itself. Applied to the handler wrap point and the built-in server/discover result, so every ctx.createServer-based scenario is covered.
  • Hand-rolled scenario servers: the SEP-2243 scenarios (http-standard-headers, http-custom-headers, http-invalid-tool-headers), request-metadata, sep-2322-client-request-state, the auth helper's stateless path, and json-schema-ref-no-deref's tools/list now return the required members. Method-dispatched fallbacks (sendGenericResult, the request-metadata generic reply, the auth helper) route through the shared helper so cacheable methods that fall through still get the caching hints; fixed per-method literals carry the members explicitly so the wire shape stays visible at the emission site.
  • Deliberate exception: the sep-2322-default-result-type-complete probe in sep-2322-client-request-state still omits resultType — that omission is the check's stimulus.
  • Tests: mock-server.test.ts pins the helper and the stateless wrap point; tools_call.test.ts gains a draft-mode case asserting the scenario serves spec-valid 2026-07-28 results; new draft-result-fields.test.ts pins the hand-rolled scenario servers (including the fallback path and the preserved deliberate omission).

How Has This Been Tested?

  • npm run check, npm run build, npm test: all green (285 tests, including the new response-shape pins).
  • node dist/index.js client --command "npx tsx examples/clients/typescript/everything-client.ts" --suite draft before and after the change: identical results (115 passed / 9 failed — the 9 are pre-existing gaps in the bundled example client, unrelated to result shapes), so existing clients see no behavior change beyond the added members.

Breaking Changes

None for clients: the added members are required by the 2026-07-28 schema and ignored by earlier-revision clients. Note for SDK consumers: SDKs pin published releases, so a strict 2026 client can only pass the affected client-direction scenarios once a release containing this change is published (next alpha).

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

  • The sep-2322-default-result-type-complete check exercises the absent⇒complete bridge against a mock that claims 2026-07-28; per the spec the bridge is scoped to earlier-revision servers, so that check may want re-scoping or rewording — left out of this PR as a follow-up question.
  • json-schema-ref-no-deref serves everything except tools/list through the bundled 1.x SDK transport (initialize handshake, no server/discover), so the scenario as a whole is still not a conformant 2026-07-28 server; making it one needs a separate rework coordinated with the example client.
  • An all-checks-SKIPPED scenario currently reports as passed (e.g. http-custom-header-server-validation against a server with no x-mcp-header tool); deliberately not touched here, will be raised separately.

At the 2026-07-28 revision every server result must include resultType,
and cacheable results (server/discover, tools/list, prompts/list,
resources/list, resources/templates/list, resources/read) must also
include ttlMs and cacheScope. The client-direction mock servers omitted
these, so a strictly-validating client was failed by the suite's own
non-conformant mock.

The shared stateless mock now stamps the missing members onto handler
results and its server/discover response (withRequiredDraftResultFields),
and the hand-rolled per-scenario servers set them explicitly or route
their fallbacks through the helper. The deliberately resultType-less
probe in sep-2322-client-request-state is unchanged. New tests pin the
response shapes.
@pkg-pr-new

pkg-pr-new Bot commented Jun 16, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/@modelcontextprotocol/conformance@341

commit: 99ac073

jsonrpc: '2.0',
id,
result: {
result: withRequiredDraftResultFields(method, {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

this is only happening in the stateless branch of the auth helper

@pcarleton pcarleton merged commit b9041ea into main Jun 16, 2026
8 checks passed
@pcarleton pcarleton deleted the fweinberger/2026-mock-result-type branch June 16, 2026 14:13
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.

2 participants