Align SEP-2575 checks with spec PR #3002: serverInfo in result _meta, clientInfo optional (#403)

Spec PR #3002 (part of the final 2026-07-28 revision) moved serverInfo from
the DiscoverResult body to _meta['io.modelcontextprotocol/serverInfo'] and
demoted the request envelope's clientInfo from required to SHOULD. The
checks still asserted the old shape, failing SDKs that follow the final
revision.

- Vendor schema types at spec commit 71e30695.
- server-stateless: drop the missing-clientInfo rejection case and assert
  the opposite (a clientInfo-less request must be served, new check
  sep-2575-request-meta-client-info-optional); discover no longer requires
  body serverInfo; new SHOULD-level check
  sep-2575-server-identifies-in-result-meta (WARNING when the _meta
  identity is absent, SKIPPED when discover itself failed).
- request-metadata (client side): the clientInfo SHOULD moves out of the
  MUST check into its own id sep-2575-client-sends-client-info (WARNING on
  absence), so requirement levels never blend in one check id.
- Mock servers and the everything-server example emit the _meta identity
  and accept clientInfo-less requests.
This commit is contained in:
Felix Weinberger 2026-07-17 18:03:39 +01:00 • committed by GitHub
commit d1c0b95917
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 237 additions and 120 deletions

View file

@ -1266,11 +1266,11 @@ app.post('/mcp', async (req, res) => {
// Per-Request Metadata Integrity Checks (Fields verification). // Per-Request Metadata Integrity Checks (Fields verification).
// A request missing any required `_meta` field is malformed: -32602 and, // A request missing any required `_meta` field is malformed: -32602 and,
// on HTTP, status 400 Bad Request. // on HTTP, status 400 Bad Request. `clientInfo` is a SHOULD since spec
// PR #3002 and is never required.
if ( if (
!meta || !meta ||
!meta['io.modelcontextprotocol/protocolVersion'] || !meta['io.modelcontextprotocol/protocolVersion'] ||
!meta['io.modelcontextprotocol/clientInfo'] ||
!meta['io.modelcontextprotocol/clientCapabilities'] !meta['io.modelcontextprotocol/clientCapabilities']
) { ) {
return res.status(400).json({ return res.status(400).json({
@ -1372,7 +1372,13 @@ app.post('/mcp', async (req, res) => {
// served on this path, so the capability must be declared too. // served on this path, so the capability must be declared too.
resources: {} resources: {}
}, },
serverInfo: { name: 'everything-stateless-server', version: '1.0.0' } // Spec PR #3002: server identity lives in the result `_meta`.
_meta: {
'io.modelcontextprotocol/serverInfo': {
name: 'everything-stateless-server',
version: '1.0.0'
}
}
} }
}); });
} }

View file

@ -252,7 +252,10 @@ describe('createServerStateless', () => {
); );
expect(status).toBe(200); expect(status).toBe(200);
expect(body.result.supportedVersions).toEqual(STATELESS_SPEC_VERSIONS); expect(body.result.supportedVersions).toEqual(STATELESS_SPEC_VERSIONS);
expect(body.result.serverInfo.name).toBe('conformance-mock-server'); // Spec PR #3002: server identity lives in the result `_meta`.
expect(body.result._meta['io.modelcontextprotocol/serverInfo'].name).toBe(
'conformance-mock-server'
);
} finally { } finally {
await srv.close(); await srv.close();
} }

View file

