feat!: align metadata models with draft schema (#993)
This commit is contained in:
parent
92581bee53
commit
839922d8fd
27 changed files with 2539 additions and 1059 deletions
|
|
@ -103,7 +103,7 @@ impl ConformanceServer {
|
|||
async fn call_mrtr_tool(
|
||||
&self,
|
||||
request: CallToolRequestParams,
|
||||
meta: &Meta,
|
||||
meta: &RequestMetaObject,
|
||||
) -> Result<CallToolResponse, ErrorData> {
|
||||
let responses = request.input_responses.as_ref();
|
||||
match request.name.as_ref() {
|
||||
|
|
|
|||
|
|
@ -209,13 +209,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<C> FromContextPart<C> for crate::model::Meta
|
||||
impl<C> FromContextPart<C> for crate::model::RequestMetaObject
|
||||
where
|
||||
C: AsRequestContext,
|
||||
{
|
||||
fn from_context_part(context: &mut C) -> Result<Self, crate::ErrorData> {
|
||||
let request_context = context.as_request_context_mut();
|
||||
let mut meta = crate::model::Meta::default();
|
||||
let mut meta = crate::model::RequestMetaObject::default();
|
||||
std::mem::swap(&mut meta, &mut request_context.meta);
|
||||
Ok(meta)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
tool::schema_for_output,
|
||||
wrapper::{Json, Parameters},
|
||||
},
|
||||
model::{Icon, JsonObject, Meta, ToolAnnotations, ToolExecution},
|
||||
model::{Icon, JsonObject, MetaObject, ToolAnnotations, ToolExecution},
|
||||
schemars::JsonSchema,
|
||||
service::{MaybeSend, MaybeSendFuture},
|
||||
};
|
||||
|
|
@ -77,7 +77,7 @@ pub trait ToolBase {
|
|||
fn icons() -> Option<Vec<Icon>> {
|
||||
None
|
||||
}
|
||||
fn meta() -> Option<Meta> {
|
||||
fn meta() -> Option<MetaObject> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -339,7 +339,8 @@ pub struct ProgressToken(pub NumberOrString);
|
|||
pub struct Request<M = String, P = JsonObject> {
|
||||
pub method: M,
|
||||
pub params: P,
|
||||
/// extensions will carry anything possible in the context, including [`Meta`]
|
||||
/// extensions will carry anything possible in the context, including the metadata
|
||||
/// ([`RequestMetaObject`] for requests, [`NotificationMetaObject`] for notifications)
|
||||
///
|
||||
/// this is similar with the Extensions in `http` crate
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
|
|
@ -372,7 +373,8 @@ pub struct RequestOptionalParam<M = String, P = JsonObject> {
|
|||
pub method: M,
|
||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub params: Option<P>,
|
||||
/// extensions will carry anything possible in the context, including [`Meta`]
|
||||
/// extensions will carry anything possible in the context, including the metadata
|
||||
/// ([`RequestMetaObject`] for requests, [`NotificationMetaObject`] for notifications)
|
||||
///
|
||||
/// this is similar with the Extensions in `http` crate
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
|
|
@ -394,7 +396,8 @@ impl<M: Default, P> RequestOptionalParam<M, P> {
|
|||
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
|
||||
pub struct RequestNoParam<M = String> {
|
||||
pub method: M,
|
||||
/// extensions will carry anything possible in the context, including [`Meta`]
|
||||
/// extensions will carry anything possible in the context, including the metadata
|
||||
/// ([`RequestMetaObject`] for requests, [`NotificationMetaObject`] for notifications)
|
||||
///
|
||||
/// this is similar with the Extensions in `http` crate
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
|
|
@ -415,7 +418,8 @@ impl<M> GetExtensions for RequestNoParam<M> {
|
|||
pub struct Notification<M = String, P = JsonObject> {
|
||||
pub method: M,
|
||||
pub params: P,
|
||||
/// extensions will carry anything possible in the context, including [`Meta`]
|
||||
/// extensions will carry anything possible in the context, including the metadata
|
||||
/// ([`RequestMetaObject`] for requests, [`NotificationMetaObject`] for notifications)
|
||||
///
|
||||
/// this is similar with the Extensions in `http` crate
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
|
|
@ -437,7 +441,8 @@ impl<M: Default, P> Notification<M, P> {
|
|||
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
|
||||
pub struct NotificationNoParam<M = String> {
|
||||
pub method: M,
|
||||
/// extensions will carry anything possible in the context, including [`Meta`]
|
||||
/// extensions will carry anything possible in the context, including the metadata
|
||||
/// ([`RequestMetaObject`] for requests, [`NotificationMetaObject`] for notifications)
|
||||
///
|
||||
/// this is similar with the Extensions in `http` crate
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
|
|
@ -782,7 +787,7 @@ pub struct CancelledNotificationParam {
|
|||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub reason: Option<String>,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<NotificationMetaObject>,
|
||||
}
|
||||
|
||||
impl CancelledNotificationParam {
|
||||
|
|
@ -818,7 +823,8 @@ pub type CancelledNotification =
|
|||
pub struct CustomNotification {
|
||||
pub method: String,
|
||||
pub params: Option<Value>,
|
||||
/// extensions will carry anything possible in the context, including [`Meta`]
|
||||
/// extensions will carry anything possible in the context, including the metadata
|
||||
/// ([`RequestMetaObject`] for requests, [`NotificationMetaObject`] for notifications)
|
||||
///
|
||||
/// this is similar with the Extensions in `http` crate
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
|
|
@ -853,7 +859,8 @@ impl CustomNotification {
|
|||
pub struct CustomRequest {
|
||||
pub method: String,
|
||||
pub params: Option<Value>,
|
||||
/// extensions will carry anything possible in the context, including [`Meta`]
|
||||
/// extensions will carry anything possible in the context, including the metadata
|
||||
/// ([`RequestMetaObject`] for requests, [`NotificationMetaObject`] for notifications)
|
||||
///
|
||||
/// this is similar with the Extensions in `http` crate
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
|
|
@ -898,7 +905,7 @@ pub type InitializedNotification = NotificationNoParam<InitializedNotificationMe
|
|||
pub struct InitializeRequestParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
/// The MCP protocol version this client supports
|
||||
pub protocol_version: ProtocolVersion,
|
||||
/// The capabilities this client supports (sampling, roots, etc.)
|
||||
|
|
@ -925,10 +932,10 @@ impl InitializeRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for InitializeRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -956,7 +963,7 @@ pub struct InitializeResult {
|
|||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub instructions: Option<String>,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
impl InitializeResult {
|
||||
|
|
@ -1167,7 +1174,7 @@ impl Implementation {
|
|||
pub struct PaginatedRequestParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub cursor: Option<String>,
|
||||
}
|
||||
|
|
@ -1180,10 +1187,10 @@ impl PaginatedRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for PaginatedRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -1214,7 +1221,7 @@ pub struct ProgressNotificationParam {
|
|||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub message: Option<String>,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<NotificationMetaObject>,
|
||||
}
|
||||
|
||||
impl ProgressNotificationParam {
|
||||
|
|
@ -1287,7 +1294,7 @@ macro_rules! paginated_result {
|
|||
#[serde(default)]
|
||||
pub result_type: ResultType,
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub next_cursor: Option<Cursor>,
|
||||
/// Time, in milliseconds, that this result may be treated as fresh (SEP-2549).
|
||||
|
|
@ -1365,7 +1372,7 @@ const_string!(ReadResourceRequestMethod = "resources/read");
|
|||
pub struct ReadResourceRequestParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
/// The URI of the resource to read
|
||||
pub uri: String,
|
||||
/// Client responses to server-initiated input requests from a previous
|
||||
|
|
@ -1389,7 +1396,7 @@ impl ReadResourceRequestParams {
|
|||
}
|
||||
|
||||
/// Set the metadata for this request.
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: RequestMetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -1408,10 +1415,10 @@ impl ReadResourceRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for ReadResourceRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -1446,7 +1453,7 @@ pub struct ReadResourceResult {
|
|||
/// The actual content of the resource
|
||||
pub contents: Vec<ResourceContents>,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
impl ReadResourceResult {
|
||||
|
|
@ -1491,7 +1498,7 @@ const_string!(SubscribeRequestMethod = "resources/subscribe");
|
|||
pub struct SubscribeRequestParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
/// The URI of the resource to subscribe to
|
||||
pub uri: String,
|
||||
}
|
||||
|
|
@ -1507,10 +1514,10 @@ impl SubscribeRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for SubscribeRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -1531,7 +1538,7 @@ const_string!(UnsubscribeRequestMethod = "resources/unsubscribe");
|
|||
pub struct UnsubscribeRequestParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
/// The URI of the resource to unsubscribe from
|
||||
pub uri: String,
|
||||
}
|
||||
|
|
@ -1547,10 +1554,10 @@ impl UnsubscribeRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for UnsubscribeRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -1572,7 +1579,7 @@ pub struct ResourceUpdatedNotificationParam {
|
|||
/// The URI of the resource that was updated
|
||||
pub uri: String,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<NotificationMetaObject>,
|
||||
}
|
||||
|
||||
impl ResourceUpdatedNotificationParam {
|
||||
|
|
@ -1611,7 +1618,7 @@ const_string!(GetPromptRequestMethod = "prompts/get");
|
|||
pub struct GetPromptRequestParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
pub name: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub arguments: Option<JsonObject>,
|
||||
|
|
@ -1643,7 +1650,7 @@ impl GetPromptRequestParams {
|
|||
}
|
||||
|
||||
/// Set the metadata for this request.
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: RequestMetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -1662,10 +1669,10 @@ impl GetPromptRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for GetPromptRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -1722,7 +1729,7 @@ const_string!(SetLevelRequestMethod = "logging/setLevel");
|
|||
pub struct SetLevelRequestParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
/// The desired logging level
|
||||
pub level: LoggingLevel,
|
||||
}
|
||||
|
|
@ -1735,10 +1742,10 @@ impl SetLevelRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for SetLevelRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -1773,7 +1780,7 @@ pub struct LoggingMessageNotificationParam {
|
|||
/// The actual log data
|
||||
pub data: Value,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<NotificationMetaObject>,
|
||||
}
|
||||
|
||||
impl LoggingMessageNotificationParam {
|
||||
|
|
@ -1994,7 +2001,7 @@ pub struct SamplingMessage {
|
|||
/// The actual content of the message (text, image, audio, tool use, or tool result)
|
||||
pub content: SamplingContent<SamplingMessageContentBlock>,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
/// Content types for sampling messages (SEP-1577).
|
||||
|
|
@ -2161,7 +2168,7 @@ pub enum ContextInclusion {
|
|||
pub struct CreateMessageRequestParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
/// Task metadata for async task management (SEP-1319)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub task: Option<TaskMetadata>,
|
||||
|
|
@ -2196,10 +2203,10 @@ pub struct CreateMessageRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for CreateMessageRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -2516,7 +2523,7 @@ impl CompletionContext {
|
|||
pub struct CompleteRequestParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
pub r#ref: Reference,
|
||||
pub argument: ArgumentInfo,
|
||||
/// Optional context containing previously resolved argument values
|
||||
|
|
@ -2543,10 +2550,10 @@ impl CompleteRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for CompleteRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -2646,7 +2653,7 @@ pub struct CompleteResult {
|
|||
pub result_type: ResultType,
|
||||
pub completion: CompletionInfo,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
impl CompleteResult {
|
||||
|
|
@ -2789,7 +2796,7 @@ pub struct Root {
|
|||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
impl Root {
|
||||
|
|
@ -2809,7 +2816,7 @@ impl Root {
|
|||
}
|
||||
|
||||
/// Sets the protocol-level metadata for this root.
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -2833,7 +2840,7 @@ pub type ListRootsRequest = RequestNoParam<ListRootsRequestMethod>;
|
|||
pub struct ListRootsResult {
|
||||
pub roots: Vec<Root>,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
impl ListRootsResult {
|
||||
|
|
@ -2843,7 +2850,7 @@ impl ListRootsResult {
|
|||
}
|
||||
|
||||
/// Sets the protocol-level metadata for this result.
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -2889,14 +2896,14 @@ enum CreateElicitationRequestParamDeserializeHelper {
|
|||
#[serde(rename = "form", rename_all = "camelCase")]
|
||||
FormElicitationParam {
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
meta: Option<Meta>,
|
||||
meta: Option<RequestMetaObject>,
|
||||
message: String,
|
||||
requested_schema: ElicitationSchema,
|
||||
},
|
||||
#[serde(rename = "url", rename_all = "camelCase")]
|
||||
UrlElicitationParam {
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
meta: Option<Meta>,
|
||||
meta: Option<RequestMetaObject>,
|
||||
message: String,
|
||||
url: String,
|
||||
elicitation_id: String,
|
||||
|
|
@ -2904,7 +2911,7 @@ enum CreateElicitationRequestParamDeserializeHelper {
|
|||
#[serde(untagged, rename_all = "camelCase")]
|
||||
FormElicitationParamBackwardsCompat {
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
meta: Option<Meta>,
|
||||
meta: Option<RequestMetaObject>,
|
||||
message: String,
|
||||
requested_schema: ElicitationSchema,
|
||||
},
|
||||
|
|
@ -2988,7 +2995,7 @@ pub enum ElicitRequestParams {
|
|||
FormElicitationParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
meta: Option<Meta>,
|
||||
meta: Option<RequestMetaObject>,
|
||||
/// Human-readable message explaining what input is needed from the user.
|
||||
/// This should be clear and provide sufficient context for the user to understand
|
||||
/// what information they need to provide.
|
||||
|
|
@ -3003,7 +3010,7 @@ pub enum ElicitRequestParams {
|
|||
UrlElicitationParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
meta: Option<Meta>,
|
||||
meta: Option<RequestMetaObject>,
|
||||
/// Human-readable message explaining what input is needed from the user.
|
||||
/// This should be clear and provide sufficient context for the user to understand
|
||||
/// what information they need to provide.
|
||||
|
|
@ -3018,13 +3025,13 @@ pub enum ElicitRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for ElicitRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
match self {
|
||||
ElicitRequestParams::FormElicitationParams { meta, .. } => meta.as_ref(),
|
||||
ElicitRequestParams::UrlElicitationParams { meta, .. } => meta.as_ref(),
|
||||
}
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
match self {
|
||||
ElicitRequestParams::FormElicitationParams { meta, .. } => meta,
|
||||
ElicitRequestParams::UrlElicitationParams { meta, .. } => meta,
|
||||
|
|
@ -3059,7 +3066,7 @@ pub struct ElicitResult {
|
|||
|
||||
/// Optional protocol-level metadata for this result.
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
impl ElicitResult {
|
||||
|
|
@ -3079,7 +3086,7 @@ impl ElicitResult {
|
|||
}
|
||||
|
||||
/// Set the metadata on this result.
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -3121,7 +3128,7 @@ pub struct CallToolResult {
|
|||
pub is_error: Option<bool>,
|
||||
/// Optional protocol-level metadata for this result
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
// Custom Deserialize implementation that:
|
||||
|
|
@ -3143,7 +3150,7 @@ impl<'de> Deserialize<'de> for CallToolResult {
|
|||
structured_content: Option<Value>,
|
||||
is_error: Option<bool>,
|
||||
#[serde(rename = "_meta")]
|
||||
meta: Option<Meta>,
|
||||
meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
let helper = Helper::deserialize(deserializer)?;
|
||||
|
|
@ -3290,7 +3297,7 @@ impl CallToolResult {
|
|||
}
|
||||
|
||||
/// Set the metadata on this result
|
||||
pub fn with_meta(mut self, meta: Option<Meta>) -> Self {
|
||||
pub fn with_meta(mut self, meta: Option<MetaObject>) -> Self {
|
||||
self.meta = meta;
|
||||
self
|
||||
}
|
||||
|
|
@ -3349,7 +3356,7 @@ const_string!(CallToolRequestMethod = "tools/call");
|
|||
pub struct CallToolRequestParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
/// The name of the tool to call
|
||||
pub name: Cow<'static, str>,
|
||||
/// Arguments to pass to the tool (must match the tool's input schema)
|
||||
|
|
@ -3407,10 +3414,10 @@ impl CallToolRequestParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for CallToolRequestParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -3503,7 +3510,7 @@ pub struct GetPromptResult {
|
|||
pub description: Option<String>,
|
||||
pub messages: Vec<PromptMessage>,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
impl GetPromptResult {
|
||||
|
|
@ -3543,7 +3550,7 @@ pub type GetTaskInfoRequest = GetTaskRequest;
|
|||
pub struct GetTaskParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
pub task_id: String,
|
||||
}
|
||||
|
||||
|
|
@ -3557,10 +3564,10 @@ impl GetTaskParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for GetTaskParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -3589,7 +3596,7 @@ pub type GetTaskResultRequest = GetTaskPayloadRequest;
|
|||
pub struct GetTaskPayloadParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
pub task_id: String,
|
||||
}
|
||||
|
||||
|
|
@ -3603,10 +3610,10 @@ impl GetTaskPayloadParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for GetTaskPayloadParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -3626,7 +3633,7 @@ pub type CancelTaskRequest = Request<CancelTaskMethod, CancelTaskParams>;
|
|||
pub struct CancelTaskParams {
|
||||
/// Protocol-level metadata for this request (SEP-1319)
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
pub task_id: String,
|
||||
}
|
||||
|
||||
|
|
@ -3640,10 +3647,10 @@ impl CancelTaskParams {
|
|||
}
|
||||
|
||||
impl RequestParamsMeta for CancelTaskParams {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -3666,7 +3673,7 @@ const_string!(TaskStatusNotificationMethod = "notifications/tasks/status");
|
|||
#[non_exhaustive]
|
||||
pub struct TaskStatusNotificationParam {
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<NotificationMetaObject>,
|
||||
#[serde(flatten)]
|
||||
pub task: crate::model::Task,
|
||||
}
|
||||
|
|
@ -3676,7 +3683,7 @@ impl TaskStatusNotificationParam {
|
|||
Self { meta: None, task }
|
||||
}
|
||||
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: NotificationMetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -3717,7 +3724,7 @@ pub struct ListTasksResult {
|
|||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next_cursor: Option<String>,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
impl ListTasksResult {
|
||||
|
|
@ -4487,7 +4494,9 @@ mod tests {
|
|||
{
|
||||
assert_eq!(
|
||||
meta,
|
||||
Some(Meta(object!({ "meta_form_key_1": "meta form value 1" })))
|
||||
Some(RequestMetaObject(MetaObject(
|
||||
object!({ "meta_form_key_1": "meta form value 1" })
|
||||
)))
|
||||
);
|
||||
assert_eq!(message, "Please provide more details.");
|
||||
assert_eq!(requested_schema.title, Some(Cow::from("User Details")));
|
||||
|
|
@ -4514,7 +4523,9 @@ mod tests {
|
|||
{
|
||||
assert_eq!(
|
||||
meta,
|
||||
Some(Meta(object!({ "meta_url_key_1": "meta url value 1" })))
|
||||
Some(RequestMetaObject(MetaObject(
|
||||
object!({ "meta_url_key_1": "meta url value 1" })
|
||||
)))
|
||||
);
|
||||
assert_eq!(message, "Please fill out the form at the following URL.");
|
||||
assert_eq!(url, "https://example.com/form");
|
||||
|
|
@ -4527,7 +4538,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_elicitation_serialization() {
|
||||
let form_elicitation = ElicitRequestParams::FormElicitationParams {
|
||||
meta: Some(Meta(object!({ "meta_form_key_1": "meta form value 1" }))),
|
||||
meta: Some(RequestMetaObject(MetaObject(
|
||||
object!({ "meta_form_key_1": "meta form value 1" }),
|
||||
))),
|
||||
message: "Please provide more details.".to_string(),
|
||||
requested_schema: ElicitationSchema::builder()
|
||||
.title("User Details")
|
||||
|
|
@ -4551,7 +4564,9 @@ mod tests {
|
|||
assert_eq!(json_form, expected_form_json);
|
||||
|
||||
let url_elicitation = ElicitRequestParams::UrlElicitationParams {
|
||||
meta: Some(Meta(object!({ "meta_url_key_1": "meta url value 1" }))),
|
||||
meta: Some(RequestMetaObject(MetaObject(
|
||||
object!({ "meta_url_key_1": "meta url value 1" }),
|
||||
))),
|
||||
message: "Please fill out the form at the following URL.".to_string(),
|
||||
url: "https://example.com/form".to_string(),
|
||||
elicitation_id: "elicitation-123".to_string(),
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::{Annotations, Meta, resource::ResourceContents};
|
||||
use super::{Annotations, MetaObject, resource::ResourceContents};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Flat content structs
|
||||
|
|
@ -28,7 +28,7 @@ pub struct TextContent {
|
|||
pub text: String,
|
||||
/// Optional protocol-level metadata for this content block.
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
/// Optional annotations describing how the client should use this content.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub annotations: Option<Annotations>,
|
||||
|
|
@ -43,7 +43,7 @@ impl TextContent {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ pub struct ImageContent {
|
|||
pub mime_type: String,
|
||||
/// Optional protocol-level metadata for this content block.
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
/// Optional annotations describing how the client should use this content.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub annotations: Option<Annotations>,
|
||||
|
|
@ -82,7 +82,7 @@ impl ImageContent {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -105,7 +105,7 @@ pub struct AudioContent {
|
|||
pub mime_type: String,
|
||||
/// Optional protocol-level metadata for this content block.
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
/// Optional annotations describing how the client should use this content.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub annotations: Option<Annotations>,
|
||||
|
|
@ -121,7 +121,7 @@ impl AudioContent {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ pub struct EmbeddedResource {
|
|||
pub resource: ResourceContents,
|
||||
/// Optional protocol-level metadata for this content block.
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
/// Optional annotations describing how the client should use this content.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub annotations: Option<Annotations>,
|
||||
|
|
@ -164,7 +164,7 @@ impl EmbeddedResource {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -189,7 +189,7 @@ pub struct ToolUseContent {
|
|||
pub name: String,
|
||||
pub input: super::JsonObject,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
/// Tool execution result in user message (SEP-1577).
|
||||
|
|
@ -203,7 +203,7 @@ pub struct ToolUseContent {
|
|||
)]
|
||||
pub struct ToolResultContent {
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
pub tool_use_id: String,
|
||||
pub content: Vec<ContentBlock>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
|
|
@ -402,7 +402,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_audio_content_has_meta() {
|
||||
let audio = AudioContent::new("data", "audio/wav").with_meta(Meta::default());
|
||||
let audio = AudioContent::new("data", "audio/wav").with_meta(MetaObject::default());
|
||||
let json = serde_json::to_value(&audio).unwrap();
|
||||
assert!(json.get("_meta").is_some());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,29 @@ use serde_json::Value;
|
|||
|
||||
use super::{
|
||||
ClientCapabilities, ClientNotification, ClientRequest, CustomNotification, CustomRequest,
|
||||
Extensions, Implementation, JsonObject, JsonRpcMessage, LoggingLevel, NumberOrString,
|
||||
ProgressToken, ProtocolVersion, ServerNotification, ServerRequest, TaskMetadata,
|
||||
Extensions, Implementation, JsonObject, JsonRpcMessage, LoggingLevel, ProgressToken,
|
||||
ProtocolVersion, RequestId, ServerNotification, ServerRequest, TaskMetadata,
|
||||
};
|
||||
|
||||
/// Access to the metadata carried by a message envelope's [`Extensions`].
|
||||
///
|
||||
/// The metadata type differs by message kind: requests carry a
|
||||
/// [`RequestMetaObject`] and notifications carry a [`NotificationMetaObject`].
|
||||
///
|
||||
/// The envelope extensions are the canonical runtime location for `_meta`:
|
||||
/// deserialization strips the wire `params._meta` into the extensions (typed
|
||||
/// params `meta` fields stay empty), and the service loop moves it into
|
||||
/// [`RequestContext::meta`] / [`NotificationContext::meta`] before dispatch.
|
||||
/// Typed params `meta` fields are honored when serializing outgoing messages;
|
||||
/// on key conflicts the extensions-level metadata wins.
|
||||
///
|
||||
/// [`RequestContext::meta`]: crate::service::RequestContext
|
||||
/// [`NotificationContext::meta`]: crate::service::NotificationContext
|
||||
pub trait GetMeta {
|
||||
fn get_meta_mut(&mut self) -> &mut Meta;
|
||||
fn get_meta(&self) -> &Meta;
|
||||
/// The metadata type for this message kind.
|
||||
type Metadata: Default;
|
||||
fn get_meta_mut(&mut self) -> &mut Self::Metadata;
|
||||
fn get_meta(&self) -> &Self::Metadata;
|
||||
}
|
||||
|
||||
pub trait GetExtensions {
|
||||
|
|
@ -21,15 +37,16 @@ pub trait GetExtensions {
|
|||
|
||||
/// Trait for request params that contain the `_meta` field.
|
||||
///
|
||||
/// Per the MCP 2025-11-25 spec, all request params should have an optional `_meta`
|
||||
/// field that can contain a `progressToken` for tracking long-running operations.
|
||||
/// Per the MCP spec, all request params may have an optional `_meta`
|
||||
/// field ([`RequestMetaObject`]) that can contain a `progressToken` for
|
||||
/// tracking long-running operations.
|
||||
pub trait RequestParamsMeta {
|
||||
/// Get a reference to the meta field
|
||||
fn meta(&self) -> Option<&Meta>;
|
||||
fn meta(&self) -> Option<&RequestMetaObject>;
|
||||
/// Get a mutable reference to the meta field
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta>;
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject>;
|
||||
/// Set the meta field
|
||||
fn set_meta(&mut self, meta: Meta) {
|
||||
fn set_meta(&mut self, meta: RequestMetaObject) {
|
||||
*self.meta_mut() = Some(meta);
|
||||
}
|
||||
/// Get the progress token from meta, if present
|
||||
|
|
@ -41,7 +58,7 @@ pub trait RequestParamsMeta {
|
|||
match self.meta_mut() {
|
||||
Some(meta) => meta.set_progress_token(token),
|
||||
none => {
|
||||
let mut meta = Meta::new();
|
||||
let mut meta = RequestMetaObject::new();
|
||||
meta.set_progress_token(token);
|
||||
*none = Some(meta);
|
||||
}
|
||||
|
|
@ -72,8 +89,8 @@ pub trait RequestParamsMeta {
|
|||
self.meta_or_default().set_baggage(value);
|
||||
}
|
||||
/// Get a mutable reference to meta, inserting an empty one if absent.
|
||||
fn meta_or_default(&mut self) -> &mut Meta {
|
||||
self.meta_mut().get_or_insert_with(Meta::new)
|
||||
fn meta_or_default(&mut self) -> &mut RequestMetaObject {
|
||||
self.meta_mut().get_or_insert_with(RequestMetaObject::new)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,13 +119,14 @@ impl GetExtensions for CustomNotification {
|
|||
}
|
||||
|
||||
impl GetMeta for CustomNotification {
|
||||
fn get_meta_mut(&mut self) -> &mut Meta {
|
||||
type Metadata = NotificationMetaObject;
|
||||
fn get_meta_mut(&mut self) -> &mut NotificationMetaObject {
|
||||
self.extensions_mut().get_or_insert_default()
|
||||
}
|
||||
fn get_meta(&self) -> &Meta {
|
||||
fn get_meta(&self) -> &NotificationMetaObject {
|
||||
self.extensions()
|
||||
.get::<Meta>()
|
||||
.unwrap_or(Meta::static_empty())
|
||||
.get::<NotificationMetaObject>()
|
||||
.unwrap_or(NotificationMetaObject::static_empty())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,19 +140,20 @@ impl GetExtensions for CustomRequest {
|
|||
}
|
||||
|
||||
impl GetMeta for CustomRequest {
|
||||
fn get_meta_mut(&mut self) -> &mut Meta {
|
||||
type Metadata = RequestMetaObject;
|
||||
fn get_meta_mut(&mut self) -> &mut RequestMetaObject {
|
||||
self.extensions_mut().get_or_insert_default()
|
||||
}
|
||||
fn get_meta(&self) -> &Meta {
|
||||
fn get_meta(&self) -> &RequestMetaObject {
|
||||
self.extensions()
|
||||
.get::<Meta>()
|
||||
.unwrap_or(Meta::static_empty())
|
||||
.get::<RequestMetaObject>()
|
||||
.unwrap_or(RequestMetaObject::static_empty())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! variant_extension {
|
||||
(
|
||||
$Enum: ident {
|
||||
$Enum: ident: $Metadata: ident {
|
||||
$($variant: ident)*
|
||||
}
|
||||
) => {
|
||||
|
|
@ -155,18 +174,19 @@ macro_rules! variant_extension {
|
|||
}
|
||||
}
|
||||
impl GetMeta for $Enum {
|
||||
fn get_meta_mut(&mut self) -> &mut Meta {
|
||||
type Metadata = $Metadata;
|
||||
fn get_meta_mut(&mut self) -> &mut $Metadata {
|
||||
self.extensions_mut().get_or_insert_default()
|
||||
}
|
||||
fn get_meta(&self) -> &Meta {
|
||||
self.extensions().get::<Meta>().unwrap_or(Meta::static_empty())
|
||||
fn get_meta(&self) -> &$Metadata {
|
||||
self.extensions().get::<$Metadata>().unwrap_or($Metadata::static_empty())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
variant_extension! {
|
||||
ClientRequest {
|
||||
ClientRequest: RequestMetaObject {
|
||||
PingRequest
|
||||
InitializeRequest
|
||||
CompleteRequest
|
||||
|
|
@ -189,7 +209,7 @@ variant_extension! {
|
|||
}
|
||||
|
||||
variant_extension! {
|
||||
ServerRequest {
|
||||
ServerRequest: RequestMetaObject {
|
||||
PingRequest
|
||||
CreateMessageRequest
|
||||
ListRootsRequest
|
||||
|
|
@ -199,7 +219,7 @@ variant_extension! {
|
|||
}
|
||||
|
||||
variant_extension! {
|
||||
ClientNotification {
|
||||
ClientNotification: NotificationMetaObject {
|
||||
CancelledNotification
|
||||
ProgressNotification
|
||||
InitializedNotification
|
||||
|
|
@ -210,7 +230,7 @@ variant_extension! {
|
|||
}
|
||||
|
||||
variant_extension! {
|
||||
ServerNotification {
|
||||
ServerNotification: NotificationMetaObject {
|
||||
CancelledNotification
|
||||
ProgressNotification
|
||||
LoggingMessageNotification
|
||||
|
|
@ -222,18 +242,31 @@ variant_extension! {
|
|||
CustomNotification
|
||||
}
|
||||
}
|
||||
|
||||
/// General-purpose `_meta` map (spec `MetaObject`).
|
||||
///
|
||||
/// This is the metadata shape used by results, content blocks, and catalog
|
||||
/// descriptors (tools, prompts, resources, roots, ...). It preserves arbitrary
|
||||
/// extension keys and offers helpers for the reserved W3C Trace Context keys
|
||||
/// (SEP-414).
|
||||
///
|
||||
/// Request and notification `_meta` maps have additional reserved keys; see
|
||||
/// [`RequestMetaObject`] and [`NotificationMetaObject`].
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(transparent)]
|
||||
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
|
||||
pub struct Meta(pub JsonObject);
|
||||
pub struct MetaObject(pub JsonObject);
|
||||
|
||||
impl Meta {
|
||||
const PROGRESS_TOKEN_FIELD: &str = "progressToken";
|
||||
const META_KEY_PROTOCOL_VERSION: &str = "io.modelcontextprotocol/protocolVersion";
|
||||
const META_KEY_CLIENT_INFO: &str = "io.modelcontextprotocol/clientInfo";
|
||||
const META_KEY_CLIENT_CAPABILITIES: &str = "io.modelcontextprotocol/clientCapabilities";
|
||||
const META_KEY_LOG_LEVEL: &str = "io.modelcontextprotocol/logLevel";
|
||||
/// Deprecated alias for [`MetaObject`].
|
||||
///
|
||||
/// This is a re-export rather than a type alias so the `Meta(...)` tuple
|
||||
/// constructor keeps working. Request and notification metadata now have
|
||||
/// dedicated types; use [`RequestMetaObject`] or [`NotificationMetaObject`]
|
||||
/// where those are expected.
|
||||
#[deprecated(note = "Use MetaObject (or RequestMetaObject / NotificationMetaObject)")]
|
||||
pub use self::MetaObject as Meta;
|
||||
|
||||
impl MetaObject {
|
||||
/// Reserved `_meta` key for the W3C Trace Context `traceparent` value (SEP-414).
|
||||
const TRACEPARENT_FIELD: &str = "traceparent";
|
||||
/// Reserved `_meta` key for the W3C Trace Context `tracestate` value (SEP-414).
|
||||
|
|
@ -241,102 +274,11 @@ impl Meta {
|
|||
/// Reserved `_meta` key for the W3C Baggage value (SEP-414).
|
||||
const BAGGAGE_FIELD: &str = "baggage";
|
||||
|
||||
/// Create an empty metadata map.
|
||||
pub fn new() -> Self {
|
||||
Self(JsonObject::new())
|
||||
}
|
||||
|
||||
/// Create a new Meta with a progress token set
|
||||
pub fn with_progress_token(token: ProgressToken) -> Self {
|
||||
let mut meta = Self::new();
|
||||
meta.set_progress_token(token);
|
||||
meta
|
||||
}
|
||||
|
||||
pub(crate) fn static_empty() -> &'static Self {
|
||||
static EMPTY: std::sync::OnceLock<Meta> = std::sync::OnceLock::new();
|
||||
EMPTY.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
pub fn get_progress_token(&self) -> Option<ProgressToken> {
|
||||
self.0
|
||||
.get(Self::PROGRESS_TOKEN_FIELD)
|
||||
.and_then(|v| match v {
|
||||
Value::String(s) => {
|
||||
Some(ProgressToken(NumberOrString::String(s.to_string().into())))
|
||||
}
|
||||
Value::Number(n) => {
|
||||
if let Some(i) = n.as_i64() {
|
||||
Some(ProgressToken(NumberOrString::Number(i)))
|
||||
} else if let Some(u) = n.as_u64() {
|
||||
if u <= i64::MAX as u64 {
|
||||
Some(ProgressToken(NumberOrString::Number(u as i64)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_progress_token(&mut self, token: ProgressToken) {
|
||||
match token.0 {
|
||||
NumberOrString::String(ref s) => self.0.insert(
|
||||
Self::PROGRESS_TOKEN_FIELD.to_string(),
|
||||
Value::String(s.to_string()),
|
||||
),
|
||||
NumberOrString::Number(n) => self.0.insert(
|
||||
Self::PROGRESS_TOKEN_FIELD.to_string(),
|
||||
Value::Number(n.into()),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/// Get the MCP protocol version carried in `_meta`, if present and valid.
|
||||
pub fn protocol_version(&self) -> Option<ProtocolVersion> {
|
||||
self.decode_value(Self::META_KEY_PROTOCOL_VERSION)
|
||||
}
|
||||
|
||||
/// Set the MCP protocol version carried in `_meta`.
|
||||
pub fn set_protocol_version(&mut self, protocol_version: ProtocolVersion) {
|
||||
self.0.insert(
|
||||
Self::META_KEY_PROTOCOL_VERSION.to_string(),
|
||||
Value::String(protocol_version.to_string()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Get the client implementation identity carried in `_meta`, if present and valid.
|
||||
pub fn client_info(&self) -> Option<Implementation> {
|
||||
self.decode_value(Self::META_KEY_CLIENT_INFO)
|
||||
}
|
||||
|
||||
/// Set the client implementation identity carried in `_meta`.
|
||||
pub fn set_client_info(&mut self, client_info: Implementation) {
|
||||
self.insert_serialized(Self::META_KEY_CLIENT_INFO, client_info);
|
||||
}
|
||||
|
||||
/// Get the client capabilities carried in `_meta`, if present and valid.
|
||||
pub fn client_capabilities(&self) -> Option<ClientCapabilities> {
|
||||
self.decode_value(Self::META_KEY_CLIENT_CAPABILITIES)
|
||||
}
|
||||
|
||||
/// Set the client capabilities carried in `_meta`.
|
||||
pub fn set_client_capabilities(&mut self, client_capabilities: ClientCapabilities) {
|
||||
self.insert_serialized(Self::META_KEY_CLIENT_CAPABILITIES, client_capabilities);
|
||||
}
|
||||
|
||||
/// Get the requested per-request log level carried in `_meta`, if present and valid.
|
||||
pub fn log_level(&self) -> Option<LoggingLevel> {
|
||||
self.decode_value(Self::META_KEY_LOG_LEVEL)
|
||||
}
|
||||
|
||||
/// Set the requested per-request log level carried in `_meta`.
|
||||
pub fn set_log_level(&mut self, log_level: LoggingLevel) {
|
||||
self.insert_serialized(Self::META_KEY_LOG_LEVEL, log_level);
|
||||
}
|
||||
|
||||
/// Read a string-valued `_meta` field, or `None` if absent or not a string.
|
||||
fn get_str(&self, field: &str) -> Option<&str> {
|
||||
self.0.get(field).and_then(Value::as_str)
|
||||
|
|
@ -356,9 +298,9 @@ impl Meta {
|
|||
/// Set the W3C `traceparent` value (SEP-414).
|
||||
///
|
||||
/// ```
|
||||
/// use rmcp::model::Meta;
|
||||
/// use rmcp::model::MetaObject;
|
||||
///
|
||||
/// let mut meta = Meta::new();
|
||||
/// let mut meta = MetaObject::new();
|
||||
/// meta.set_traceparent("00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01");
|
||||
/// assert_eq!(
|
||||
/// meta.get_traceparent(),
|
||||
|
|
@ -389,10 +331,9 @@ impl Meta {
|
|||
self.set_str(Self::BAGGAGE_FIELD, value);
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, other: Meta) {
|
||||
for (k, v) in other.0.into_iter() {
|
||||
self.0.insert(k, v);
|
||||
}
|
||||
/// Insert every entry of `other`, overwriting existing keys on conflict.
|
||||
pub fn extend(&mut self, other: MetaObject) {
|
||||
self.0.extend(other.0);
|
||||
}
|
||||
|
||||
fn decode_value<T>(&self, key: &str) -> Option<T>
|
||||
|
|
@ -412,7 +353,7 @@ impl Meta {
|
|||
}
|
||||
}
|
||||
|
||||
impl Deref for Meta {
|
||||
impl Deref for MetaObject {
|
||||
type Target = JsonObject;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
|
@ -420,12 +361,353 @@ impl Deref for Meta {
|
|||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Meta {
|
||||
impl DerefMut for MetaObject {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<JsonObject> for MetaObject {
|
||||
fn from(object: JsonObject) -> Self {
|
||||
Self(object)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "schemars")]
|
||||
impl schemars::JsonSchema for MetaObject {
|
||||
fn schema_name() -> std::borrow::Cow<'static, str> {
|
||||
std::borrow::Cow::Borrowed("MetaObject")
|
||||
}
|
||||
|
||||
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||
schemars::json_schema!({
|
||||
"description": "See [specification/draft/basic/index#general-fields] for notes on _meta usage.",
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The `_meta` map carried by requests (spec `RequestMetaObject`).
|
||||
///
|
||||
/// In addition to arbitrary extension keys, requests reserve:
|
||||
/// - `progressToken` for progress tracking
|
||||
/// - `io.modelcontextprotocol/protocolVersion` (SEP-2575)
|
||||
/// - `io.modelcontextprotocol/clientInfo` (SEP-2575)
|
||||
/// - `io.modelcontextprotocol/clientCapabilities` (SEP-2575)
|
||||
/// - `io.modelcontextprotocol/logLevel` (SEP-2575)
|
||||
///
|
||||
/// The 2026-07-28 draft schema marks the protocol-version, client-info, and
|
||||
/// client-capabilities keys as required; earlier protocol versions do not know
|
||||
/// them. All keys therefore stay optional at runtime and in the generated
|
||||
/// (version-shared) JSON schema — use
|
||||
/// [`RequestMetaObject::missing_required_keys`] to validate a request against
|
||||
/// the negotiated protocol version.
|
||||
///
|
||||
/// This type dereferences to [`MetaObject`] (and transitively to the underlying
|
||||
/// map), so general helpers such as the SEP-414 trace-context accessors remain
|
||||
/// available.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)]
|
||||
#[serde(transparent)]
|
||||
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
|
||||
pub struct RequestMetaObject(pub MetaObject);
|
||||
|
||||
impl RequestMetaObject {
|
||||
const PROGRESS_TOKEN_FIELD: &str = "progressToken";
|
||||
const META_KEY_PROTOCOL_VERSION: &str = "io.modelcontextprotocol/protocolVersion";
|
||||
const META_KEY_CLIENT_INFO: &str = "io.modelcontextprotocol/clientInfo";
|
||||
const META_KEY_CLIENT_CAPABILITIES: &str = "io.modelcontextprotocol/clientCapabilities";
|
||||
const META_KEY_LOG_LEVEL: &str = "io.modelcontextprotocol/logLevel";
|
||||
|
||||
/// Request `_meta` keys the 2026-07-28 draft schema marks as required.
|
||||
pub const DRAFT_REQUIRED_KEYS: [&str; 3] = [
|
||||
Self::META_KEY_PROTOCOL_VERSION,
|
||||
Self::META_KEY_CLIENT_INFO,
|
||||
Self::META_KEY_CLIENT_CAPABILITIES,
|
||||
];
|
||||
|
||||
/// Create an empty request metadata map.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Create a new request meta with a progress token set
|
||||
pub fn with_progress_token(token: ProgressToken) -> Self {
|
||||
let mut meta = Self::new();
|
||||
meta.set_progress_token(token);
|
||||
meta
|
||||
}
|
||||
|
||||
pub(crate) fn static_empty() -> &'static Self {
|
||||
static EMPTY: std::sync::OnceLock<RequestMetaObject> = std::sync::OnceLock::new();
|
||||
EMPTY.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
/// Get the progress token carried in `_meta`, if present and valid.
|
||||
pub fn get_progress_token(&self) -> Option<ProgressToken> {
|
||||
self.0.decode_value(Self::PROGRESS_TOKEN_FIELD)
|
||||
}
|
||||
|
||||
/// Set the progress token carried in `_meta`.
|
||||
pub fn set_progress_token(&mut self, token: ProgressToken) {
|
||||
self.0.insert_serialized(Self::PROGRESS_TOKEN_FIELD, token);
|
||||
}
|
||||
|
||||
/// Get the MCP protocol version carried in `_meta`, if present and valid.
|
||||
pub fn protocol_version(&self) -> Option<ProtocolVersion> {
|
||||
self.0.decode_value(Self::META_KEY_PROTOCOL_VERSION)
|
||||
}
|
||||
|
||||
/// Set the MCP protocol version carried in `_meta`.
|
||||
pub fn set_protocol_version(&mut self, protocol_version: ProtocolVersion) {
|
||||
self.0.0.insert(
|
||||
Self::META_KEY_PROTOCOL_VERSION.to_string(),
|
||||
Value::String(protocol_version.to_string()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Get the client implementation identity carried in `_meta`, if present and valid.
|
||||
pub fn client_info(&self) -> Option<Implementation> {
|
||||
self.0.decode_value(Self::META_KEY_CLIENT_INFO)
|
||||
}
|
||||
|
||||
/// Set the client implementation identity carried in `_meta`.
|
||||
pub fn set_client_info(&mut self, client_info: Implementation) {
|
||||
self.0
|
||||
.insert_serialized(Self::META_KEY_CLIENT_INFO, client_info);
|
||||
}
|
||||
|
||||
/// Get the client capabilities carried in `_meta`, if present and valid.
|
||||
pub fn client_capabilities(&self) -> Option<ClientCapabilities> {
|
||||
self.0.decode_value(Self::META_KEY_CLIENT_CAPABILITIES)
|
||||
}
|
||||
|
||||
/// Set the client capabilities carried in `_meta`.
|
||||
pub fn set_client_capabilities(&mut self, client_capabilities: ClientCapabilities) {
|
||||
self.0
|
||||
.insert_serialized(Self::META_KEY_CLIENT_CAPABILITIES, client_capabilities);
|
||||
}
|
||||
|
||||
/// Get the requested per-request log level carried in `_meta`, if present and valid.
|
||||
pub fn log_level(&self) -> Option<LoggingLevel> {
|
||||
self.0.decode_value(Self::META_KEY_LOG_LEVEL)
|
||||
}
|
||||
|
||||
/// Set the requested per-request log level carried in `_meta`.
|
||||
pub fn set_log_level(&mut self, log_level: LoggingLevel) {
|
||||
self.0
|
||||
.insert_serialized(Self::META_KEY_LOG_LEVEL, log_level);
|
||||
}
|
||||
|
||||
/// Return the [`Self::DRAFT_REQUIRED_KEYS`] whose values are absent or
|
||||
/// invalid in this map, if `protocol_version` requires them.
|
||||
///
|
||||
/// A key counts as missing when it is not present *or* when its value does
|
||||
/// not decode into the expected type (e.g. a numeric `protocolVersion` or
|
||||
/// a string `clientInfo`), matching what the typed accessors return.
|
||||
///
|
||||
/// Protocol versions before 2026-07-28 have no required request metadata,
|
||||
/// so this always returns an empty list for them.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use rmcp::model::{ProtocolVersion, RequestMetaObject};
|
||||
///
|
||||
/// let meta = RequestMetaObject::new();
|
||||
/// // Older protocols have no required request metadata.
|
||||
/// assert!(
|
||||
/// meta.missing_required_keys(&ProtocolVersion::V_2025_11_25)
|
||||
/// .is_empty()
|
||||
/// );
|
||||
/// // The 2026-07-28 draft requires the SEP-2575 keys.
|
||||
/// assert_eq!(
|
||||
/// meta.missing_required_keys(&ProtocolVersion::V_2026_07_28),
|
||||
/// RequestMetaObject::DRAFT_REQUIRED_KEYS.to_vec(),
|
||||
/// );
|
||||
/// ```
|
||||
pub fn missing_required_keys(&self, protocol_version: &ProtocolVersion) -> Vec<&'static str> {
|
||||
if protocol_version.as_str() < ProtocolVersion::V_2026_07_28.as_str() {
|
||||
return Vec::new();
|
||||
}
|
||||
let mut missing = Vec::new();
|
||||
if self.protocol_version().is_none() {
|
||||
missing.push(Self::META_KEY_PROTOCOL_VERSION);
|
||||
}
|
||||
if self.client_info().is_none() {
|
||||
missing.push(Self::META_KEY_CLIENT_INFO);
|
||||
}
|
||||
if self.client_capabilities().is_none() {
|
||||
missing.push(Self::META_KEY_CLIENT_CAPABILITIES);
|
||||
}
|
||||
missing
|
||||
}
|
||||
|
||||
/// Insert every entry of `other`, overwriting existing keys on conflict.
|
||||
pub fn extend(&mut self, other: RequestMetaObject) {
|
||||
self.0.extend(other.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for RequestMetaObject {
|
||||
type Target = MetaObject;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for RequestMetaObject {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MetaObject> for RequestMetaObject {
|
||||
fn from(meta: MetaObject) -> Self {
|
||||
Self(meta)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<JsonObject> for RequestMetaObject {
|
||||
fn from(object: JsonObject) -> Self {
|
||||
Self(MetaObject(object))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "schemars")]
|
||||
impl schemars::JsonSchema for RequestMetaObject {
|
||||
fn schema_name() -> std::borrow::Cow<'static, str> {
|
||||
std::borrow::Cow::Borrowed("RequestMetaObject")
|
||||
}
|
||||
|
||||
fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||
let progress_token = generator.subschema_for::<ProgressToken>();
|
||||
let client_info = generator.subschema_for::<Implementation>();
|
||||
let client_capabilities = generator.subschema_for::<ClientCapabilities>();
|
||||
let log_level = generator.subschema_for::<LoggingLevel>();
|
||||
// rmcp generates one schema shared by every supported protocol
|
||||
// version, so the keys the 2026-07-28 draft marks as required are left
|
||||
// optional here: a 2025-11-25 request whose `_meta` only carries
|
||||
// `progressToken` is valid. Draft-strict validation is available at
|
||||
// runtime via [`RequestMetaObject::missing_required_keys`].
|
||||
schemars::json_schema!({
|
||||
"description": "Metadata reserved by MCP on requests. Extension keys are also allowed.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"progressToken": progress_token,
|
||||
"io.modelcontextprotocol/protocolVersion": {
|
||||
"type": "string",
|
||||
},
|
||||
"io.modelcontextprotocol/clientInfo": client_info,
|
||||
"io.modelcontextprotocol/clientCapabilities": client_capabilities,
|
||||
"io.modelcontextprotocol/logLevel": log_level,
|
||||
},
|
||||
"additionalProperties": true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The `_meta` map carried by notifications (spec `NotificationMetaObject`).
|
||||
///
|
||||
/// In addition to arbitrary extension keys, notifications reserve
|
||||
/// `io.modelcontextprotocol/subscriptionId` to correlate a notification with a
|
||||
/// prior subscription request.
|
||||
///
|
||||
/// This type dereferences to [`MetaObject`] (and transitively to the underlying
|
||||
/// map), so general helpers such as the SEP-414 trace-context accessors remain
|
||||
/// available.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)]
|
||||
#[serde(transparent)]
|
||||
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
|
||||
pub struct NotificationMetaObject(pub MetaObject);
|
||||
|
||||
impl NotificationMetaObject {
|
||||
const META_KEY_SUBSCRIPTION_ID: &str = "io.modelcontextprotocol/subscriptionId";
|
||||
|
||||
/// Create an empty notification metadata map.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub(crate) fn static_empty() -> &'static Self {
|
||||
static EMPTY: std::sync::OnceLock<NotificationMetaObject> = std::sync::OnceLock::new();
|
||||
EMPTY.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
/// Get the subscription id carried in `_meta`, if present and valid.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use rmcp::model::{NotificationMetaObject, RequestId};
|
||||
///
|
||||
/// let mut meta = NotificationMetaObject::new();
|
||||
/// assert_eq!(meta.subscription_id(), None);
|
||||
/// meta.set_subscription_id(RequestId::Number(7));
|
||||
/// assert_eq!(meta.subscription_id(), Some(RequestId::Number(7)));
|
||||
/// ```
|
||||
pub fn subscription_id(&self) -> Option<RequestId> {
|
||||
self.0.decode_value(Self::META_KEY_SUBSCRIPTION_ID)
|
||||
}
|
||||
|
||||
/// Set the subscription id carried in `_meta`.
|
||||
pub fn set_subscription_id(&mut self, subscription_id: RequestId) {
|
||||
self.0
|
||||
.insert_serialized(Self::META_KEY_SUBSCRIPTION_ID, subscription_id);
|
||||
}
|
||||
|
||||
/// Insert every entry of `other`, overwriting existing keys on conflict.
|
||||
pub fn extend(&mut self, other: NotificationMetaObject) {
|
||||
self.0.extend(other.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for NotificationMetaObject {
|
||||
type Target = MetaObject;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for NotificationMetaObject {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MetaObject> for NotificationMetaObject {
|
||||
fn from(meta: MetaObject) -> Self {
|
||||
Self(meta)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<JsonObject> for NotificationMetaObject {
|
||||
fn from(object: JsonObject) -> Self {
|
||||
Self(MetaObject(object))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "schemars")]
|
||||
impl schemars::JsonSchema for NotificationMetaObject {
|
||||
fn schema_name() -> std::borrow::Cow<'static, str> {
|
||||
std::borrow::Cow::Borrowed("NotificationMetaObject")
|
||||
}
|
||||
|
||||
fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||
let subscription_id = generator.subschema_for::<RequestId>();
|
||||
schemars::json_schema!({
|
||||
"description": "Metadata reserved by MCP on notifications. Extension keys are also allowed.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"io.modelcontextprotocol/subscriptionId": subscription_id,
|
||||
},
|
||||
"additionalProperties": true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Req, Resp, Noti> JsonRpcMessage<Req, Resp, Noti>
|
||||
where
|
||||
Req: GetExtensions,
|
||||
|
|
@ -450,17 +732,18 @@ where
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::model::NumberOrString;
|
||||
|
||||
#[derive(Default)]
|
||||
struct Params {
|
||||
meta: Option<Meta>,
|
||||
meta: Option<RequestMetaObject>,
|
||||
}
|
||||
|
||||
impl RequestParamsMeta for Params {
|
||||
fn meta(&self) -> Option<&Meta> {
|
||||
fn meta(&self) -> Option<&RequestMetaObject> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
fn meta_mut(&mut self) -> &mut Option<Meta> {
|
||||
fn meta_mut(&mut self) -> &mut Option<RequestMetaObject> {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
||||
|
|
@ -469,7 +752,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn trace_context_round_trip() {
|
||||
let mut meta = Meta::new();
|
||||
let mut meta = MetaObject::new();
|
||||
meta.set_traceparent(TRACEPARENT);
|
||||
meta.set_tracestate("vendor1=value1,vendor2=value2");
|
||||
meta.set_baggage("userId=alice,region=us-east-1");
|
||||
|
|
@ -480,7 +763,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn absent_field_is_none() {
|
||||
let meta = Meta::new();
|
||||
let meta = MetaObject::new();
|
||||
assert_eq!(meta.get_traceparent(), None);
|
||||
assert_eq!(meta.get_tracestate(), None);
|
||||
assert_eq!(meta.get_baggage(), None);
|
||||
|
|
@ -488,9 +771,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn non_string_value_is_none() {
|
||||
let mut meta = Meta::new();
|
||||
let mut meta = MetaObject::new();
|
||||
meta.0
|
||||
.insert(Meta::TRACEPARENT_FIELD.to_string(), Value::from(42));
|
||||
.insert(MetaObject::TRACEPARENT_FIELD.to_string(), Value::from(42));
|
||||
assert_eq!(meta.get_traceparent(), None);
|
||||
}
|
||||
|
||||
|
|
@ -501,4 +784,91 @@ mod tests {
|
|||
params.set_traceparent(TRACEPARENT);
|
||||
assert_eq!(params.traceparent(), Some(TRACEPARENT));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_meta_derefs_to_general_helpers() {
|
||||
let mut meta = RequestMetaObject::new();
|
||||
meta.set_traceparent(TRACEPARENT);
|
||||
meta.set_progress_token(ProgressToken(NumberOrString::Number(7)));
|
||||
assert_eq!(meta.get_traceparent(), Some(TRACEPARENT));
|
||||
assert_eq!(
|
||||
meta.get_progress_token(),
|
||||
Some(ProgressToken(NumberOrString::Number(7)))
|
||||
);
|
||||
}
|
||||
|
||||
mod subscription_id {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn returns_none_when_absent() {
|
||||
let meta = NotificationMetaObject::new();
|
||||
assert_eq!(meta.subscription_id(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trips_number_id() {
|
||||
let mut meta = NotificationMetaObject::new();
|
||||
meta.set_subscription_id(RequestId::Number(42));
|
||||
assert_eq!(meta.subscription_id(), Some(RequestId::Number(42)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trips_string_id() {
|
||||
let mut meta = NotificationMetaObject::new();
|
||||
meta.set_subscription_id(RequestId::String("sub-1".into()));
|
||||
assert_eq!(
|
||||
meta.subscription_id(),
|
||||
Some(RequestId::String("sub-1".into()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
mod missing_required_keys {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn is_empty_for_pre_draft_protocols() {
|
||||
let meta = RequestMetaObject::new();
|
||||
assert!(
|
||||
meta.missing_required_keys(&ProtocolVersion::V_2025_11_25)
|
||||
.is_empty()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lists_all_draft_keys_for_empty_meta() {
|
||||
let meta = RequestMetaObject::new();
|
||||
assert_eq!(
|
||||
meta.missing_required_keys(&ProtocolVersion::V_2026_07_28),
|
||||
RequestMetaObject::DRAFT_REQUIRED_KEYS.to_vec()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn treats_malformed_values_as_missing() {
|
||||
let meta: RequestMetaObject = serde_json::from_value(serde_json::json!({
|
||||
"io.modelcontextprotocol/protocolVersion": 123,
|
||||
"io.modelcontextprotocol/clientInfo": "not an implementation",
|
||||
"io.modelcontextprotocol/clientCapabilities": null,
|
||||
}))
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
meta.missing_required_keys(&ProtocolVersion::V_2026_07_28),
|
||||
RequestMetaObject::DRAFT_REQUIRED_KEYS.to_vec()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_empty_when_draft_keys_are_present() {
|
||||
let mut meta = RequestMetaObject::new();
|
||||
meta.set_protocol_version(ProtocolVersion::V_2026_07_28);
|
||||
meta.set_client_info(Implementation::from_build_env());
|
||||
meta.set_client_capabilities(ClientCapabilities::default());
|
||||
assert!(
|
||||
meta.missing_required_keys(&ProtocolVersion::V_2026_07_28)
|
||||
.is_empty()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ use serde::{Deserialize, Serialize};
|
|||
use serde_json::Value;
|
||||
|
||||
use super::{
|
||||
CallToolResult, CreateMessageRequest, ElicitRequest, GetPromptResult, ListRootsRequest, Meta,
|
||||
ReadResourceResult, ResultType, ServerResult,
|
||||
CallToolResult, CreateMessageRequest, ElicitRequest, GetPromptResult, ListRootsRequest,
|
||||
MetaObject, ReadResourceResult, ResultType, ServerResult,
|
||||
};
|
||||
|
||||
/// Default maximum number of MRTR rounds a high-level client call will drive.
|
||||
|
|
@ -220,7 +220,7 @@ pub struct InputRequiredResult {
|
|||
|
||||
/// Optional protocol-level metadata.
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
/// Custom deserializer that requires `resultType: "input_required"` to prevent
|
||||
|
|
@ -238,7 +238,7 @@ impl<'de> Deserialize<'de> for InputRequiredResult {
|
|||
input_requests: Option<InputRequests>,
|
||||
request_state: Option<String>,
|
||||
#[serde(rename = "_meta")]
|
||||
meta: Option<Meta>,
|
||||
meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
let helper = Helper::deserialize(deserializer)?;
|
||||
|
|
@ -283,7 +283,7 @@ impl InputRequiredResult {
|
|||
}
|
||||
|
||||
/// Sets optional metadata.
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{
|
||||
Annotations, ContentBlock, Icon, Meta, Role,
|
||||
Annotations, ContentBlock, Icon, MetaObject, Role,
|
||||
content::{AudioContent, EmbeddedResource, ImageContent, TextContent},
|
||||
resource::ResourceContents,
|
||||
};
|
||||
|
|
@ -22,7 +22,7 @@ pub struct Prompt {
|
|||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub icons: Option<Vec<Icon>>,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
impl Prompt {
|
||||
|
|
@ -70,7 +70,7 @@ impl Prompt {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -144,7 +144,7 @@ impl PromptMessage {
|
|||
role: Role,
|
||||
data: &[u8],
|
||||
mime_type: &str,
|
||||
meta: Option<Meta>,
|
||||
meta: Option<MetaObject>,
|
||||
annotations: Option<Annotations>,
|
||||
) -> Self {
|
||||
use base64::{Engine, prelude::BASE64_STANDARD};
|
||||
|
|
@ -166,7 +166,7 @@ impl PromptMessage {
|
|||
role: Role,
|
||||
data: &[u8],
|
||||
mime_type: &str,
|
||||
meta: Option<Meta>,
|
||||
meta: Option<MetaObject>,
|
||||
annotations: Option<Annotations>,
|
||||
) -> Self {
|
||||
use base64::{Engine, prelude::BASE64_STANDARD};
|
||||
|
|
@ -188,8 +188,8 @@ impl PromptMessage {
|
|||
uri: String,
|
||||
mime_type: Option<String>,
|
||||
text: Option<String>,
|
||||
resource_meta: Option<Meta>,
|
||||
resource_content_meta: Option<Meta>,
|
||||
resource_meta: Option<MetaObject>,
|
||||
resource_content_meta: Option<MetaObject>,
|
||||
annotations: Option<Annotations>,
|
||||
) -> Self {
|
||||
let resource_contents = match text {
|
||||
|
|
@ -216,7 +216,11 @@ impl PromptMessage {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_text_with_meta<S: Into<String>>(role: Role, text: S, meta: Option<Meta>) -> Self {
|
||||
pub fn new_text_with_meta<S: Into<String>>(
|
||||
role: Role,
|
||||
text: S,
|
||||
meta: Option<MetaObject>,
|
||||
) -> Self {
|
||||
Self {
|
||||
role,
|
||||
content: ContentBlock::Text(TextContent {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{Annotations, Icon, Meta};
|
||||
use super::{Annotations, Icon, MetaObject};
|
||||
|
||||
/// A known resource that the server is capable of reading (spec `Resource`).
|
||||
///
|
||||
|
|
@ -31,7 +31,7 @@ pub struct Resource {
|
|||
pub icons: Option<Vec<Icon>>,
|
||||
/// Optional protocol-level metadata for this resource.
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
/// Optional annotations describing how the client should use this resource.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub annotations: Option<Annotations>,
|
||||
|
|
@ -77,7 +77,7 @@ impl Resource {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -112,7 +112,7 @@ pub struct ResourceTemplate {
|
|||
pub icons: Option<Vec<Icon>>,
|
||||
/// Optional protocol-level metadata for this resource template.
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
/// Optional annotations describing how the client should use this template.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub annotations: Option<Annotations>,
|
||||
|
|
@ -152,7 +152,7 @@ impl ResourceTemplate {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -176,7 +176,7 @@ pub enum ResourceContents {
|
|||
mime_type: Option<String>,
|
||||
text: String,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
meta: Option<Meta>,
|
||||
meta: Option<MetaObject>,
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
BlobResourceContents {
|
||||
|
|
@ -185,7 +185,7 @@ pub enum ResourceContents {
|
|||
mime_type: Option<String>,
|
||||
blob: String,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
meta: Option<Meta>,
|
||||
meta: Option<MetaObject>,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ impl ResourceContents {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
match &mut self {
|
||||
Self::TextResourceContents { meta: m, .. } => *m = Some(meta),
|
||||
Self::BlobResourceContents { meta: m, .. } => *m = Some(meta),
|
||||
|
|
@ -303,7 +303,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_resource_template_with_meta() {
|
||||
let resource_template =
|
||||
ResourceTemplate::new("file:///{path}", "template").with_meta(Meta::default());
|
||||
ResourceTemplate::new("file:///{path}", "template").with_meta(MetaObject::default());
|
||||
let json = serde_json::to_value(&resource_template).unwrap();
|
||||
assert!(json.get("_meta").is_some());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,19 @@ use std::borrow::Cow;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{
|
||||
CustomNotification, CustomRequest, Extensions, Meta, Notification, NotificationNoParam,
|
||||
Request, RequestNoParam, RequestOptionalParam,
|
||||
CustomNotification, CustomRequest, Extensions, JsonObject, MetaObject, Notification,
|
||||
NotificationMetaObject, NotificationNoParam, Request, RequestMetaObject, RequestNoParam,
|
||||
RequestOptionalParam,
|
||||
};
|
||||
|
||||
/// Wire-side view of `params`: the `_meta` map plus the remaining fields.
|
||||
///
|
||||
/// All metadata types are transparent wrappers over [`JsonObject`], so the
|
||||
/// serde plumbing works on the raw map; call sites wrap/unwrap the typed
|
||||
/// metadata ([`RequestMetaObject`] / [`NotificationMetaObject`]).
|
||||
#[derive(Deserialize)]
|
||||
struct WithMeta<'a, P> {
|
||||
_meta: Option<Cow<'a, Meta>>,
|
||||
_meta: Option<Cow<'a, JsonObject>>,
|
||||
#[serde(flatten)]
|
||||
_rest: P,
|
||||
}
|
||||
|
|
@ -25,7 +32,7 @@ impl<P: Serialize> Serialize for WithMeta<'_, P> {
|
|||
serde_json::to_value(&self._rest).map_err(serde::ser::Error::custom)?;
|
||||
|
||||
// Extract _meta from the serialized params (if it's an object containing one)
|
||||
let params_meta: Option<Meta> = rest_value
|
||||
let params_meta: Option<JsonObject> = rest_value
|
||||
.as_object_mut()
|
||||
.and_then(|obj| obj.remove("_meta"))
|
||||
.and_then(|v| serde_json::from_value(v).ok());
|
||||
|
|
@ -78,6 +85,53 @@ struct ProxyNoParam<M> {
|
|||
method: M,
|
||||
}
|
||||
|
||||
/// Combine the message-specific `_meta` map with a legacy [`MetaObject`]
|
||||
/// extension (inserted through the deprecated `Meta` name), so pre-3.x code
|
||||
/// does not silently lose metadata on the wire. On key conflicts the
|
||||
/// message-specific map wins.
|
||||
fn merge_legacy_meta<'a>(
|
||||
typed: Option<&'a JsonObject>,
|
||||
extensions: &'a Extensions,
|
||||
) -> Option<Cow<'a, JsonObject>> {
|
||||
let legacy = extensions.get::<MetaObject>().map(|meta| &meta.0);
|
||||
match (typed, legacy) {
|
||||
(Some(typed), None) => Some(Cow::Borrowed(typed)),
|
||||
(None, Some(legacy)) => Some(Cow::Borrowed(legacy)),
|
||||
(Some(typed), Some(legacy)) => {
|
||||
let mut merged = legacy.clone();
|
||||
merged.extend(typed.clone());
|
||||
Some(Cow::Owned(merged))
|
||||
}
|
||||
(None, None) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Borrow the request `_meta` map from extensions, if any.
|
||||
fn request_meta(extensions: &Extensions) -> Option<Cow<'_, JsonObject>> {
|
||||
let typed = extensions.get::<RequestMetaObject>().map(|meta| &meta.0.0);
|
||||
merge_legacy_meta(typed, extensions)
|
||||
}
|
||||
|
||||
/// Borrow the notification `_meta` map from extensions, if any.
|
||||
fn notification_meta(extensions: &Extensions) -> Option<Cow<'_, JsonObject>> {
|
||||
let typed = extensions
|
||||
.get::<NotificationMetaObject>()
|
||||
.map(|meta| &meta.0.0);
|
||||
merge_legacy_meta(typed, extensions)
|
||||
}
|
||||
|
||||
/// Build extensions holding a typed metadata map deserialized from `params._meta`.
|
||||
fn extensions_with_meta<T>(meta: Option<Cow<'_, JsonObject>>) -> Extensions
|
||||
where
|
||||
T: From<JsonObject> + Clone + Send + Sync + 'static,
|
||||
{
|
||||
let mut extensions = Extensions::new();
|
||||
if let Some(meta) = meta {
|
||||
extensions.insert(T::from(meta.into_owned()));
|
||||
}
|
||||
extensions
|
||||
}
|
||||
|
||||
impl<M, R> Serialize for Request<M, R>
|
||||
where
|
||||
M: Serialize,
|
||||
|
|
@ -87,14 +141,12 @@ where
|
|||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let extensions = &self.extensions;
|
||||
let _meta = extensions.get::<Meta>().map(Cow::Borrowed);
|
||||
Proxy::serialize(
|
||||
&Proxy {
|
||||
method: &self.method,
|
||||
params: WithMeta {
|
||||
_rest: &self.params,
|
||||
_meta,
|
||||
_meta: request_meta(&self.extensions),
|
||||
},
|
||||
},
|
||||
serializer,
|
||||
|
|
@ -112,13 +164,8 @@ where
|
|||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let body = Proxy::deserialize(deserializer)?;
|
||||
let _meta = body.params._meta.map(|m| m.into_owned());
|
||||
let mut extensions = Extensions::new();
|
||||
if let Some(meta) = _meta {
|
||||
extensions.insert(meta);
|
||||
}
|
||||
Ok(Request {
|
||||
extensions,
|
||||
extensions: extensions_with_meta::<RequestMetaObject>(body.params._meta),
|
||||
method: body.method,
|
||||
params: body.params._rest,
|
||||
})
|
||||
|
|
@ -134,14 +181,12 @@ where
|
|||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let extensions = &self.extensions;
|
||||
let _meta = extensions.get::<Meta>().map(Cow::Borrowed);
|
||||
Proxy::serialize(
|
||||
&Proxy {
|
||||
method: &self.method,
|
||||
params: WithMeta {
|
||||
_rest: &self.params,
|
||||
_meta,
|
||||
_meta: request_meta(&self.extensions),
|
||||
},
|
||||
},
|
||||
serializer,
|
||||
|
|
@ -163,14 +208,10 @@ where
|
|||
let mut _meta = None;
|
||||
if let Some(body_params) = body.params {
|
||||
params = body_params._rest;
|
||||
_meta = body_params._meta.map(|m| m.into_owned());
|
||||
}
|
||||
let mut extensions = Extensions::new();
|
||||
if let Some(meta) = _meta {
|
||||
extensions.insert(meta);
|
||||
_meta = body_params._meta;
|
||||
}
|
||||
Ok(RequestOptionalParam {
|
||||
extensions,
|
||||
extensions: extensions_with_meta::<RequestMetaObject>(_meta),
|
||||
method: body.method,
|
||||
params,
|
||||
})
|
||||
|
|
@ -185,14 +226,26 @@ where
|
|||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let extensions = &self.extensions;
|
||||
let _meta = extensions.get::<Meta>().map(Cow::Borrowed);
|
||||
ProxyNoParam::serialize(
|
||||
&ProxyNoParam {
|
||||
method: &self.method,
|
||||
},
|
||||
serializer,
|
||||
)
|
||||
// Emit `params` only when metadata is present, so the wire shape of
|
||||
// meta-less requests stays `{"method": ...}`.
|
||||
match request_meta(&self.extensions) {
|
||||
Some(_meta) => Proxy::serialize(
|
||||
&Proxy {
|
||||
method: &self.method,
|
||||
params: WithMeta {
|
||||
_meta: Some(_meta),
|
||||
_rest: (),
|
||||
},
|
||||
},
|
||||
serializer,
|
||||
),
|
||||
None => ProxyNoParam::serialize(
|
||||
&ProxyNoParam {
|
||||
method: &self.method,
|
||||
},
|
||||
serializer,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -204,10 +257,10 @@ where
|
|||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let body = ProxyNoParam::<_>::deserialize(deserializer)?;
|
||||
let extensions = Extensions::new();
|
||||
let body = ProxyOptionalParam::<'_, _, Option<JsonObject>>::deserialize(deserializer)?;
|
||||
let _meta = body.params.and_then(|params| params._meta);
|
||||
Ok(RequestNoParam {
|
||||
extensions,
|
||||
extensions: extensions_with_meta::<RequestMetaObject>(_meta),
|
||||
method: body.method,
|
||||
})
|
||||
}
|
||||
|
|
@ -222,14 +275,12 @@ where
|
|||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let extensions = &self.extensions;
|
||||
let _meta = extensions.get::<Meta>().map(Cow::Borrowed);
|
||||
Proxy::serialize(
|
||||
&Proxy {
|
||||
method: &self.method,
|
||||
params: WithMeta {
|
||||
_rest: &self.params,
|
||||
_meta,
|
||||
_meta: notification_meta(&self.extensions),
|
||||
},
|
||||
},
|
||||
serializer,
|
||||
|
|
@ -248,10 +299,7 @@ where
|
|||
{
|
||||
let body = ProxyOptionalParam::<'_, _, R>::deserialize(deserializer)?;
|
||||
let (_meta, params) = match body.params {
|
||||
Some(with_meta) => {
|
||||
let meta = with_meta._meta.map(|m| m.into_owned());
|
||||
(meta, with_meta._rest)
|
||||
}
|
||||
Some(with_meta) => (with_meta._meta, with_meta._rest),
|
||||
None => {
|
||||
// JSON-RPC 2.0: params is optional. Treat absent params as {}.
|
||||
let empty = serde_json::Value::Object(serde_json::Map::new());
|
||||
|
|
@ -259,12 +307,8 @@ where
|
|||
(None, r)
|
||||
}
|
||||
};
|
||||
let mut extensions = Extensions::new();
|
||||
if let Some(meta) = _meta {
|
||||
extensions.insert(meta);
|
||||
}
|
||||
Ok(Notification {
|
||||
extensions,
|
||||
extensions: extensions_with_meta::<NotificationMetaObject>(_meta),
|
||||
method: body.method,
|
||||
params,
|
||||
})
|
||||
|
|
@ -279,14 +323,26 @@ where
|
|||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let extensions = &self.extensions;
|
||||
let _meta = extensions.get::<Meta>().map(Cow::Borrowed);
|
||||
ProxyNoParam::serialize(
|
||||
&ProxyNoParam {
|
||||
method: &self.method,
|
||||
},
|
||||
serializer,
|
||||
)
|
||||
// Emit `params` only when metadata is present, so the wire shape of
|
||||
// meta-less notifications stays `{"method": ...}`.
|
||||
match notification_meta(&self.extensions) {
|
||||
Some(_meta) => Proxy::serialize(
|
||||
&Proxy {
|
||||
method: &self.method,
|
||||
params: WithMeta {
|
||||
_meta: Some(_meta),
|
||||
_rest: (),
|
||||
},
|
||||
},
|
||||
serializer,
|
||||
),
|
||||
None => ProxyNoParam::serialize(
|
||||
&ProxyNoParam {
|
||||
method: &self.method,
|
||||
},
|
||||
serializer,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -298,10 +354,10 @@ where
|
|||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let body = ProxyNoParam::<_>::deserialize(deserializer)?;
|
||||
let extensions = Extensions::new();
|
||||
let body = ProxyOptionalParam::<'_, _, Option<JsonObject>>::deserialize(deserializer)?;
|
||||
let _meta = body.params.and_then(|params| params._meta);
|
||||
Ok(NotificationNoParam {
|
||||
extensions,
|
||||
extensions: extensions_with_meta::<NotificationMetaObject>(_meta),
|
||||
method: body.method,
|
||||
})
|
||||
}
|
||||
|
|
@ -312,8 +368,7 @@ impl Serialize for CustomRequest {
|
|||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let extensions = &self.extensions;
|
||||
let _meta = extensions.get::<Meta>().map(Cow::Borrowed);
|
||||
let _meta = request_meta(&self.extensions);
|
||||
let params = self.params.as_ref();
|
||||
|
||||
let params = if _meta.is_some() || params.is_some() {
|
||||
|
|
@ -346,14 +401,10 @@ impl<'de> Deserialize<'de> for CustomRequest {
|
|||
let mut _meta = None;
|
||||
if let Some(body_params) = body.params {
|
||||
params = body_params._rest;
|
||||
_meta = body_params._meta.map(|m| m.into_owned());
|
||||
}
|
||||
let mut extensions = Extensions::new();
|
||||
if let Some(meta) = _meta {
|
||||
extensions.insert(meta);
|
||||
_meta = body_params._meta;
|
||||
}
|
||||
Ok(CustomRequest {
|
||||
extensions,
|
||||
extensions: extensions_with_meta::<RequestMetaObject>(_meta),
|
||||
method: body.method,
|
||||
params,
|
||||
})
|
||||
|
|
@ -365,8 +416,7 @@ impl Serialize for CustomNotification {
|
|||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let extensions = &self.extensions;
|
||||
let _meta = extensions.get::<Meta>().map(Cow::Borrowed);
|
||||
let _meta = notification_meta(&self.extensions);
|
||||
let params = self.params.as_ref();
|
||||
|
||||
let params = if _meta.is_some() || params.is_some() {
|
||||
|
|
@ -399,14 +449,10 @@ impl<'de> Deserialize<'de> for CustomNotification {
|
|||
let mut _meta = None;
|
||||
if let Some(body_params) = body.params {
|
||||
params = body_params._rest;
|
||||
_meta = body_params._meta.map(|m| m.into_owned());
|
||||
}
|
||||
let mut extensions = Extensions::new();
|
||||
if let Some(meta) = _meta {
|
||||
extensions.insert(meta);
|
||||
_meta = body_params._meta;
|
||||
}
|
||||
Ok(CustomNotification {
|
||||
extensions,
|
||||
extensions: extensions_with_meta::<NotificationMetaObject>(_meta),
|
||||
method: body.method,
|
||||
params,
|
||||
})
|
||||
|
|
@ -418,7 +464,8 @@ mod test {
|
|||
use serde_json::json;
|
||||
|
||||
use crate::model::{
|
||||
CallToolRequest, CallToolRequestParams, CustomRequest, Extensions, ListToolsRequest, Meta,
|
||||
CallToolRequest, CallToolRequestParams, CustomRequest, Extensions, InitializedNotification,
|
||||
ListToolsRequest, NotificationMetaObject, PingRequest, RequestMetaObject,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
|
@ -436,12 +483,12 @@ mod test {
|
|||
// When both extensions and params contain _meta, the output should have
|
||||
// a single merged _meta key (not two separate ones).
|
||||
let mut extensions = Extensions::new();
|
||||
let mut ext_meta = Meta::new();
|
||||
ext_meta.0.insert("traceId".to_string(), json!("abc"));
|
||||
let mut ext_meta = RequestMetaObject::new();
|
||||
ext_meta.insert("traceId".to_string(), json!("abc"));
|
||||
extensions.insert(ext_meta);
|
||||
|
||||
let mut params_meta = Meta::new();
|
||||
params_meta.0.insert("progressToken".to_string(), json!(1));
|
||||
let mut params_meta = RequestMetaObject::new();
|
||||
params_meta.insert("progressToken".to_string(), json!(1));
|
||||
|
||||
let req = CallToolRequest {
|
||||
extensions,
|
||||
|
|
@ -479,8 +526,8 @@ mod test {
|
|||
#[test]
|
||||
fn test_meta_only_from_extensions() {
|
||||
let mut extensions = Extensions::new();
|
||||
let mut ext_meta = Meta::new();
|
||||
ext_meta.0.insert("traceId".to_string(), json!("ext-only"));
|
||||
let mut ext_meta = RequestMetaObject::new();
|
||||
ext_meta.insert("traceId".to_string(), json!("ext-only"));
|
||||
extensions.insert(ext_meta);
|
||||
|
||||
let req = CallToolRequest {
|
||||
|
|
@ -503,8 +550,8 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_meta_only_from_params() {
|
||||
let mut params_meta = Meta::new();
|
||||
params_meta.0.insert("progressToken".to_string(), json!(42));
|
||||
let mut params_meta = RequestMetaObject::new();
|
||||
params_meta.insert("progressToken".to_string(), json!(42));
|
||||
|
||||
let req = CallToolRequest {
|
||||
extensions: Extensions::new(),
|
||||
|
|
@ -550,19 +597,13 @@ mod test {
|
|||
fn test_extensions_meta_takes_priority_on_conflict() {
|
||||
// When both sources have the same key, extensions should win.
|
||||
let mut extensions = Extensions::new();
|
||||
let mut ext_meta = Meta::new();
|
||||
ext_meta
|
||||
.0
|
||||
.insert("shared_key".to_string(), json!("from_extensions"));
|
||||
let mut ext_meta = RequestMetaObject::new();
|
||||
ext_meta.insert("shared_key".to_string(), json!("from_extensions"));
|
||||
extensions.insert(ext_meta);
|
||||
|
||||
let mut params_meta = Meta::new();
|
||||
params_meta
|
||||
.0
|
||||
.insert("shared_key".to_string(), json!("from_params"));
|
||||
params_meta
|
||||
.0
|
||||
.insert("params_only".to_string(), json!("kept"));
|
||||
let mut params_meta = RequestMetaObject::new();
|
||||
params_meta.insert("shared_key".to_string(), json!("from_params"));
|
||||
params_meta.insert("params_only".to_string(), json!("kept"));
|
||||
|
||||
let req = CallToolRequest {
|
||||
extensions,
|
||||
|
|
@ -586,10 +627,8 @@ mod test {
|
|||
#[test]
|
||||
fn test_round_trip_preserves_meta() {
|
||||
let mut extensions = Extensions::new();
|
||||
let mut ext_meta = Meta::new();
|
||||
ext_meta
|
||||
.0
|
||||
.insert("traceId".to_string(), json!("round-trip"));
|
||||
let mut ext_meta = RequestMetaObject::new();
|
||||
ext_meta.insert("traceId".to_string(), json!("round-trip"));
|
||||
extensions.insert(ext_meta);
|
||||
|
||||
let req = CallToolRequest {
|
||||
|
|
@ -609,8 +648,8 @@ mod test {
|
|||
let deserialized: CallToolRequest = serde_json::from_str(&serialized).unwrap();
|
||||
|
||||
// Extensions should have the meta after round-trip
|
||||
let meta = deserialized.extensions.get::<Meta>().unwrap();
|
||||
assert_eq!(meta.0.get("traceId").unwrap(), "round-trip");
|
||||
let meta = deserialized.extensions.get::<RequestMetaObject>().unwrap();
|
||||
assert_eq!(meta.get("traceId").unwrap(), "round-trip");
|
||||
|
||||
// Params should be preserved
|
||||
assert_eq!(deserialized.params.name, "my_tool");
|
||||
|
|
@ -630,10 +669,8 @@ mod test {
|
|||
fn test_custom_request_no_duplicate_meta() {
|
||||
// CustomRequest uses Option<Value> as params — verify no duplicate _meta.
|
||||
let mut extensions = Extensions::new();
|
||||
let mut ext_meta = Meta::new();
|
||||
ext_meta
|
||||
.0
|
||||
.insert("traceId".to_string(), json!("custom-ext"));
|
||||
let mut ext_meta = RequestMetaObject::new();
|
||||
ext_meta.insert("traceId".to_string(), json!("custom-ext"));
|
||||
extensions.insert(ext_meta);
|
||||
|
||||
let params = Some(json!({
|
||||
|
|
@ -660,4 +697,162 @@ mod test {
|
|||
assert_eq!(meta.get("traceId").unwrap(), "custom-ext");
|
||||
assert_eq!(meta.get("progressToken").unwrap(), 99);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_request_no_param_meta_round_trip() {
|
||||
// Ping-shaped requests must carry `params._meta` on the wire.
|
||||
let mut extensions = Extensions::new();
|
||||
let mut meta = RequestMetaObject::new();
|
||||
meta.insert("traceId".to_string(), json!("ping-trace"));
|
||||
extensions.insert(meta);
|
||||
|
||||
let req = PingRequest {
|
||||
method: Default::default(),
|
||||
extensions,
|
||||
};
|
||||
|
||||
let value = serde_json::to_value(&req).unwrap();
|
||||
assert_eq!(value["params"]["_meta"]["traceId"], json!("ping-trace"));
|
||||
|
||||
let deserialized: PingRequest = serde_json::from_value(value).unwrap();
|
||||
let meta = deserialized
|
||||
.extensions
|
||||
.get::<RequestMetaObject>()
|
||||
.expect("meta should survive the round-trip");
|
||||
assert_eq!(meta.get("traceId").unwrap(), &json!("ping-trace"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_request_no_param_without_meta_has_no_params_key() {
|
||||
let req = PingRequest {
|
||||
method: Default::default(),
|
||||
extensions: Extensions::new(),
|
||||
};
|
||||
let value = serde_json::to_value(&req).unwrap();
|
||||
assert!(
|
||||
value.get("params").is_none(),
|
||||
"meta-less no-param requests must keep the historical wire shape: {value}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_notification_no_param_meta_round_trip() {
|
||||
// Initialized-shaped notifications must carry `params._meta` on the wire.
|
||||
let mut extensions = Extensions::new();
|
||||
let mut meta = NotificationMetaObject::new();
|
||||
meta.insert("traceId".to_string(), json!("init-trace"));
|
||||
extensions.insert(meta);
|
||||
|
||||
let notification = InitializedNotification {
|
||||
method: Default::default(),
|
||||
extensions,
|
||||
};
|
||||
|
||||
let value = serde_json::to_value(¬ification).unwrap();
|
||||
assert_eq!(value["params"]["_meta"]["traceId"], json!("init-trace"));
|
||||
|
||||
let deserialized: InitializedNotification = serde_json::from_value(value).unwrap();
|
||||
let meta = deserialized
|
||||
.extensions
|
||||
.get::<NotificationMetaObject>()
|
||||
.expect("meta should survive the round-trip");
|
||||
assert_eq!(meta.get("traceId").unwrap(), &json!("init-trace"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_notification_no_param_without_meta_has_no_params_key() {
|
||||
let notification = InitializedNotification {
|
||||
method: Default::default(),
|
||||
extensions: Extensions::new(),
|
||||
};
|
||||
let value = serde_json::to_value(¬ification).unwrap();
|
||||
assert!(
|
||||
value.get("params").is_none(),
|
||||
"meta-less no-param notifications must keep the historical wire shape: {value}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_param_ignores_unknown_params_fields() {
|
||||
// Old/foreign peers may send params without _meta; both shapes must parse.
|
||||
let _req: PingRequest =
|
||||
serde_json::from_value(json!({"method": "ping", "params": {}})).unwrap();
|
||||
let _req: PingRequest =
|
||||
serde_json::from_value(json!({"method": "ping", "params": {"unknown": 1}})).unwrap();
|
||||
let _req: PingRequest = serde_json::from_value(json!({"method": "ping"})).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_legacy_meta_extension_still_serializes() {
|
||||
// Pre-3.x code inserts `MetaObject` into extensions through the
|
||||
// deprecated `Meta` name; its metadata must not be silently dropped.
|
||||
let mut extensions = Extensions::new();
|
||||
let mut legacy = crate::model::MetaObject::new();
|
||||
legacy.insert("traceId".to_string(), json!("legacy"));
|
||||
extensions.insert(legacy);
|
||||
|
||||
let req = CallToolRequest {
|
||||
extensions,
|
||||
method: Default::default(),
|
||||
params: CallToolRequestParams {
|
||||
meta: None,
|
||||
name: "my_tool".into(),
|
||||
arguments: None,
|
||||
task: None,
|
||||
input_responses: None,
|
||||
request_state: None,
|
||||
},
|
||||
};
|
||||
|
||||
let value = serde_json::to_value(&req).unwrap();
|
||||
assert_eq!(value["params"]["_meta"]["traceId"], json!("legacy"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_typed_meta_wins_over_legacy_extension_on_conflict() {
|
||||
let mut extensions = Extensions::new();
|
||||
let mut legacy = crate::model::MetaObject::new();
|
||||
legacy.insert("shared".to_string(), json!("legacy"));
|
||||
legacy.insert("legacy_only".to_string(), json!("kept"));
|
||||
extensions.insert(legacy);
|
||||
let mut typed = RequestMetaObject::new();
|
||||
typed.insert("shared".to_string(), json!("typed"));
|
||||
extensions.insert(typed);
|
||||
|
||||
let req = CallToolRequest {
|
||||
extensions,
|
||||
method: Default::default(),
|
||||
params: CallToolRequestParams {
|
||||
meta: None,
|
||||
name: "my_tool".into(),
|
||||
arguments: None,
|
||||
task: None,
|
||||
input_responses: None,
|
||||
request_state: None,
|
||||
},
|
||||
};
|
||||
|
||||
let value = serde_json::to_value(&req).unwrap();
|
||||
let meta = value["params"]["_meta"].as_object().unwrap();
|
||||
assert_eq!(meta.get("shared").unwrap(), "typed");
|
||||
assert_eq!(meta.get("legacy_only").unwrap(), "kept");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arbitrary_meta_keys_round_trip_unchanged() {
|
||||
let input = json!({
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"_meta": {
|
||||
"progressToken": 5,
|
||||
"vendor.example/custom": {"nested": ["a", 1, null]},
|
||||
"another-key": true
|
||||
},
|
||||
"name": "my_tool"
|
||||
}
|
||||
});
|
||||
let req: CallToolRequest = serde_json::from_value(input.clone()).unwrap();
|
||||
let output = serde_json::to_value(&req).unwrap();
|
||||
assert_eq!(input, output);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
use super::Meta;
|
||||
use super::MetaObject;
|
||||
|
||||
/// Metadata for augmenting a request with task execution (spec `TaskMetadata`).
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
||||
|
|
@ -139,7 +139,7 @@ impl Task {
|
|||
pub struct CreateTaskResult {
|
||||
pub task: Task,
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
impl CreateTaskResult {
|
||||
|
|
@ -149,7 +149,7 @@ impl CreateTaskResult {
|
|||
}
|
||||
|
||||
/// Sets the protocol-level metadata for this result.
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
@ -165,7 +165,7 @@ impl CreateTaskResult {
|
|||
#[non_exhaustive]
|
||||
pub struct GetTaskResult {
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
#[serde(flatten)]
|
||||
pub task: Task,
|
||||
}
|
||||
|
|
@ -222,7 +222,7 @@ impl<'de> serde::Deserialize<'de> for GetTaskPayloadResult {
|
|||
#[non_exhaustive]
|
||||
pub struct CancelTaskResult {
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
#[serde(flatten)]
|
||||
pub task: Task,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use schemars::JsonSchema;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
use super::{Icon, JsonObject, Meta};
|
||||
use super::{Icon, JsonObject, MetaObject};
|
||||
|
||||
/// A tool that can be used by a model.
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
|
|
@ -39,7 +39,7 @@ pub struct Tool {
|
|||
pub icons: Option<Vec<Icon>>,
|
||||
/// Optional additional metadata for this tool
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<MetaObject>,
|
||||
}
|
||||
|
||||
/// Per-tool task support mode as defined in the MCP specification.
|
||||
|
|
@ -286,7 +286,7 @@ impl Tool {
|
|||
}
|
||||
|
||||
/// Set the metadata
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
pub fn with_meta(mut self, meta: MetaObject) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ use crate::{
|
|||
error::ErrorData as McpError,
|
||||
model::{
|
||||
CancelledNotification, CancelledNotificationParam, Extensions, GetExtensions, GetMeta,
|
||||
JsonRpcError, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, Meta,
|
||||
NumberOrString, ProgressToken, RequestId,
|
||||
JsonRpcError, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse,
|
||||
NotificationMetaObject, NumberOrString, ProgressToken, RequestId, RequestMetaObject,
|
||||
},
|
||||
transport::{DynamicTransportError, IntoTransport, Transport},
|
||||
};
|
||||
|
|
@ -109,17 +109,17 @@ impl<T> TransferObject for T where
|
|||
|
||||
#[allow(private_bounds, reason = "there's no the third implementation")]
|
||||
pub trait ServiceRole: std::fmt::Debug + Send + Sync + 'static + Copy + Clone {
|
||||
type Req: TransferObject + GetMeta + GetExtensions;
|
||||
type Req: TransferObject + GetMeta<Metadata = RequestMetaObject> + GetExtensions;
|
||||
type Resp: TransferObject;
|
||||
type Not: TryInto<CancelledNotification, Error = Self::Not>
|
||||
+ From<CancelledNotification>
|
||||
+ TransferObject;
|
||||
type PeerReq: TransferObject + GetMeta + GetExtensions;
|
||||
type PeerReq: TransferObject + GetMeta<Metadata = RequestMetaObject> + GetExtensions;
|
||||
type PeerResp: TransferObject;
|
||||
type PeerNot: TryInto<CancelledNotification, Error = Self::PeerNot>
|
||||
+ From<CancelledNotification>
|
||||
+ TransferObject
|
||||
+ GetMeta
|
||||
+ GetMeta<Metadata = NotificationMetaObject>
|
||||
+ GetExtensions;
|
||||
type InitializeError;
|
||||
const IS_CLIENT: bool;
|
||||
|
|
@ -544,7 +544,7 @@ type ProxyOutbound<R> = mpsc::Receiver<PeerSinkMessage<R>>;
|
|||
#[non_exhaustive]
|
||||
pub struct PeerRequestOptions {
|
||||
pub timeout: Option<Duration>,
|
||||
pub meta: Option<Meta>,
|
||||
pub meta: Option<RequestMetaObject>,
|
||||
/// Reset the request timeout when a matching progress notification is received.
|
||||
pub reset_timeout_on_progress: bool,
|
||||
/// Maximum total time to wait for the request, regardless of progress notifications.
|
||||
|
|
@ -862,7 +862,7 @@ pub struct RequestContext<R: ServiceRole> {
|
|||
/// this token will be cancelled when the [`CancelledNotification`] is received.
|
||||
pub ct: CancellationToken,
|
||||
pub id: RequestId,
|
||||
pub meta: Meta,
|
||||
pub meta: RequestMetaObject,
|
||||
pub extensions: Extensions,
|
||||
/// An interface to fetch the remote client or server
|
||||
pub peer: Peer<R>,
|
||||
|
|
@ -874,7 +874,7 @@ impl<R: ServiceRole> RequestContext<R> {
|
|||
Self {
|
||||
ct: CancellationToken::new(),
|
||||
id,
|
||||
meta: Meta::default(),
|
||||
meta: RequestMetaObject::default(),
|
||||
extensions: Extensions::default(),
|
||||
peer,
|
||||
}
|
||||
|
|
@ -895,7 +895,7 @@ impl RequestContext<RoleServer> {
|
|||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub struct NotificationContext<R: ServiceRole> {
|
||||
pub meta: Meta,
|
||||
pub meta: NotificationMetaObject,
|
||||
pub extensions: Extensions,
|
||||
/// An interface to fetch the remote client or server
|
||||
pub peer: Peer<R>,
|
||||
|
|
@ -1171,7 +1171,7 @@ where
|
|||
let context_ct = request_ct.child_token();
|
||||
local_ct_pool.insert(id.clone(), request_ct);
|
||||
let mut extensions = Extensions::new();
|
||||
let mut meta = Meta::new();
|
||||
let mut meta = RequestMetaObject::new();
|
||||
// avoid clone
|
||||
// swap meta firstly, otherwise progress token will be lost
|
||||
std::mem::swap(&mut meta, request.get_meta_mut());
|
||||
|
|
@ -1226,7 +1226,7 @@ where
|
|||
{
|
||||
let service = shared_service.clone();
|
||||
let mut extensions = Extensions::new();
|
||||
let mut meta = Meta::new();
|
||||
let mut meta = NotificationMetaObject::new();
|
||||
// avoid clone
|
||||
std::mem::swap(&mut extensions, notification.extensions_mut());
|
||||
std::mem::swap(&mut meta, notification.get_meta_mut());
|
||||
|
|
|
|||
|
|
@ -115,11 +115,11 @@ where
|
|||
|
||||
let mut context = NotificationContext {
|
||||
peer: peer.clone(),
|
||||
meta: Meta::default(),
|
||||
meta: NotificationMetaObject::default(),
|
||||
extensions: Extensions::default(),
|
||||
};
|
||||
|
||||
if let Some(meta) = logging.extensions.get_mut::<Meta>() {
|
||||
if let Some(meta) = logging.extensions.get_mut::<NotificationMetaObject>() {
|
||||
std::mem::swap(&mut context.meta, meta);
|
||||
}
|
||||
std::mem::swap(&mut context.extensions, &mut logging.extensions);
|
||||
|
|
@ -890,7 +890,7 @@ where
|
|||
|
||||
fn input_request_context<T>(&self, key: &str, request: &mut T) -> RequestContext<RoleClient>
|
||||
where
|
||||
T: GetMeta + GetExtensions,
|
||||
T: GetMeta<Metadata = crate::model::RequestMetaObject> + GetExtensions,
|
||||
{
|
||||
let mut meta = Default::default();
|
||||
let mut extensions = Default::default();
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ async fn test_elicitation_result_serialization() {
|
|||
assert_eq!(deserialized.meta, None);
|
||||
|
||||
// Test protocol-level metadata round-trips as _meta.
|
||||
let meta_result = ElicitResult::new(ElicitationAction::Accept).with_meta(Meta(object!({
|
||||
let meta_result = ElicitResult::new(ElicitationAction::Accept).with_meta(MetaObject(object!({
|
||||
"traceId": "elicitation-123"
|
||||
})));
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ async fn test_elicitation_result_serialization() {
|
|||
let deserialized: ElicitResult = serde_json::from_value(expected).unwrap();
|
||||
assert_eq!(
|
||||
deserialized.meta,
|
||||
Some(Meta(object!({ "traceId": "elicitation-123" })))
|
||||
Some(MetaObject(object!({ "traceId": "elicitation-123" })))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use rmcp::model::{ContentBlock, EmbeddedResource, Meta, ResourceContents};
|
||||
use rmcp::model::{ContentBlock, EmbeddedResource, MetaObject, ResourceContents};
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn serialize_embedded_text_resource_with_meta() {
|
||||
let mut resource_content_meta = Meta::new();
|
||||
let mut resource_content_meta = MetaObject::new();
|
||||
resource_content_meta.insert("inner".to_string(), json!(2));
|
||||
|
||||
let mut resource_meta = Meta::new();
|
||||
let mut resource_meta = MetaObject::new();
|
||||
resource_meta.insert("top".to_string(), json!(1));
|
||||
|
||||
let content = ContentBlock::Resource(
|
||||
|
|
@ -90,10 +90,10 @@ fn deserialize_embedded_text_resource_with_meta() {
|
|||
|
||||
#[test]
|
||||
fn serialize_embedded_blob_resource_with_meta() {
|
||||
let mut resource_content_meta = Meta::new();
|
||||
let mut resource_content_meta = MetaObject::new();
|
||||
resource_content_meta.insert("blob_inner".to_string(), json!(true));
|
||||
|
||||
let mut resource_meta = Meta::new();
|
||||
let mut resource_meta = MetaObject::new();
|
||||
resource_meta.insert("blob_top".to_string(), json!("t"));
|
||||
|
||||
let content = ContentBlock::Resource(
|
||||
|
|
|
|||
|
|
@ -61,6 +61,60 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
/// The three metadata definitions must expose the MCP 2026-07-28 draft
|
||||
/// vocabulary: `MetaObject` is an open map, `RequestMetaObject` reserves
|
||||
/// `progressToken` plus the SEP-2575 keys, and `NotificationMetaObject`
|
||||
/// reserves `io.modelcontextprotocol/subscriptionId`. The keys the draft
|
||||
/// marks as required stay optional because rmcp generates one schema
|
||||
/// shared by every supported protocol version; draft-strict validation is
|
||||
/// a runtime concern (`RequestMetaObject::missing_required_keys`).
|
||||
#[test]
|
||||
fn test_metadata_definitions_match_draft_schema() {
|
||||
let settings = SchemaSettings::draft07();
|
||||
let schema = settings
|
||||
.into_generator()
|
||||
.into_root_schema_for::<ClientJsonRpcMessage>();
|
||||
let schema = serde_json::to_value(&schema).expect("Failed to serialize schema");
|
||||
let definitions = &schema["definitions"];
|
||||
|
||||
assert_eq!(
|
||||
definitions["MetaObject"],
|
||||
serde_json::json!({
|
||||
"description": "See [specification/draft/basic/index#general-fields] for notes on _meta usage.",
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
})
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
definitions["RequestMetaObject"],
|
||||
serde_json::json!({
|
||||
"description": "Metadata reserved by MCP on requests. Extension keys are also allowed.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"progressToken": { "$ref": "#/definitions/ProgressToken" },
|
||||
"io.modelcontextprotocol/protocolVersion": { "type": "string" },
|
||||
"io.modelcontextprotocol/clientInfo": { "$ref": "#/definitions/Implementation" },
|
||||
"io.modelcontextprotocol/clientCapabilities": { "$ref": "#/definitions/ClientCapabilities" },
|
||||
"io.modelcontextprotocol/logLevel": { "$ref": "#/definitions/LoggingLevel" },
|
||||
},
|
||||
"additionalProperties": true,
|
||||
})
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
definitions["NotificationMetaObject"],
|
||||
serde_json::json!({
|
||||
"description": "Metadata reserved by MCP on notifications. Extension keys are also allowed.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"io.modelcontextprotocol/subscriptionId": { "$ref": "#/definitions/NumberOrString" },
|
||||
},
|
||||
"additionalProperties": true,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_server_json_rpc_message_schema() {
|
||||
let settings = SchemaSettings::draft07();
|
||||
|
|
|
|||
|
|
@ -86,11 +86,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -128,11 +131,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"arguments": {
|
||||
"description": "Arguments to pass to the tool (must match the tool's input schema)",
|
||||
|
|
@ -187,11 +193,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"taskId": {
|
||||
"type": "string"
|
||||
|
|
@ -210,11 +219,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"reason": {
|
||||
"type": [
|
||||
|
|
@ -334,11 +346,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"argument": {
|
||||
"$ref": "#/definitions/ArgumentInfo"
|
||||
|
|
@ -474,11 +489,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"description": "The actual content of the message (text, image, audio, tool use, or tool result)",
|
||||
|
|
@ -550,11 +568,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this result.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"action": {
|
||||
"description": "The user's decision on how to handle the elicitation request",
|
||||
|
|
@ -638,11 +659,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -727,11 +751,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"arguments": {
|
||||
"type": [
|
||||
|
|
@ -773,11 +800,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"taskId": {
|
||||
"type": "string"
|
||||
|
|
@ -797,11 +827,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"taskId": {
|
||||
"type": "string"
|
||||
|
|
@ -873,11 +906,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -952,11 +988,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"capabilities": {
|
||||
"description": "The capabilities this client supports (sampling, roots, etc.)",
|
||||
|
|
@ -1169,11 +1208,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"roots": {
|
||||
"type": "array",
|
||||
|
|
@ -1212,6 +1254,11 @@
|
|||
"emergency"
|
||||
]
|
||||
},
|
||||
"MetaObject": {
|
||||
"description": "See [specification/draft/basic/index#general-fields] for notes on _meta usage.",
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"Notification": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -1257,6 +1304,16 @@
|
|||
"params"
|
||||
]
|
||||
},
|
||||
"NotificationMetaObject": {
|
||||
"description": "Metadata reserved by MCP on notifications. Extension keys are also allowed.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"io.modelcontextprotocol/subscriptionId": {
|
||||
"$ref": "#/definitions/NumberOrString"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"NotificationNoParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -1294,11 +1351,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cursor": {
|
||||
"type": [
|
||||
|
|
@ -1322,11 +1382,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"description": "An optional message describing the current progress.",
|
||||
|
|
@ -1397,11 +1460,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"inputResponses": {
|
||||
"description": "Client responses to server-initiated input requests from a previous\n[`InputRequiredResult`].",
|
||||
|
|
@ -1641,6 +1707,28 @@
|
|||
"params"
|
||||
]
|
||||
},
|
||||
"RequestMetaObject": {
|
||||
"description": "Metadata reserved by MCP on requests. Extension keys are also allowed.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"io.modelcontextprotocol/clientCapabilities": {
|
||||
"$ref": "#/definitions/ClientCapabilities"
|
||||
},
|
||||
"io.modelcontextprotocol/clientInfo": {
|
||||
"$ref": "#/definitions/Implementation"
|
||||
},
|
||||
"io.modelcontextprotocol/logLevel": {
|
||||
"$ref": "#/definitions/LoggingLevel"
|
||||
},
|
||||
"io.modelcontextprotocol/protocolVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"progressToken": {
|
||||
"$ref": "#/definitions/ProgressToken"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"RequestNoParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -1763,11 +1851,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this resource.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this resource.",
|
||||
|
|
@ -1841,11 +1932,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mimeType": {
|
||||
"type": [
|
||||
|
|
@ -1869,11 +1963,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"blob": {
|
||||
"type": "string"
|
||||
|
|
@ -1925,11 +2022,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": [
|
||||
|
|
@ -2116,11 +2216,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"level": {
|
||||
"description": "The desired logging level",
|
||||
|
|
@ -2147,11 +2250,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uri": {
|
||||
"description": "The URI of the resource to subscribe to",
|
||||
|
|
@ -2252,11 +2358,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createdAt": {
|
||||
"description": "ISO-8601 creation timestamp.",
|
||||
|
|
@ -2347,11 +2456,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -2378,11 +2490,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"type": "array",
|
||||
|
|
@ -2412,11 +2527,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
|
|
@ -2459,11 +2577,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uri": {
|
||||
"description": "The URI of the resource to unsubscribe from",
|
||||
|
|
|
|||
|
|
@ -86,11 +86,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -128,11 +131,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"arguments": {
|
||||
"description": "Arguments to pass to the tool (must match the tool's input schema)",
|
||||
|
|
@ -187,11 +193,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"taskId": {
|
||||
"type": "string"
|
||||
|
|
@ -210,11 +219,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"reason": {
|
||||
"type": [
|
||||
|
|
@ -334,11 +346,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"argument": {
|
||||
"$ref": "#/definitions/ArgumentInfo"
|
||||
|
|
@ -474,11 +489,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"description": "The actual content of the message (text, image, audio, tool use, or tool result)",
|
||||
|
|
@ -550,11 +568,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this result.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"action": {
|
||||
"description": "The user's decision on how to handle the elicitation request",
|
||||
|
|
@ -638,11 +659,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -727,11 +751,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"arguments": {
|
||||
"type": [
|
||||
|
|
@ -773,11 +800,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"taskId": {
|
||||
"type": "string"
|
||||
|
|
@ -797,11 +827,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"taskId": {
|
||||
"type": "string"
|
||||
|
|
@ -873,11 +906,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -952,11 +988,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"capabilities": {
|
||||
"description": "The capabilities this client supports (sampling, roots, etc.)",
|
||||
|
|
@ -1169,11 +1208,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"roots": {
|
||||
"type": "array",
|
||||
|
|
@ -1212,6 +1254,11 @@
|
|||
"emergency"
|
||||
]
|
||||
},
|
||||
"MetaObject": {
|
||||
"description": "See [specification/draft/basic/index#general-fields] for notes on _meta usage.",
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"Notification": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -1257,6 +1304,16 @@
|
|||
"params"
|
||||
]
|
||||
},
|
||||
"NotificationMetaObject": {
|
||||
"description": "Metadata reserved by MCP on notifications. Extension keys are also allowed.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"io.modelcontextprotocol/subscriptionId": {
|
||||
"$ref": "#/definitions/NumberOrString"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"NotificationNoParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -1294,11 +1351,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cursor": {
|
||||
"type": [
|
||||
|
|
@ -1322,11 +1382,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"description": "An optional message describing the current progress.",
|
||||
|
|
@ -1397,11 +1460,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"inputResponses": {
|
||||
"description": "Client responses to server-initiated input requests from a previous\n[`InputRequiredResult`].",
|
||||
|
|
@ -1641,6 +1707,28 @@
|
|||
"params"
|
||||
]
|
||||
},
|
||||
"RequestMetaObject": {
|
||||
"description": "Metadata reserved by MCP on requests. Extension keys are also allowed.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"io.modelcontextprotocol/clientCapabilities": {
|
||||
"$ref": "#/definitions/ClientCapabilities"
|
||||
},
|
||||
"io.modelcontextprotocol/clientInfo": {
|
||||
"$ref": "#/definitions/Implementation"
|
||||
},
|
||||
"io.modelcontextprotocol/logLevel": {
|
||||
"$ref": "#/definitions/LoggingLevel"
|
||||
},
|
||||
"io.modelcontextprotocol/protocolVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"progressToken": {
|
||||
"$ref": "#/definitions/ProgressToken"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"RequestNoParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -1763,11 +1851,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this resource.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this resource.",
|
||||
|
|
@ -1841,11 +1932,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mimeType": {
|
||||
"type": [
|
||||
|
|
@ -1869,11 +1963,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"blob": {
|
||||
"type": "string"
|
||||
|
|
@ -1925,11 +2022,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": [
|
||||
|
|
@ -2116,11 +2216,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"level": {
|
||||
"description": "The desired logging level",
|
||||
|
|
@ -2147,11 +2250,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uri": {
|
||||
"description": "The URI of the resource to subscribe to",
|
||||
|
|
@ -2252,11 +2358,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createdAt": {
|
||||
"description": "ISO-8601 creation timestamp.",
|
||||
|
|
@ -2347,11 +2456,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -2378,11 +2490,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"type": "array",
|
||||
|
|
@ -2412,11 +2527,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
|
|
@ -2459,11 +2577,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uri": {
|
||||
"description": "The URI of the resource to unsubscribe from",
|
||||
|
|
|
|||
|
|
@ -76,11 +76,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -171,11 +174,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this result",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"description": "The content returned by the tool (text, images, etc.)",
|
||||
|
|
@ -211,11 +217,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createdAt": {
|
||||
"description": "ISO-8601 creation timestamp.",
|
||||
|
|
@ -279,11 +288,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"reason": {
|
||||
"type": [
|
||||
|
|
@ -303,15 +315,89 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"CompleteResult": {
|
||||
"ClientCapabilities": {
|
||||
"title": "Builder",
|
||||
"description": "```rust\n# use rmcp::model::ClientCapabilities;\nlet cap = ClientCapabilities::builder()\n .enable_experimental()\n .build();\n```",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"elicitation": {
|
||||
"description": "Capability to handle elicitation requests from servers for interactive user input",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ElicitationCapability"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"experimental": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"extensions": {
|
||||
"description": "Optional MCP extensions that the client supports (SEP-1724).\nKeys are extension identifiers (e.g., `\"io.modelcontextprotocol/ui\"`),\nvalues are per-extension settings objects. An empty object indicates\nsupport with no settings.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"roots": {
|
||||
"description": "Capability for filesystem roots (deprecated by SEP-2577).",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RootsCapabilities"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sampling": {
|
||||
"description": "Capability for LLM sampling requests (SEP-1577, deprecated by SEP-2577).",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SamplingCapability"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tasks": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/TasksCapability"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"CompleteResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"completion": {
|
||||
"$ref": "#/definitions/CompletionInfo"
|
||||
|
|
@ -495,11 +581,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Protocol-level metadata for this request (SEP-1319)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"includeContext": {
|
||||
"description": "How much context to include from MCP servers",
|
||||
|
|
@ -608,11 +697,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"task": {
|
||||
"$ref": "#/definitions/Task"
|
||||
|
|
@ -658,11 +750,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
|
|
@ -685,11 +780,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"elicitationId": {
|
||||
"type": "string"
|
||||
|
|
@ -716,11 +814,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
|
|
@ -742,11 +843,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this result.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"action": {
|
||||
"description": "The user's decision on how to handle the elicitation request",
|
||||
|
|
@ -784,6 +888,34 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"ElicitationCapability": {
|
||||
"description": "Elicitation allows servers to request interactive input from users during tool execution.\nThis capability indicates that a client can handle elicitation requests and present\nappropriate UI to users for collecting the requested information.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"form": {
|
||||
"description": "Whether client supports form-based elicitation.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/FormElicitationCapability"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"description": "Whether client supports URL-based elicitation.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/UrlElicitationCapability"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"ElicitationCreateRequestMethod": {
|
||||
"type": "string",
|
||||
"format": "const",
|
||||
|
|
@ -856,11 +988,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -935,15 +1070,31 @@
|
|||
"message"
|
||||
]
|
||||
},
|
||||
"FormElicitationCapability": {
|
||||
"description": "Capability for handling elicitation requests from servers.\nElicitation allows servers to request interactive input from users during tool execution.\nThis capability indicates that a client can handle elicitation requests and present\nappropriate UI to users for collecting the requested information.\n\nCapability for form mode elicitation.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"schemaValidation": {
|
||||
"description": "Whether the client supports JSON Schema validation for elicitation responses.\nWhen true, the client will validate user input against the requested_schema\nbefore sending the response back to the server.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"GetPromptResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"type": [
|
||||
|
|
@ -979,11 +1130,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createdAt": {
|
||||
"description": "ISO-8601 creation timestamp.",
|
||||
|
|
@ -1100,11 +1254,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -1178,11 +1335,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"capabilities": {
|
||||
"description": "The capabilities this server provides (tools, resources, prompts, etc.)",
|
||||
|
|
@ -1257,11 +1417,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"inputRequests": {
|
||||
"description": "Server-initiated requests that the client must fulfill before retrying.",
|
||||
|
|
@ -1524,11 +1687,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cacheScope": {
|
||||
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||
|
|
@ -1580,11 +1746,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cacheScope": {
|
||||
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||
|
|
@ -1636,11 +1805,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cacheScope": {
|
||||
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||
|
|
@ -1697,11 +1869,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"nextCursor": {
|
||||
"type": [
|
||||
|
|
@ -1724,11 +1899,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cacheScope": {
|
||||
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||
|
|
@ -1801,11 +1979,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"description": "The actual log data"
|
||||
|
|
@ -1832,6 +2013,11 @@
|
|||
"data"
|
||||
]
|
||||
},
|
||||
"MetaObject": {
|
||||
"description": "See [specification/draft/basic/index#general-fields] for notes on _meta usage.",
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"ModelHint": {
|
||||
"description": "A hint suggesting a preferred model name or family.\n\nModel hints are advisory suggestions that help clients choose appropriate\nmodels. They can be specific model names or general families like \"claude\" or \"gpt\".",
|
||||
"type": "object",
|
||||
|
|
@ -1973,6 +2159,16 @@
|
|||
"params"
|
||||
]
|
||||
},
|
||||
"NotificationMetaObject": {
|
||||
"description": "Metadata reserved by MCP on notifications. Extension keys are also allowed.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"io.modelcontextprotocol/subscriptionId": {
|
||||
"$ref": "#/definitions/NumberOrString"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"NotificationNoParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -2140,11 +2336,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"description": "An optional message describing the current progress.",
|
||||
|
|
@ -2188,11 +2387,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"arguments": {
|
||||
"type": [
|
||||
|
|
@ -2303,11 +2505,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cacheScope": {
|
||||
"description": "Scope describing who may cache this result (SEP-2549).\nRequired by spec version 2026-07-28, but optional here to maintain compatibility\nwith older spec versions.",
|
||||
|
|
@ -2382,6 +2587,28 @@
|
|||
"params"
|
||||
]
|
||||
},
|
||||
"RequestMetaObject": {
|
||||
"description": "Metadata reserved by MCP on requests. Extension keys are also allowed.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"io.modelcontextprotocol/clientCapabilities": {
|
||||
"$ref": "#/definitions/ClientCapabilities"
|
||||
},
|
||||
"io.modelcontextprotocol/clientInfo": {
|
||||
"$ref": "#/definitions/Implementation"
|
||||
},
|
||||
"io.modelcontextprotocol/logLevel": {
|
||||
"$ref": "#/definitions/LoggingLevel"
|
||||
},
|
||||
"io.modelcontextprotocol/protocolVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"progressToken": {
|
||||
"$ref": "#/definitions/ProgressToken"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"RequestNoParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -2410,11 +2637,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this resource.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this resource.",
|
||||
|
|
@ -2488,11 +2718,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mimeType": {
|
||||
"type": [
|
||||
|
|
@ -2516,11 +2749,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"blob": {
|
||||
"type": "string"
|
||||
|
|
@ -2553,11 +2789,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this resource template.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this template.",
|
||||
|
|
@ -2625,11 +2864,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uri": {
|
||||
"description": "The URI of the resource that was updated",
|
||||
|
|
@ -2676,6 +2918,40 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"RootsCapabilities": {
|
||||
"description": "Roots capability. Deprecated by SEP-2577; remains functional and will be\nremoved in a future release.\nSee <https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577>.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"listChanged": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"SamplingCapability": {
|
||||
"description": "Sampling capability with optional sub-capabilities (SEP-1577).\n\nDeprecated by SEP-2577; remains functional and will be removed in a future\nrelease.\nSee <https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577>.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {
|
||||
"description": "Support for `includeContext` (soft-deprecated)",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
},
|
||||
"tools": {
|
||||
"description": "Support for `tools` and `toolChoice` parameters",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"SamplingContent": {
|
||||
"description": "Single or array content wrapper (SEP-1577).",
|
||||
"anyOf": [
|
||||
|
|
@ -2695,11 +2971,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"description": "The actual content of the message (text, image, audio, tool use, or tool result)",
|
||||
|
|
@ -3226,11 +3505,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NotificationMetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createdAt": {
|
||||
"description": "ISO-8601 creation timestamp.",
|
||||
|
|
@ -3341,11 +3623,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional protocol-level metadata for this content block.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional annotations describing how the client should use this content.",
|
||||
|
|
@ -3478,11 +3763,14 @@
|
|||
"properties": {
|
||||
"_meta": {
|
||||
"description": "Optional additional metadata for this tool",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Optional additional tool information.",
|
||||
|
|
@ -3658,11 +3946,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"type": "array",
|
||||
|
|
@ -3692,11 +3983,14 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": true
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MetaObject"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
|
|
@ -3848,6 +4142,10 @@
|
|||
"type",
|
||||
"enum"
|
||||
]
|
||||
},
|
||||
"UrlElicitationCapability": {
|
||||
"description": "Capability for URL mode elicitation.",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue