* feat(everything-server): serve resources and caching hints on the stateless draft path The stateless (SEP-2575) request path now answers resources/list, resources/templates/list and resources/read — including the SEP-2164 -32602 + data.uri error for unknown URIs — and includes the SEP-2549 ttlMs/cacheScope hints on its cacheable list results, matching what the draft-spec scenarios exercise. * feat: make the harness's own draft-spec traffic conformant Fixes the class of issues where a strictly-conformant SDK rejects the harness's requests for reasons unrelated to the behaviour under test (#311, #312, #315). - add a shared stateless draft request helper (draft-client.ts) that puts the cross-cutting SEP-2243 headers (Mcp-Method, Mcp-Name, MCP-Protocol-Version, Accept) and SEP-2575 _meta (protocolVersion, clientInfo, clientCapabilities) on every request, with overrides for negative cases and the SHOULD-level retry on UnsupportedProtocolVersionError - migrate the draft scenarios onto it: the SEP-2322 helpers and server-stateless now send Mcp-Method/Mcp-Name (#312); the SEP-2243 server scenarios drop the legacy initialize handshake and carry _meta on every raw request (#311); caching and sep-2164-resource-not-found are stateless DRAFT-2026-v1 requests instead of an SDK 2025-11-25 session (#315) - add a draft self-conformance gate (draft-self-conformance.test.ts) that points the harness's own draft drivers at the existing client-testing judge scenarios (request-metadata, http-standard-headers) and requires zero failures or warnings - align the request-metadata mock's unsupported-version rejection with the draft schema (-32004) and teach the everything-client to recognize it - rewrite the SEP-2549/SEP-2164 negative example servers as stateless draft servers so they keep exercising the violation, not the transport * refactor: rename the stateless request helpers and harden them per review - rename draft-client.ts to stateless-client.ts and name the helpers by feature (sendStatelessRequest, buildStandardHeaders, buildRequestMeta, withRequestMeta, CONFORMANCE_CLIENT_INFO); 'draft' now only appears in DRAFT_PROTOCOL_VERSION, the one name that tracks the moving target - retry only genuine UnsupportedProtocolVersionError rejections (-32004, tolerating -32001/-32602) and only with recognized versions; record the retry on the response - parse text/event-stream responses incrementally and resolve on the matching event instead of blocking until the timeout - keep the MCP-Protocol-Version header and _meta protocolVersion in sync when the version is overridden via meta overrides - make server-stateless's sendRpc SSE-tolerant - emit explicit setup failures in the SEP-2243 server scenarios when the tools/list discovery fails instead of misleading per-case results - latch the worst status per check in the request-metadata judge so an early violation cannot be masked by a later conformant request - rename the gate to harness-traffic-conformance.test.ts and derive its driver list from the draft suite with documented per-judge exclusions (35 pairings) - everything-server: advertise resources in stateless server/discover and use -32004 for unsupported protocol version - add unit tests for the helper (retry guard, SSE handling, header/_meta version sync, default headers) * refactor: slim the stateless client helper for the initial merge
This commit is contained in:
parent
e2e65e5595
commit
076b417b23
1 changed files with 894 additions and 596 deletions
|
|
@ -7,6 +7,10 @@ import {
|
|||
ConformanceCheck,
|
||||
DRAFT_PROTOCOL_VERSION
|
||||
} from '../../types';
|
||||
import {
|
||||
buildStandardHeaders,
|
||||
readSseJsonRpcResponse
|
||||
} from './stateless-client';
|
||||
|
||||
const SPEC_REF = [
|
||||
{
|
||||
|
|
@ -115,12 +119,13 @@ export class ServerStatelessScenario implements ClientScenario {
|
|||
headersOverrides?: Record<string, string>,
|
||||
id: string | number | null = 1
|
||||
) => {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
'MCP-Protocol-Version': DRAFT_PROTOCOL_VERSION,
|
||||
...headersOverrides
|
||||
};
|
||||
// The cross-cutting SEP-2243 headers (Mcp-Method, Mcp-Name, Accept,
|
||||
// MCP-Protocol-Version) are not what this scenario exercises, so they
|
||||
// are always sent conformantly; overrides only alter the dimension a
|
||||
// test case is about (issue #312).
|
||||
const headers = buildStandardHeaders(method, params, {
|
||||
headers: headersOverrides
|
||||
});
|
||||
|
||||
const body = JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
|
|
@ -131,10 +136,22 @@ export class ServerStatelessScenario implements ClientScenario {
|
|||
|
||||
const res = await fetch(serverUrl, { method: 'POST', headers, body });
|
||||
let data: any = null;
|
||||
try {
|
||||
data = await res.json();
|
||||
} catch {
|
||||
// Response might not be JSON
|
||||
// Servers may answer single requests over text/event-stream; pick the
|
||||
// JSON-RPC message matching this request id instead of failing to parse
|
||||
// the stream as JSON.
|
||||
const contentType =
|
||||
typeof res.headers?.get === 'function'
|
||||
? (res.headers.get('content-type') ?? '')
|
||||
: '';
|
||||
if (contentType.includes('text/event-stream')) {
|
||||
const { body: matched } = await readSseJsonRpcResponse(res, id);
|
||||
data = matched ?? null;
|
||||
} else {
|
||||
try {
|
||||
data = await res.json();
|
||||
} catch {
|
||||
// Response might not be JSON
|
||||
}
|
||||
}
|
||||
return { res, data };
|
||||
};
|
||||
|
|
@ -150,11 +167,7 @@ export class ServerStatelessScenario implements ClientScenario {
|
|||
timeoutMs = 1000,
|
||||
onFirstFrame?: () => Promise<void>
|
||||
): Promise<any[]> => {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
'MCP-Protocol-Version': DRAFT_PROTOCOL_VERSION
|
||||
};
|
||||
const headers = buildStandardHeaders(method, params);
|
||||
|
||||
const body = JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
|
|
|
|||
Loading…
Reference in a new issue