@ -1,8 +1,9 @@
/** /**
* Stateless mock server: 2026-x lifecycle (SEP-2575). * Stateless mock server: 2026-x lifecycle (SEP-2575).
* *
* No initialize handshake. Validates `_meta` (protocolVersion / clientInfo / * No initialize handshake. Validates `_meta` (protocolVersion /
* clientCapabilities) and the `MCP-Protocol-Version` header on every request, * clientCapabilities — `clientInfo` is a SHOULD since spec PR #3002 and is
* never required) and the `MCP-Protocol-Version` header on every request,
* serves `server/discover`, and routes other methods to the supplied handlers. * serves `server/discover`, and routes other methods to the supplied handlers.
* Implemented with raw express so it can front-run SDK support. * Implemented with raw express so it can front-run SDK support.
*/ */
@ -14,9 +15,13 @@ import type { MockServer, RequestHandlers } from './index';
import { STATELESS_SPEC_VERSIONS } from '../connection/select'; import { STATELESS_SPEC_VERSIONS } from '../connection/select';
import { capabilitiesFromHandlers } from './stateful'; import { capabilitiesFromHandlers } from './stateful';
/**
* The required per-request `_meta` keys. `io.modelcontextprotocol/clientInfo`
* is deliberately absent: spec PR #3002 demoted it to SHOULD, so a request
* without it is valid.
*/
const META_KEYS = [ const META_KEYS = [
'io.modelcontextprotocol/protocolVersion', 'io.modelcontextprotocol/protocolVersion',
'io.modelcontextprotocol/clientInfo',
'io.modelcontextprotocol/clientCapabilities' 'io.modelcontextprotocol/clientCapabilities'
] as const; ] as const;
@ -156,7 +161,14 @@ export function validateStatelessRequest(
result: withRequiredDraftResultFields(method, { result: withRequiredDraftResultFields(method, {
supportedVersions, supportedVersions,
capabilities, capabilities,
serverInfo: { name: 'conformance-mock-server', version: '1.0.0' } // Spec PR #3002: server identity lives in the result `_meta`, not
// the DiscoverResult body.
_meta: {
'io.modelcontextprotocol/serverInfo': {
name: 'conformance-mock-server',
version: '1.0.0'
}
}
}) })
} }
}; };

View file

