feat!: add server discovery and negotiation (SEP-2575) (#973)

* feat!: add server discovery and negotiation

* feat!: make protocol unions extensible

* ci: add discovery conformance coverage
This commit is contained in:
Dale Seo 2026-07-16 13:47:30 -04:00 • committed by GitHub
commit 3549e86d28
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 1325 additions and 98 deletions

View file

@ -562,6 +562,22 @@
"CustomResult": {
"description": "A catch-all response either side can use for custom requests."
},
"DiscoverRequestMethod": {
"type": "string",
"format": "const",
"const": "server/discover"
},
"DiscoverRequestParams": {
"type": "object",
"properties": {
"_meta": {
"$ref": "#/definitions/RequestMetaObject"
}
},
"required": [
"_meta"
]
},
"ElicitResult": {
"description": "The result returned by a client in response to an elicitation request.\n\nContains the user's decision (accept/decline/cancel) and optionally their input data\nif they chose to accept the request.",
"type": "object",
@ -1120,6 +1136,9 @@
{
"$ref": "#/definitions/Request4"
},
{
"$ref": "#/definitions/Request5"
},
{
"$ref": "#/definitions/RequestOptionalParam"
},
@ -1129,9 +1148,6 @@
{
"$ref": "#/definitions/RequestOptionalParam3"
},
{
"$ref": "#/definitions/Request5"
},
{
"$ref": "#/definitions/Request6"
},
@ -1141,21 +1157,24 @@
{
"$ref": "#/definitions/Request8"
},
{
"$ref": "#/definitions/RequestOptionalParam4"
},
{
"$ref": "#/definitions/Request9"
},
{
"$ref": "#/definitions/RequestOptionalParam5"
"$ref": "#/definitions/RequestOptionalParam4"
},
{
"$ref": "#/definitions/Request10"
},
{
"$ref": "#/definitions/RequestOptionalParam5"
},
{
"$ref": "#/definitions/Request11"
},
{
"$ref": "#/definitions/Request12"
},
{
"$ref": "#/definitions/CustomRequest"
}
@ -1548,6 +1567,22 @@
]
},
"Request10": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
"method": {
"$ref": "#/definitions/GetTaskMethod"
},
"params": {
"$ref": "#/definitions/GetTaskParams"
}
},
"required": [
"method",
"params"
]
},
"Request11": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1563,7 +1598,7 @@
"params"
]
},
"Request11": {
"Request12": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1580,6 +1615,22 @@
]
},
"Request2": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
"method": {
"$ref": "#/definitions/DiscoverRequestMethod"
},
"params": {
"$ref": "#/definitions/DiscoverRequestParams"
}
},
"required": [
"method",
"params"
]
},
"Request3": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1595,7 +1646,7 @@
"params"
]
},
"Request3": {
"Request4": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1611,7 +1662,7 @@
"params"
]
},
"Request4": {
"Request5": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1627,7 +1678,7 @@
"params"
]
},
"Request5": {
"Request6": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1643,7 +1694,7 @@
"params"
]
},
"Request6": {
"Request7": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1659,7 +1710,7 @@
"params"
]
},
"Request7": {
"Request8": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1675,7 +1726,7 @@
"params"
]
},
"Request8": {
"Request9": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1691,22 +1742,6 @@
"params"
]
},
"Request9": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
"method": {
"$ref": "#/definitions/GetTaskMethod"
},
"params": {
"$ref": "#/definitions/GetTaskParams"
}
},
"required": [
"method",
"params"
]
},
"RequestMetaObject": {
"description": "Metadata reserved by MCP on requests. Extension keys are also allowed.",
"type": "object",

View file

@ -562,6 +562,22 @@
"CustomResult": {
"description": "A catch-all response either side can use for custom requests."
},
"DiscoverRequestMethod": {
"type": "string",
"format": "const",
"const": "server/discover"
},
"DiscoverRequestParams": {
"type": "object",
"properties": {
"_meta": {
"$ref": "#/definitions/RequestMetaObject"
}
},
"required": [
"_meta"
]
},
"ElicitResult": {
"description": "The result returned by a client in response to an elicitation request.\n\nContains the user's decision (accept/decline/cancel) and optionally their input data\nif they chose to accept the request.",
"type": "object",
@ -1120,6 +1136,9 @@
{
"$ref": "#/definitions/Request4"
},
{
"$ref": "#/definitions/Request5"
},
{
"$ref": "#/definitions/RequestOptionalParam"
},
@ -1129,9 +1148,6 @@
{
"$ref": "#/definitions/RequestOptionalParam3"
},
{
"$ref": "#/definitions/Request5"
},
{
"$ref": "#/definitions/Request6"
},
@ -1141,21 +1157,24 @@
{
"$ref": "#/definitions/Request8"
},
{
"$ref": "#/definitions/RequestOptionalParam4"
},
{
"$ref": "#/definitions/Request9"
},
{
"$ref": "#/definitions/RequestOptionalParam5"
"$ref": "#/definitions/RequestOptionalParam4"
},
{
"$ref": "#/definitions/Request10"
},
{
"$ref": "#/definitions/RequestOptionalParam5"
},
{
"$ref": "#/definitions/Request11"
},
{
"$ref": "#/definitions/Request12"
},
{
"$ref": "#/definitions/CustomRequest"
}
@ -1548,6 +1567,22 @@
]
},
"Request10": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
"method": {
"$ref": "#/definitions/GetTaskMethod"
},
"params": {
"$ref": "#/definitions/GetTaskParams"
}
},
"required": [
"method",
"params"
]
},
"Request11": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1563,7 +1598,7 @@
"params"
]
},
"Request11": {
"Request12": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1580,6 +1615,22 @@
]
},
"Request2": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
"method": {
"$ref": "#/definitions/DiscoverRequestMethod"
},
"params": {
"$ref": "#/definitions/DiscoverRequestParams"
}
},
"required": [
"method",
"params"
]
},
"Request3": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1595,7 +1646,7 @@
"params"
]
},
"Request3": {
"Request4": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1611,7 +1662,7 @@
"params"
]
},
"Request4": {
"Request5": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1627,7 +1678,7 @@
"params"
]
},
"Request5": {
"Request6": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1643,7 +1694,7 @@
"params"
]
},
"Request6": {
"Request7": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1659,7 +1710,7 @@
"params"
]
},
"Request7": {
"Request8": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1675,7 +1726,7 @@
"params"
]
},
"Request8": {
"Request9": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
@ -1691,22 +1742,6 @@
"params"
]
},
"Request9": {
"description": "Represents a JSON-RPC request with method, parameters, and extensions.\n\nThis is the core structure for all MCP requests, containing:\n- `method`: The name of the method being called\n- `params`: The parameters for the method\n- `extensions`: Additional context data (similar to HTTP headers)",
"type": "object",
"properties": {
"method": {
"$ref": "#/definitions/GetTaskMethod"
},
"params": {
"$ref": "#/definitions/GetTaskParams"
}
},
"required": [
"method",
"params"
]
},
"RequestMetaObject": {
"description": "Metadata reserved by MCP on requests. Extension keys are also allowed.",
"type": "object",

View file

@ -743,6 +743,83 @@
"CustomResult": {
"description": "A catch-all response either side can use for custom requests."
},
"DiscoverResult": {
"description": "The server's response to a [`DiscoverRequest`].",
"type": "object",
"properties": {
"_meta": {
"description": "Protocol-level response metadata.",
"anyOf": [
{
"$ref": "#/definitions/MetaObject"
},
{
"type": "null"
}
]
},
"cacheScope": {
"description": "Whether the cached result may be shared across authorization contexts.",
"allOf": [
{
"$ref": "#/definitions/CacheScope"
}
]
},
"capabilities": {
"description": "Capabilities provided by this server.",
"allOf": [
{
"$ref": "#/definitions/ServerCapabilities"
}
]
},
"instructions": {
"description": "Optional guidance for using the server.",
"type": [
"string",
"null"
]
},
"resultType": {
"description": "Identifies how the result should be parsed.",
"allOf": [
{
"$ref": "#/definitions/ResultType"
}
]
},
"serverInfo": {
"description": "Information about the server implementation.",
"allOf": [
{
"$ref": "#/definitions/Implementation"
}
]
},
"supportedVersions": {
"description": "Protocol versions implemented by this server.",
"type": "array",
"items": {
"$ref": "#/definitions/ProtocolVersion"
}
},
"ttlMs": {
"description": "How long clients may consider this response fresh, in milliseconds.",
"type": "integer",
"format": "uint64",
"minimum": 0
}
},
"required": [
"resultType",
"supportedVersions",
"capabilities",
"serverInfo",
"ttlMs",
"cacheScope"
]
},
"ElicitRequestParams": {
"description": "Parameters for creating an elicitation request to gather user input.\n\nThis structure contains everything needed to request interactive input from a user:\n- A human-readable message explaining what information is needed\n- A type-safe schema defining the expected structure of the response\n\n# Example\n1. Form-based elicitation request\n```rust\nuse rmcp::model::*;\n\nlet params = ElicitRequestParams::FormElicitationParams {\n meta: None,\n message: \"Please provide your email\".to_string(),\n requested_schema: ElicitationSchema::builder()\n .required_email(\"email\")\n .build()\n .unwrap(),\n};\n```\n2. URL-based elicitation request\n```rust\nuse rmcp::model::*;\nlet params = ElicitRequestParams::UrlElicitationParams {\n meta: None,\n message: \"Please provide your feedback at the following URL\".to_string(),\n url: \"https://example.com/feedback\".to_string(),\n elicitation_id: \"unique-id-123\".to_string(),\n};\n```",
"anyOf": [
@ -3194,6 +3271,9 @@
},
"ServerResult": {
"anyOf": [
{
"$ref": "#/definitions/DiscoverResult"
},
{
"$ref": "#/definitions/InitializeResult"
},

View file

@ -743,6 +743,83 @@
"CustomResult": {
"description": "A catch-all response either side can use for custom requests."
},
"DiscoverResult": {
"description": "The server's response to a [`DiscoverRequest`].",
"type": "object",
"properties": {
"_meta": {
"description": "Protocol-level response metadata.",
"anyOf": [
{
"$ref": "#/definitions/MetaObject"
},
{
"type": "null"
}
]
},
"cacheScope": {
"description": "Whether the cached result may be shared across authorization contexts.",
"allOf": [
{
"$ref": "#/definitions/CacheScope"
}
]
},
"capabilities": {
"description": "Capabilities provided by this server.",
"allOf": [
{
"$ref": "#/definitions/ServerCapabilities"
}
]
},
"instructions": {
"description": "Optional guidance for using the server.",
"type": [
"string",
"null"
]
},
"resultType": {
"description": "Identifies how the result should be parsed.",
"allOf": [
{
"$ref": "#/definitions/ResultType"
}
]
},
"serverInfo": {
"description": "Information about the server implementation.",
"allOf": [
{
"$ref": "#/definitions/Implementation"
}
]
},
"supportedVersions": {
"description": "Protocol versions implemented by this server.",
"type": "array",
"items": {
"$ref": "#/definitions/ProtocolVersion"
}
},
"ttlMs": {
"description": "How long clients may consider this response fresh, in milliseconds.",
"type": "integer",
"format": "uint64",
"minimum": 0
}
},
"required": [
"resultType",
"supportedVersions",
"capabilities",
"serverInfo",
"ttlMs",
"cacheScope"
]
},
"ElicitRequestParams": {
"description": "Parameters for creating an elicitation request to gather user input.\n\nThis structure contains everything needed to request interactive input from a user:\n- A human-readable message explaining what information is needed\n- A type-safe schema defining the expected structure of the response\n\n# Example\n1. Form-based elicitation request\n```rust\nuse rmcp::model::*;\n\nlet params = ElicitRequestParams::FormElicitationParams {\n meta: None,\n message: \"Please provide your email\".to_string(),\n requested_schema: ElicitationSchema::builder()\n .required_email(\"email\")\n .build()\n .unwrap(),\n};\n```\n2. URL-based elicitation request\n```rust\nuse rmcp::model::*;\nlet params = ElicitRequestParams::UrlElicitationParams {\n meta: None,\n message: \"Please provide your feedback at the following URL\".to_string(),\n url: \"https://example.com/feedback\".to_string(),\n elicitation_id: \"unique-id-123\".to_string(),\n};\n```",
"anyOf": [
@ -3194,6 +3271,9 @@
},
"ServerResult": {
"anyOf": [
{
"$ref": "#/definitions/DiscoverResult"
},
{
"$ref": "#/definitions/InitializeResult"
},