@ -32,6 +32,7 @@ const STATUS_SEVERITY: Record<CheckStatus, number> = {
export const DECLARED_CHECK_IDS = [ export const DECLARED_CHECK_IDS = [
'sep-2575-http-client-sends-version-header', 'sep-2575-http-client-sends-version-header',
'sep-2575-client-populates-meta', 'sep-2575-client-populates-meta',
'sep-2575-client-sends-client-info',
'sep-2575-http-version-header-matches-meta', 'sep-2575-http-version-header-matches-meta',
'sep-2575-client-declares-roots-capability', 'sep-2575-client-declares-roots-capability',
'sep-2575-client-declares-sampling-capability', 'sep-2575-client-declares-sampling-capability',
@ -161,17 +162,19 @@ export class RequestMetadataScenario implements Scenario {
// 2. "Every client request MUST include the following // 2. "Every client request MUST include the following
// io.modelcontextprotocol/* fields in _meta: protocolVersion, // io.modelcontextprotocol/* fields in _meta: protocolVersion,
// clientInfo, clientCapabilities." // clientCapabilities." clientInfo is a SHOULD since spec PR #3002 and
// is tracked by its own check below, so requirement levels never blend
// in one check id.
const hasClientInfo = meta?.['io.modelcontextprotocol/clientInfo']; const hasClientInfo = meta?.['io.modelcontextprotocol/clientInfo'];
const hasCapabilities = const hasCapabilities =
meta?.['io.modelcontextprotocol/clientCapabilities']; meta?.['io.modelcontextprotocol/clientCapabilities'];
const metaIsValid = metaVersion && hasClientInfo && hasCapabilities; const metaIsValid = metaVersion && hasCapabilities;
this.addOrUpdateCheck({ this.addOrUpdateCheck({
id: 'sep-2575-client-populates-meta', id: 'sep-2575-client-populates-meta',
name: 'ClientPopulatesMeta', name: 'ClientPopulatesMeta',
description: description:
'Client populates _meta on every request with all three required fields', 'Client populates _meta on every request with the required fields (protocolVersion, clientCapabilities)',
status: metaIsValid ? 'SUCCESS' : 'FAILURE', status: metaIsValid ? 'SUCCESS' : 'FAILURE',
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
specReferences: [ specReferences: [
@ -183,6 +186,24 @@ export class RequestMetadataScenario implements Scenario {
details: { method: request.method, meta } details: { method: request.method, meta }
}); });
// 2b. clientInfo SHOULD (spec PR #3002): absence is a WARNING, never a
// FAILURE — a dedicated id so adoption is trackable on its own.
this.addOrUpdateCheck({
id: 'sep-2575-client-sends-client-info',
name: 'ClientSendsClientInfo',
description:
"Client SHOULD include io.modelcontextprotocol/clientInfo in every request's _meta (spec PR #3002)",
status: hasClientInfo ? 'SUCCESS' : 'WARNING',
timestamp: new Date().toISOString(),
specReferences: [
{
id: 'SEP-2575',
url: 'https://modelcontextprotocol.io/specification/draft/basic/index#meta'
}
],
details: { method: request.method, meta }
});
// 3. "The header value MUST match the io.modelcontextprotocol/protocolVersion // 3. "The header value MUST match the io.modelcontextprotocol/protocolVersion
// field carried in the request body's _meta." Only comparable when both // field carried in the request body's _meta." Only comparable when both
// are present; absence is already covered by the two checks above, so // are present; absence is already covered by the two checks above, so

View file

@ -29,13 +29,14 @@ export class ServerStatelessScenario implements ClientScenario {
**Server Implementation Requirements:** **Server Implementation Requirements:**
**Endpoints**: **Endpoints**:
- \`server/discover\`: Returns supportedVersions, capabilities, and serverInfo metadata. - \`server/discover\`: Returns supportedVersions and capabilities; SHOULD identify itself via \`_meta['io.modelcontextprotocol/serverInfo']\` (spec PR #3002).
- \`tools/call\`: Implement structural test tools like \`test_missing_capability\` requiring explicit capabilities in \`_meta\`. - \`tools/call\`: Implement structural test tools like \`test_missing_capability\` requiring explicit capabilities in \`_meta\`.
**Grouped Specification Requirements**: **Grouped Specification Requirements**:
1. **Per-Request _meta Validation (5 Checks)** 1. **Per-Request _meta Validation (4 Checks)**
- Rejects requests missing \`_meta\` or lacking structural required internal subfields (\`protocolVersion\`, \`clientInfo\`, \`clientCapabilities\`) with a JSON-RPC \`-32602 Invalid params\` error signature and an HTTP status code \`400 Bad Request\`. - Rejects requests missing \`_meta\` or lacking structural required internal subfields (\`protocolVersion\`, \`clientCapabilities\`) with a JSON-RPC \`-32602 Invalid params\` error signature and an HTTP status code \`400 Bad Request\`.
- Serves requests whose \`_meta\` omits \`clientInfo\` (a SHOULD since spec PR #3002 — servers MUST NOT require it).
2. **Discovery & Capabilities (3 Checks)** 2. **Discovery & Capabilities (3 Checks)**
- Implements \`server/discover\` mapping exact mandatory protocol elements. - Implements \`server/discover\` mapping exact mandatory protocol elements.
- Dynamically checks prompt capability declaration constraints, validates that active RPC handlers match advertised discovery capacities. - Dynamically checks prompt capability declaration constraints, validates that active RPC handlers match advertised discovery capacities.
@ -332,20 +333,8 @@ export class ServerStatelessScenario implements ClientScenario {
}, },
rpcId: 102 rpcId: 102
}, },
{ // No 'missing-client-info' case: spec PR #3002 demoted clientInfo to
slug: 'missing-client-info', // SHOULD, so its absence is valid (asserted positively below).
description:
'Rejects request with _meta missing io.modelcontextprotocol/clientInfo',
params: {
_meta: {
'io.modelcontextprotocol/protocolVersion':
validMeta['io.modelcontextprotocol/protocolVersion'],
'io.modelcontextprotocol/clientCapabilities':
validMeta['io.modelcontextprotocol/clientCapabilities']
}
},
rpcId: 103
},
{ {
slug: 'missing-client-capabilities', slug: 'missing-client-capabilities',
description: description:
@ -411,6 +400,45 @@ export class ServerStatelessScenario implements ClientScenario {
); );
} }
// Positive companion (spec PR #3002): clientInfo is a SHOULD — a request
// whose _meta omits it MUST be served, not rejected.
const noClientInfoProbe = await sendRpc(
'server/discover',
{
_meta: {
'io.modelcontextprotocol/protocolVersion':
validMeta['io.modelcontextprotocol/protocolVersion'],
'io.modelcontextprotocol/clientCapabilities':
validMeta['io.modelcontextprotocol/clientCapabilities']
}
},
undefined,
105
).catch(() => null);
const noClientInfoData: any = noClientInfoProbe?.data;
await runCheck(
'sep-2575-request-meta-client-info-optional',
'RequestMetaClientInfoOptional',
'Serves requests whose _meta omits io.modelcontextprotocol/clientInfo (clientInfo is a SHOULD).',
() => {
if (!noClientInfoProbe)
return { error: 'clientInfo-less probe failed completely' };
if (noClientInfoData?.error) {
return {
error: `Expected a result, got error ${noClientInfoData.error.code}: ${noClientInfoData.error.message}`,
details: { response: noClientInfoData }
};
}
if (noClientInfoProbe.res?.status !== 200) {
return {
error: `Expected HTTP 200, got status code ${noClientInfoProbe.res?.status}`,
details: { response: noClientInfoData }
};
}
return { details: { response: noClientInfoData } };
}
);
// ========================================== // ==========================================
// 2. Discovery & Capabilities (4 Checks) // 2. Discovery & Capabilities (4 Checks)
// ========================================== // ==========================================
@ -448,10 +476,12 @@ export class ServerStatelessScenario implements ClientScenario {
() => { () => {
if (discoverRpcError) if (discoverRpcError)
return { error: `Discovery failed: ${discoverRpcError.message}` }; return { error: `Discovery failed: ${discoverRpcError.message}` };
// Mandatory body fields per the final revision (spec PR #3002 removed
// body serverInfo — identity is a SHOULD in the result _meta, checked
// separately below).
if ( if (
!discoverResult?.supportedVersions || !discoverResult?.supportedVersions ||
!discoverResult?.capabilities || !discoverResult?.capabilities
!discoverResult?.serverInfo
) { ) {
return { return {
error: 'Missing mandatory fields in discover response setup', error: 'Missing mandatory fields in discover response setup',
@ -462,6 +492,38 @@ export class ServerStatelessScenario implements ClientScenario {
} }
); );
await runCheck(
'sep-2575-server-identifies-in-result-meta',
'ServerIdentifiesInResultMeta',
"Servers SHOULD identify themselves via _meta['io.modelcontextprotocol/serverInfo'] on responses (spec PR #3002).",
() => {
if (discoverRpcError)
// Discover itself failed (already a FAILURE on the implements-
// discover check): nothing is known about identity, so the gap
// must not read as an intentional absence.
return {
skipped: true,
details: {
note: `Prerequisite missing: ${discoverRpcError.message}`
}
};
const metaServerInfo =
discoverResult?._meta?.['io.modelcontextprotocol/serverInfo'];
if (!metaServerInfo?.name || !metaServerInfo?.version) {
const bodyServerInfo = discoverResult?.serverInfo;
return {
// SHOULD-level: WARNING, never FAILURE.
warning: true,
error: bodyServerInfo
? 'serverInfo found only in the pre-#3002 result body, not in _meta'
: 'No serverInfo in the discover result _meta',
details: { result: discoverResult }
};
}
return { details: { serverInfo: metaServerInfo } };
}
);
await runCheck( await runCheck(
'sep-2575-server-declares-prompts-in-discover', 'sep-2575-server-declares-prompts-in-discover',
'ServerDeclaresPromptsInDiscover', 'ServerDeclaresPromptsInDiscover',

View file

@ -1234,9 +1234,7 @@ export type ClientResult = EmptyResult | CreateMessageResult | ListRootsResult;
/* Server messages */ /* Server messages */
export type ServerRequest = export type ServerRequest =
| PingRequest PingRequest | CreateMessageRequest | ListRootsRequest;
| CreateMessageRequest
| ListRootsRequest;
export type ServerNotification = export type ServerNotification =
| CancelledNotification | CancelledNotification

View file

@ -6,10 +6,7 @@
* @category JSON-RPC * @category JSON-RPC
*/ */
export type JSONRPCMessage = export type JSONRPCMessage =
| JSONRPCRequest JSONRPCRequest | JSONRPCNotification | JSONRPCResponse | JSONRPCError;
| JSONRPCNotification
| JSONRPCResponse
| JSONRPCError;
/** @internal */ /** @internal */
export const LATEST_PROTOCOL_VERSION = "2025-06-18"; export const LATEST_PROTOCOL_VERSION = "2025-06-18";
@ -1134,11 +1131,7 @@ export interface Annotations {
* @category Content * @category Content
*/ */
export type ContentBlock = export type ContentBlock =
| TextContent TextContent | ImageContent | AudioContent | ResourceLink | EmbeddedResource;
| ImageContent
| AudioContent
| ResourceLink
| EmbeddedResource;
/** /**
* Text provided to or from an LLM. * Text provided to or from an LLM.
@ -1490,10 +1483,7 @@ export interface ElicitRequest extends Request {
* @category `elicitation/create` * @category `elicitation/create`
*/ */
export type PrimitiveSchemaDefinition = export type PrimitiveSchemaDefinition =
| StringSchema StringSchema | NumberSchema | BooleanSchema | EnumSchema;
| NumberSchema
| BooleanSchema
| EnumSchema;
/** /**
* @category `elicitation/create` * @category `elicitation/create`
@ -1586,18 +1576,12 @@ export type ClientNotification =
/** @internal */ /** @internal */
export type ClientResult = export type ClientResult =
| EmptyResult EmptyResult | CreateMessageResult | ListRootsResult | ElicitResult;
| CreateMessageResult
| ListRootsResult
| ElicitResult;
/* Server messages */ /* Server messages */
/** @internal */ /** @internal */
export type ServerRequest = export type ServerRequest =
| PingRequest PingRequest | CreateMessageRequest | ListRootsRequest | ElicitRequest;
| CreateMessageRequest
| ListRootsRequest
| ElicitRequest;
/** @internal */ /** @internal */
export type ServerNotification = export type ServerNotification =

View file

@ -6,9 +6,7 @@
* @category JSON-RPC * @category JSON-RPC
*/ */
export type JSONRPCMessage = export type JSONRPCMessage =
| JSONRPCRequest JSONRPCRequest | JSONRPCNotification | JSONRPCResponse;
| JSONRPCNotification
| JSONRPCResponse;
/** @internal */ /** @internal */
export const LATEST_PROTOCOL_VERSION = "2025-11-25"; export const LATEST_PROTOCOL_VERSION = "2025-11-25";
@ -1740,11 +1738,7 @@ export interface Annotations {
* @category Content * @category Content
*/ */
export type ContentBlock = export type ContentBlock =
| TextContent TextContent | ImageContent | AudioContent | ResourceLink | EmbeddedResource;
| ImageContent
| AudioContent
| ResourceLink
| EmbeddedResource;
/** /**
* Text provided to or from an LLM. * Text provided to or from an LLM.
@ -2219,8 +2213,7 @@ export interface ElicitRequestURLParams extends TaskAugmentedRequestParams {
* @category `elicitation/create` * @category `elicitation/create`
*/ */
export type ElicitRequestParams = export type ElicitRequestParams =
| ElicitRequestFormParams ElicitRequestFormParams | ElicitRequestURLParams;
| ElicitRequestURLParams;
/** /**
* A request from the server to elicit additional information from the user via the client. * A request from the server to elicit additional information from the user via the client.
@ -2239,10 +2232,7 @@ export interface ElicitRequest extends JSONRPCRequest {
* @category `elicitation/create` * @category `elicitation/create`
*/ */
export type PrimitiveSchemaDefinition = export type PrimitiveSchemaDefinition =
| StringSchema StringSchema | NumberSchema | BooleanSchema | EnumSchema;
| NumberSchema
| BooleanSchema
| EnumSchema;
/** /**
* @category `elicitation/create` * @category `elicitation/create`
@ -2343,8 +2333,7 @@ export interface TitledSingleSelectEnumSchema {
*/ */
// Combined single selection enumeration // Combined single selection enumeration
export type SingleSelectEnumSchema = export type SingleSelectEnumSchema =
| UntitledSingleSelectEnumSchema UntitledSingleSelectEnumSchema | TitledSingleSelectEnumSchema;
| TitledSingleSelectEnumSchema;
/** /**
* Schema for multiple-selection enumeration without display titles for options. * Schema for multiple-selection enumeration without display titles for options.
@ -2437,8 +2426,7 @@ export interface TitledMultiSelectEnumSchema {
*/ */
// Combined multiple selection enumeration // Combined multiple selection enumeration
export type MultiSelectEnumSchema = export type MultiSelectEnumSchema =
| UntitledMultiSelectEnumSchema UntitledMultiSelectEnumSchema | TitledMultiSelectEnumSchema;
| TitledMultiSelectEnumSchema;
/** /**
* Use TitledSingleSelectEnumSchema instead. * Use TitledSingleSelectEnumSchema instead.
@ -2464,9 +2452,7 @@ export interface LegacyTitledEnumSchema {
*/ */
// Union type for all enum schemas // Union type for all enum schemas
export type EnumSchema = export type EnumSchema =
| SingleSelectEnumSchema SingleSelectEnumSchema | MultiSelectEnumSchema | LegacyTitledEnumSchema;
| MultiSelectEnumSchema
| LegacyTitledEnumSchema;
/** /**
* The client's response to an elicitation request. * The client's response to an elicitation request.

View file

@ -1 +1 @@
modelcontextprotocol@f817239f4d6b1efff2c4dfc2f7af85c985d73076 modelcontextprotocol@71e306956a4959c9655e5036be215d41986596e6

View file

@ -4,12 +4,7 @@
* @category Common Types * @category Common Types
*/ */
export type JSONValue = export type JSONValue =
| string string | number | boolean | null | JSONObject | JSONArray;
| number
| boolean
| null
| JSONObject
| JSONArray;
/** /**
* @category Common Types * @category Common Types
@ -29,9 +24,7 @@ export type JSONArray = JSONValue[];
* @category JSON-RPC * @category JSON-RPC
*/ */
export type JSONRPCMessage = export type JSONRPCMessage =
| JSONRPCRequest JSONRPCRequest | JSONRPCNotification | JSONRPCResponse;
| JSONRPCNotification
| JSONRPCResponse;
/** @internal */ /** @internal */
export const LATEST_PROTOCOL_VERSION = "2026-07-28"; export const LATEST_PROTOCOL_VERSION = "2026-07-28";
@ -82,12 +75,19 @@ export interface RequestMetaObject extends MetaObject {
*/ */
"io.modelcontextprotocol/protocolVersion": string; "io.modelcontextprotocol/protocolVersion": string;
/** /**
* Identifies the client software making the request. Required. * Identifies the client software making the request. Clients SHOULD
* include this field on every request unless specifically configured not
* to do so.
* *
* The {@link Implementation} schema requires `name` and `version`; other * The {@link Implementation} schema requires `name` and `version`; other
* fields are optional. * fields are optional.
*
* The value is self-reported by the client and is not verified by the
* protocol. It is intended for display, logging, and debugging. Servers
* SHOULD NOT use it to change their behavior, and SHOULD NOT rely on it for
* security decisions.
*/ */
"io.modelcontextprotocol/clientInfo": Implementation; "io.modelcontextprotocol/clientInfo"?: Implementation;
/** /**
* The client's capabilities for this specific request. Required. * The client's capabilities for this specific request. Required.
* *
@ -133,6 +133,30 @@ export interface NotificationMetaObject extends MetaObject {
"io.modelcontextprotocol/subscriptionId"?: RequestId; "io.modelcontextprotocol/subscriptionId"?: RequestId;
} }
/**
* Extends {@link MetaObject} with additional result-specific fields. All key naming rules from `MetaObject` apply.
*
* @see {@link MetaObject} for key naming rules and reserved prefixes.
* @see [General fields: `_meta`](/specification/draft/basic/index#meta) for more details.
* @category Common Types
*/
export interface ResultMetaObject extends MetaObject {
/**
* Identifies the server software producing the response. Servers SHOULD
* include this field on every response unless specifically configured not
* to do so.
*
* The {@link Implementation} schema requires `name` and `version`; other
* fields are optional.
*
* The value is self-reported by the server and is not verified by the
* protocol. It is intended for display, logging, and debugging. Clients
* SHOULD NOT use it to change their behavior, and SHOULD NOT rely on it for
* security decisions.
*/
"io.modelcontextprotocol/serverInfo"?: Implementation;
}
/** /**
* A progress token, used to associate progress notifications with the original request. * A progress token, used to associate progress notifications with the original request.
* *
@ -197,7 +221,7 @@ export type ResultType = "complete" | "input_required" | string;
* @category Common Types * @category Common Types
*/ */
export interface Result { export interface Result {
_meta?: MetaObject; _meta?: ResultMetaObject;
/** /**
* Indicates the type of the result, which allows the client to determine * Indicates the type of the result, which allows the client to determine
* how to parse the result object. * how to parse the result object.
@ -511,15 +535,11 @@ export type EmptyResult = Result;
/** @internal */ /** @internal */
export type InputRequest = export type InputRequest =
| CreateMessageRequest CreateMessageRequest | ListRootsRequest | ElicitRequest;
| ListRootsRequest
| ElicitRequest;
/** @internal */ /** @internal */
export type InputResponse = export type InputResponse =
| CreateMessageResult CreateMessageResult | ListRootsResult | ElicitResult;
| ListRootsResult
| ElicitResult;
/** /**
* A map of server-initiated requests that the client must fulfill. * A map of server-initiated requests that the client must fulfill.
@ -665,10 +685,6 @@ export interface DiscoverResult extends CacheableResult {
* The capabilities of the server. * The capabilities of the server.
*/ */
capabilities: ServerCapabilities; capabilities: ServerCapabilities;
/**
* Information about the server software implementation.
*/
serverInfo: Implementation;
/** /**
* Natural-language guidance describing the server and its features. * Natural-language guidance describing the server and its features.
* *
@ -1300,6 +1316,40 @@ export interface SubscriptionsListenRequest extends JSONRPCRequest {
params: SubscriptionsListenRequestParams; params: SubscriptionsListenRequestParams;
} }
/**
* Extends {@link ResultMetaObject} with the subscription-stream identifier carried by a
* {@link SubscriptionsListenResult}. All key naming rules from `MetaObject` apply.
*
* @see {@link MetaObject} for key naming rules and reserved prefixes.
* @category `subscriptions/listen`
*/
export interface SubscriptionsListenResultMeta extends ResultMetaObject {
/**
* Identifies the subscription stream this response closes, so the client can
* correlate it with the originating subscription — mirroring the same key on
* the stream's notifications. The value is the JSON-RPC ID of the
* `subscriptions/listen` request that opened the stream (and equals this
* response's `id`).
*/
"io.modelcontextprotocol/subscriptionId": RequestId;
}
/**
* The response to a {@link SubscriptionsListenRequest | subscriptions/listen}
* request, signalling that the subscription has ended gracefully (for example,
* during server shutdown). Because the listen stream is long-lived, this result
* is sent only when the server tears the subscription down; an abrupt transport
* close carries no response. The result body is otherwise empty.
*
* @example Subscription closed gracefully
* {@includeCode ./examples/SubscriptionsListenResult/listen-closed.json}
*
* @category `subscriptions/listen`
*/
export interface SubscriptionsListenResult extends Result {
_meta: SubscriptionsListenResultMeta;
}
/** /**
* Parameters for a {@link SubscriptionsAcknowledgedNotification | notifications/subscriptions/acknowledged} notification. * Parameters for a {@link SubscriptionsAcknowledgedNotification | notifications/subscriptions/acknowledged} notification.
* *
@ -1316,10 +1366,16 @@ export interface SubscriptionsAcknowledgedNotificationParams extends Notificatio
} }
/** /**
* Sent by the server as the first message on a * Sent by the server to acknowledge that a
* {@link SubscriptionsListenRequest | subscriptions/listen} stream to acknowledge * {@link SubscriptionsListenRequest | subscriptions/listen} subscription has been
* that the subscription has been established and to report which notification * established and to report which notification types it agreed to honor.
* types it agreed to honor. *
* This notification MUST be the first message the server sends carrying the
* subscription's ID in `io.modelcontextprotocol/subscriptionId`. The server MUST
* NOT send any notification on the subscription before acknowledging it. On
* stdio, where every subscription shares one channel, this ordering is defined
* per subscription ID and not per channel: messages belonging to other
* subscriptions MAY be interleaved before it.
* *
* @example Listen acknowledged * @example Listen acknowledged
* {@includeCode ./examples/SubscriptionsAcknowledgedNotification/listen-acknowledged.json} * {@includeCode ./examples/SubscriptionsAcknowledgedNotification/listen-acknowledged.json}
@ -2234,11 +2290,7 @@ export interface Annotations {
* @category Content * @category Content
*/ */
export type ContentBlock = export type ContentBlock =
| TextContent TextContent | ImageContent | AudioContent | ResourceLink | EmbeddedResource;
| ImageContent
| AudioContent
| ResourceLink
| EmbeddedResource;
/** /**
* Text provided to or from an LLM. * Text provided to or from an LLM.
@ -2778,8 +2830,7 @@ export interface ElicitRequestURLParams {
* @category `elicitation/create` * @category `elicitation/create`
*/ */
export type ElicitRequestParams = export type ElicitRequestParams =
| ElicitRequestFormParams ElicitRequestFormParams | ElicitRequestURLParams;
| ElicitRequestURLParams;
/** /**
* A request from the server to elicit additional information from the user via the client. * A request from the server to elicit additional information from the user via the client.
@ -2801,10 +2852,7 @@ export interface ElicitRequest {
* @category `elicitation/create` * @category `elicitation/create`
*/ */
export type PrimitiveSchemaDefinition = export type PrimitiveSchemaDefinition =
| StringSchema StringSchema | NumberSchema | BooleanSchema | EnumSchema;
| NumberSchema
| BooleanSchema
| EnumSchema;
/** /**
* @example Email input schema * @example Email input schema
@ -2929,8 +2977,7 @@ export interface TitledSingleSelectEnumSchema {
*/ */
// Combined single selection enumeration // Combined single selection enumeration
export type SingleSelectEnumSchema = export type SingleSelectEnumSchema =
| UntitledSingleSelectEnumSchema UntitledSingleSelectEnumSchema | TitledSingleSelectEnumSchema;
| TitledSingleSelectEnumSchema;
/** /**
* Schema for multiple-selection enumeration without display titles for options. * Schema for multiple-selection enumeration without display titles for options.
@ -3029,8 +3076,7 @@ export interface TitledMultiSelectEnumSchema {
*/ */
// Combined multiple selection enumeration // Combined multiple selection enumeration
export type MultiSelectEnumSchema = export type MultiSelectEnumSchema =
| UntitledMultiSelectEnumSchema UntitledMultiSelectEnumSchema | TitledMultiSelectEnumSchema;
| TitledMultiSelectEnumSchema;
/** /**
* Use {@link TitledSingleSelectEnumSchema} instead. * Use {@link TitledSingleSelectEnumSchema} instead.
@ -3056,9 +3102,7 @@ export interface LegacyTitledEnumSchema {
*/ */
// Union type for all enum schemas // Union type for all enum schemas
export type EnumSchema = export type EnumSchema =
| SingleSelectEnumSchema SingleSelectEnumSchema | MultiSelectEnumSchema | LegacyTitledEnumSchema;
| MultiSelectEnumSchema
| LegacyTitledEnumSchema;
/** /**
* The result returned by the client for an {@link ElicitRequest| elicitation/create} request. * The result returned by the client for an {@link ElicitRequest| elicitation/create} request.
@ -3134,6 +3178,7 @@ export type ServerResult =
| ListResourceTemplatesResult | ListResourceTemplatesResult
| ListResourcesResult | ListResourcesResult
| ReadResourceResult | ReadResourceResult
| SubscriptionsListenResult
| CallToolResult | CallToolResult
| ListToolsResult | ListToolsResult
| InputRequiredResult; | InputRequiredResult;