feat: add title field for data types (#410)
* feat(model): add title field to various structs * fix(test): fix test json schema * fix(model): allow boxed type in `ts_union` macro
This commit is contained in:
parent
fdd6bc0565
commit
1b70f5b032
16 changed files with 219 additions and 73 deletions
|
|
@ -10,6 +10,8 @@ use crate::common::{extract_doc_line, none_expr};
|
||||||
pub struct PromptAttribute {
|
pub struct PromptAttribute {
|
||||||
/// The name of the prompt
|
/// The name of the prompt
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
|
/// Human readable title of prompt
|
||||||
|
pub title: Option<String>,
|
||||||
/// Optional description of what the prompt does
|
/// Optional description of what the prompt does
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
/// Arguments that can be passed to the prompt
|
/// Arguments that can be passed to the prompt
|
||||||
|
|
@ -18,6 +20,7 @@ pub struct PromptAttribute {
|
||||||
|
|
||||||
pub struct ResolvedPromptAttribute {
|
pub struct ResolvedPromptAttribute {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub title: Option<String>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub arguments: Expr,
|
pub arguments: Expr,
|
||||||
}
|
}
|
||||||
|
|
@ -28,18 +31,25 @@ impl ResolvedPromptAttribute {
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
arguments,
|
arguments,
|
||||||
|
title,
|
||||||
} = self;
|
} = self;
|
||||||
let description = if let Some(description) = description {
|
let description = if let Some(description) = description {
|
||||||
quote! { Some(#description.into()) }
|
quote! { Some(#description.into()) }
|
||||||
} else {
|
} else {
|
||||||
quote! { None }
|
quote! { None }
|
||||||
};
|
};
|
||||||
|
let title = if let Some(title) = title {
|
||||||
|
quote! { Some(#title.into()) }
|
||||||
|
} else {
|
||||||
|
quote! { None }
|
||||||
|
};
|
||||||
let tokens = quote! {
|
let tokens = quote! {
|
||||||
pub fn #fn_ident() -> rmcp::model::Prompt {
|
pub fn #fn_ident() -> rmcp::model::Prompt {
|
||||||
rmcp::model::Prompt {
|
rmcp::model::Prompt {
|
||||||
name: #name.into(),
|
name: #name.into(),
|
||||||
description: #description,
|
description: #description,
|
||||||
arguments: #arguments,
|
arguments: #arguments,
|
||||||
|
title: #title,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -87,6 +97,7 @@ pub fn prompt(attr: TokenStream, input: TokenStream) -> syn::Result<TokenStream>
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
description: description.clone(),
|
description: description.clone(),
|
||||||
arguments: arguments.clone(),
|
arguments: arguments.clone(),
|
||||||
|
title: attribute.title,
|
||||||
};
|
};
|
||||||
let prompt_attr_fn = resolved_prompt_attr.into_fn(prompt_attr_fn_ident.clone())?;
|
let prompt_attr_fn = resolved_prompt_attr.into_fn(prompt_attr_fn_ident.clone())?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,8 @@ fn extract_schema_from_return_type(ret_type: &syn::Type) -> Option<Expr> {
|
||||||
pub struct ToolAttribute {
|
pub struct ToolAttribute {
|
||||||
/// The name of the tool
|
/// The name of the tool
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
|
/// Human readable title of tool
|
||||||
|
pub title: Option<String>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
/// A JSON Schema object defining the expected parameters for the tool
|
/// A JSON Schema object defining the expected parameters for the tool
|
||||||
pub input_schema: Option<Expr>,
|
pub input_schema: Option<Expr>,
|
||||||
|
|
@ -77,6 +79,7 @@ pub struct ToolAttribute {
|
||||||
|
|
||||||
pub struct ResolvedToolAttribute {
|
pub struct ResolvedToolAttribute {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub title: Option<String>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub input_schema: Expr,
|
pub input_schema: Expr,
|
||||||
pub output_schema: Option<Expr>,
|
pub output_schema: Option<Expr>,
|
||||||
|
|
@ -88,6 +91,7 @@ impl ResolvedToolAttribute {
|
||||||
let Self {
|
let Self {
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
|
title,
|
||||||
input_schema,
|
input_schema,
|
||||||
output_schema,
|
output_schema,
|
||||||
annotations,
|
annotations,
|
||||||
|
|
@ -102,10 +106,16 @@ impl ResolvedToolAttribute {
|
||||||
} else {
|
} else {
|
||||||
quote! { None }
|
quote! { None }
|
||||||
};
|
};
|
||||||
|
let title = if let Some(title) = title {
|
||||||
|
quote! { Some(#title.into()) }
|
||||||
|
} else {
|
||||||
|
quote! { None }
|
||||||
|
};
|
||||||
let tokens = quote! {
|
let tokens = quote! {
|
||||||
pub fn #fn_ident() -> rmcp::model::Tool {
|
pub fn #fn_ident() -> rmcp::model::Tool {
|
||||||
rmcp::model::Tool {
|
rmcp::model::Tool {
|
||||||
name: #name.into(),
|
name: #name.into(),
|
||||||
|
title: #title,
|
||||||
description: #description,
|
description: #description,
|
||||||
input_schema: #input_schema,
|
input_schema: #input_schema,
|
||||||
output_schema: #output_schema,
|
output_schema: #output_schema,
|
||||||
|
|
@ -229,6 +239,7 @@ pub fn tool(attr: TokenStream, input: TokenStream) -> syn::Result<TokenStream> {
|
||||||
input_schema: input_schema_expr,
|
input_schema: input_schema_expr,
|
||||||
output_schema: output_schema_expr,
|
output_schema: output_schema_expr,
|
||||||
annotations: annotations_expr,
|
annotations: annotations_expr,
|
||||||
|
title: attribute.title,
|
||||||
};
|
};
|
||||||
let tool_attr_fn = resolved_tool_attr.into_fn(tool_attr_fn_ident)?;
|
let tool_attr_fn = resolved_tool_attr.into_fn(tool_attr_fn_ident)?;
|
||||||
// modify the the input function
|
// modify the the input function
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ impl<H: ClientHandler> Service<RoleClient> for H {
|
||||||
ServerRequest::CreateMessageRequest(request) => self
|
ServerRequest::CreateMessageRequest(request) => self
|
||||||
.create_message(request.params, context)
|
.create_message(request.params, context)
|
||||||
.await
|
.await
|
||||||
|
.map(Box::new)
|
||||||
.map(ClientResult::CreateMessageResult),
|
.map(ClientResult::CreateMessageResult),
|
||||||
ServerRequest::ListRootsRequest(_) => self
|
ServerRequest::ListRootsRequest(_) => self
|
||||||
.list_roots(context)
|
.list_roots(context)
|
||||||
|
|
|
||||||
|
|
@ -350,6 +350,7 @@ pub fn cached_arguments_from_schema<T: schemars::JsonSchema + std::any::Any>()
|
||||||
|
|
||||||
arguments.push(crate::model::PromptArgument {
|
arguments.push(crate::model::PromptArgument {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
|
title: None,
|
||||||
description,
|
description,
|
||||||
required: Some(required.contains(name.as_str())),
|
required: Some(required.contains(name.as_str())),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -504,7 +504,7 @@ impl ErrorData {
|
||||||
/// Represents any JSON-RPC message that can be sent or received.
|
/// Represents any JSON-RPC message that can be sent or received.
|
||||||
///
|
///
|
||||||
/// This enum covers all possible message types in the JSON-RPC protocol:
|
/// This enum covers all possible message types in the JSON-RPC protocol:
|
||||||
/// individual requests/responses, notifications, batch operations, and errors.
|
/// individual requests/responses, notifications, and errors.
|
||||||
/// It serves as the top-level message container for MCP communication.
|
/// It serves as the top-level message container for MCP communication.
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
|
|
@ -697,6 +697,8 @@ impl Default for ClientInfo {
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
pub struct Implementation {
|
pub struct Implementation {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub title: Option<String>,
|
||||||
pub version: String,
|
pub version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -710,6 +712,7 @@ impl Implementation {
|
||||||
pub fn from_build_env() -> Self {
|
pub fn from_build_env() -> Self {
|
||||||
Implementation {
|
Implementation {
|
||||||
name: env!("CARGO_CRATE_NAME").to_owned(),
|
name: env!("CARGO_CRATE_NAME").to_owned(),
|
||||||
|
title: None,
|
||||||
version: env!("CARGO_PKG_VERSION").to_owned(),
|
version: env!("CARGO_PKG_VERSION").to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1115,6 +1118,8 @@ pub struct ResourceReference {
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
pub struct PromptReference {
|
pub struct PromptReference {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub title: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const_string!(CompleteRequestMethod = "completion/complete");
|
const_string!(CompleteRequestMethod = "completion/complete");
|
||||||
|
|
@ -1449,24 +1454,50 @@ pub struct GetPromptResult {
|
||||||
|
|
||||||
macro_rules! ts_union {
|
macro_rules! ts_union {
|
||||||
(
|
(
|
||||||
export type $U: ident =
|
export type $U:ident =
|
||||||
$(|)?$($V: ident)|*;
|
$($rest:tt)*
|
||||||
) => {
|
) => {
|
||||||
|
ts_union!(@declare $U { $($rest)* });
|
||||||
|
ts_union!(@impl_from $U { $($rest)* });
|
||||||
|
};
|
||||||
|
(@declare $U:ident { $($variant:tt)* }) => {
|
||||||
|
ts_union!(@declare_variant $U { } {$($variant)*} );
|
||||||
|
};
|
||||||
|
(@declare_variant $U:ident { $($declared:tt)* } {$(|)? box $V:ident $($rest:tt)*}) => {
|
||||||
|
ts_union!(@declare_variant $U { $($declared)* $V(Box<$V>), } {$($rest)*});
|
||||||
|
};
|
||||||
|
(@declare_variant $U:ident { $($declared:tt)* } {$(|)? $V:ident $($rest:tt)*}) => {
|
||||||
|
ts_union!(@declare_variant $U { $($declared)* $V($V), } {$($rest)*});
|
||||||
|
};
|
||||||
|
(@declare_variant $U:ident { $($declared:tt)* } { ; }) => {
|
||||||
|
ts_union!(@declare_end $U { $($declared)* } );
|
||||||
|
};
|
||||||
|
(@declare_end $U:ident { $($declared:tt)* }) => {
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
pub enum $U {
|
pub enum $U {
|
||||||
$($V($V),)*
|
$($declared)*
|
||||||
}
|
}
|
||||||
|
|
||||||
$(
|
|
||||||
impl From<$V> for $U {
|
|
||||||
fn from(value: $V) -> Self {
|
|
||||||
$U::$V(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
};
|
};
|
||||||
|
(@impl_from $U: ident {$(|)? box $V:ident $($rest:tt)*}) => {
|
||||||
|
impl From<$V> for $U {
|
||||||
|
fn from(value: $V) -> Self {
|
||||||
|
$U::$V(Box::new(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ts_union!(@impl_from $U {$($rest)*});
|
||||||
|
};
|
||||||
|
(@impl_from $U: ident {$(|)? $V:ident $($rest:tt)*}) => {
|
||||||
|
impl From<$V> for $U {
|
||||||
|
fn from(value: $V) -> Self {
|
||||||
|
$U::$V(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ts_union!(@impl_from $U {$($rest)*});
|
||||||
|
};
|
||||||
|
(@impl_from $U: ident { ; }) => {};
|
||||||
|
(@impl_from $U: ident { }) => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ts_union!(
|
ts_union!(
|
||||||
|
|
@ -1515,7 +1546,7 @@ ts_union!(
|
||||||
);
|
);
|
||||||
|
|
||||||
ts_union!(
|
ts_union!(
|
||||||
export type ClientResult = CreateMessageResult | ListRootsResult | CreateElicitationResult | EmptyResult;
|
export type ClientResult = box CreateMessageResult | ListRootsResult | CreateElicitationResult | EmptyResult;
|
||||||
);
|
);
|
||||||
|
|
||||||
impl ClientResult {
|
impl ClientResult {
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ pub enum RawContent {
|
||||||
Text(RawTextContent),
|
Text(RawTextContent),
|
||||||
Image(RawImageContent),
|
Image(RawImageContent),
|
||||||
Resource(RawEmbeddedResource),
|
Resource(RawEmbeddedResource),
|
||||||
Audio(AudioContent),
|
Audio(RawAudioContent),
|
||||||
ResourceLink(super::resource::RawResource),
|
ResourceLink(super::resource::RawResource),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -253,6 +253,7 @@ mod tests {
|
||||||
let resource_link = RawContent::ResourceLink(RawResource {
|
let resource_link = RawContent::ResourceLink(RawResource {
|
||||||
uri: "file:///test.txt".to_string(),
|
uri: "file:///test.txt".to_string(),
|
||||||
name: "test.txt".to_string(),
|
name: "test.txt".to_string(),
|
||||||
|
title: None,
|
||||||
description: Some("A test file".to_string()),
|
description: Some("A test file".to_string()),
|
||||||
mime_type: Some("text/plain".to_string()),
|
mime_type: Some("text/plain".to_string()),
|
||||||
size: Some(100),
|
size: Some(100),
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ use super::{
|
||||||
pub struct Prompt {
|
pub struct Prompt {
|
||||||
/// The name of the prompt
|
/// The name of the prompt
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub title: Option<String>,
|
||||||
/// Optional description of what the prompt does
|
/// Optional description of what the prompt does
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
|
@ -35,6 +37,7 @@ impl Prompt {
|
||||||
{
|
{
|
||||||
Prompt {
|
Prompt {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
|
title: None,
|
||||||
description: description.map(Into::into),
|
description: description.map(Into::into),
|
||||||
arguments,
|
arguments,
|
||||||
}
|
}
|
||||||
|
|
@ -47,6 +50,9 @@ impl Prompt {
|
||||||
pub struct PromptArgument {
|
pub struct PromptArgument {
|
||||||
/// The name of the argument
|
/// The name of the argument
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
/// A human-readable title for the argument
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub title: Option<String>,
|
||||||
/// A description of what the argument is used for
|
/// A description of what the argument is used for
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ pub struct RawResource {
|
||||||
pub uri: String,
|
pub uri: String,
|
||||||
/// Name of the resource
|
/// Name of the resource
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
/// Human-readable title of the resource
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub title: Option<String>,
|
||||||
/// Optional description of the resource
|
/// Optional description of the resource
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
|
@ -34,6 +37,8 @@ pub struct RawResourceTemplate {
|
||||||
pub uri_template: String,
|
pub uri_template: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub title: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub mime_type: Option<String>,
|
pub mime_type: Option<String>,
|
||||||
|
|
@ -82,6 +87,7 @@ impl RawResource {
|
||||||
Self {
|
Self {
|
||||||
uri: uri.into(),
|
uri: uri.into(),
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
|
title: None,
|
||||||
description: None,
|
description: None,
|
||||||
mime_type: None,
|
mime_type: None,
|
||||||
size: None,
|
size: None,
|
||||||
|
|
@ -99,6 +105,7 @@ mod tests {
|
||||||
fn test_resource_serialization() {
|
fn test_resource_serialization() {
|
||||||
let resource = RawResource {
|
let resource = RawResource {
|
||||||
uri: "file:///test.txt".to_string(),
|
uri: "file:///test.txt".to_string(),
|
||||||
|
title: None,
|
||||||
name: "test".to_string(),
|
name: "test".to_string(),
|
||||||
description: Some("Test resource".to_string()),
|
description: Some("Test resource".to_string()),
|
||||||
mime_type: Some("text/plain".to_string()),
|
mime_type: Some("text/plain".to_string()),
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ use super::JsonObject;
|
||||||
pub struct Tool {
|
pub struct Tool {
|
||||||
/// The name of the tool
|
/// The name of the tool
|
||||||
pub name: Cow<'static, str>,
|
pub name: Cow<'static, str>,
|
||||||
|
/// A human-readable title for the tool
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub title: Option<String>,
|
||||||
/// A description of what the tool does
|
/// A description of what the tool does
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub description: Option<Cow<'static, str>>,
|
pub description: Option<Cow<'static, str>>,
|
||||||
|
|
@ -138,6 +141,7 @@ impl Tool {
|
||||||
{
|
{
|
||||||
Tool {
|
Tool {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
|
title: None,
|
||||||
description: Some(description.into()),
|
description: Some(description.into()),
|
||||||
input_schema: input_schema.into(),
|
input_schema: input_schema.into(),
|
||||||
output_schema: None,
|
output_schema: None,
|
||||||
|
|
|
||||||
|
|
@ -384,7 +384,22 @@ macro_rules! method {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Peer<RoleServer> {
|
impl Peer<RoleServer> {
|
||||||
method!(peer_req create_message CreateMessageRequest(CreateMessageRequestParam) => CreateMessageResult);
|
pub async fn create_message(
|
||||||
|
&self,
|
||||||
|
params: CreateMessageRequestParam,
|
||||||
|
) -> Result<CreateMessageResult, ServiceError> {
|
||||||
|
let result = self
|
||||||
|
.send_request(ServerRequest::CreateMessageRequest(CreateMessageRequest {
|
||||||
|
method: Default::default(),
|
||||||
|
params,
|
||||||
|
extensions: Default::default(),
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
match result {
|
||||||
|
ClientResult::CreateMessageResult(result) => Ok(*result),
|
||||||
|
_ => Err(ServiceError::UnexpectedResponse),
|
||||||
|
}
|
||||||
|
}
|
||||||
method!(peer_req list_roots ListRootsRequest() => ListRootsResult);
|
method!(peer_req list_roots ListRootsRequest() => ListRootsResult);
|
||||||
#[cfg(feature = "elicitation")]
|
#[cfg(feature = "elicitation")]
|
||||||
method!(peer_req create_elicitation CreateElicitationRequest(CreateElicitationRequestParam) => CreateElicitationResult);
|
method!(peer_req create_elicitation CreateElicitationRequest(CreateElicitationRequestParam) => CreateElicitationResult);
|
||||||
|
|
|
||||||
|
|
@ -892,6 +892,7 @@ async fn test_initialize_request_with_elicitation() {
|
||||||
client_info: Implementation {
|
client_info: Implementation {
|
||||||
name: "test-client".to_string(),
|
name: "test-client".to_string(),
|
||||||
version: "1.0.0".to_string(),
|
version: "1.0.0".to_string(),
|
||||||
|
title: None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -933,6 +934,7 @@ async fn test_capability_checking_logic() {
|
||||||
client_info: Implementation {
|
client_info: Implementation {
|
||||||
name: "test-client".to_string(),
|
name: "test-client".to_string(),
|
||||||
version: "1.0.0".to_string(),
|
version: "1.0.0".to_string(),
|
||||||
|
title: None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -950,6 +952,7 @@ async fn test_capability_checking_logic() {
|
||||||
client_info: Implementation {
|
client_info: Implementation {
|
||||||
name: "test-client".to_string(),
|
name: "test-client".to_string(),
|
||||||
version: "1.0.0".to_string(),
|
version: "1.0.0".to_string(),
|
||||||
|
title: None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
"title": "JsonRpcMessage",
|
"title": "JsonRpcMessage",
|
||||||
"description": "Represents any JSON-RPC message that can be sent or received.\n\nThis enum covers all possible message types in the JSON-RPC protocol:\nindividual requests/responses, notifications, batch operations, and errors.\nIt serves as the top-level message container for MCP communication.",
|
"description": "Represents any JSON-RPC message that can be sent or received.\n\nThis enum covers all possible message types in the JSON-RPC protocol:\nindividual requests/responses, notifications, and errors.\nIt serves as the top-level message container for MCP communication.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"description": "A single request expecting a response",
|
"description": "A single request expecting a response",
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
},
|
},
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/Annotated2"
|
"$ref": "#/definitions/RawAudioContent"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -139,31 +139,6 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Annotated2": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"annotations": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/definitions/Annotations"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "null"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"mimeType": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"data",
|
|
||||||
"mimeType"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Annotations": {
|
"Annotations": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -491,6 +466,12 @@
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"title": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
|
@ -845,6 +826,12 @@
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -855,6 +842,21 @@
|
||||||
"description": "Represents the MCP protocol version used for communication.\n\nThis ensures compatibility between clients and servers by specifying\nwhich version of the Model Context Protocol is being used.",
|
"description": "Represents the MCP protocol version used for communication.\n\nThis ensures compatibility between clients and servers by specifying\nwhich version of the Model Context Protocol is being used.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"RawAudioContent": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"mimeType": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"data",
|
||||||
|
"mimeType"
|
||||||
|
]
|
||||||
|
},
|
||||||
"RawEmbeddedResource": {
|
"RawEmbeddedResource": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -929,6 +931,13 @@
|
||||||
"format": "uint32",
|
"format": "uint32",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
},
|
},
|
||||||
|
"title": {
|
||||||
|
"description": "Human-readable title of the resource",
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"uri": {
|
"uri": {
|
||||||
"description": "URI representing the resource location (e.g., \"file:///path/to/file\" or \"str:///content\")",
|
"description": "URI representing the resource location (e.g., \"file:///path/to/file\" or \"str:///content\")",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
"title": "JsonRpcMessage",
|
"title": "JsonRpcMessage",
|
||||||
"description": "Represents any JSON-RPC message that can be sent or received.\n\nThis enum covers all possible message types in the JSON-RPC protocol:\nindividual requests/responses, notifications, batch operations, and errors.\nIt serves as the top-level message container for MCP communication.",
|
"description": "Represents any JSON-RPC message that can be sent or received.\n\nThis enum covers all possible message types in the JSON-RPC protocol:\nindividual requests/responses, notifications, and errors.\nIt serves as the top-level message container for MCP communication.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"description": "A single request expecting a response",
|
"description": "A single request expecting a response",
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
},
|
},
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/Annotated2"
|
"$ref": "#/definitions/RawAudioContent"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -140,31 +140,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Annotated2": {
|
"Annotated2": {
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"annotations": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/definitions/Annotations"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "null"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"mimeType": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"data",
|
|
||||||
"mimeType"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Annotated3": {
|
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"_meta": {
|
"_meta": {
|
||||||
|
|
@ -193,7 +168,7 @@
|
||||||
"resource"
|
"resource"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Annotated4": {
|
"Annotated3": {
|
||||||
"description": "Represents a resource in the extension with metadata",
|
"description": "Represents a resource in the extension with metadata",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -234,6 +209,13 @@
|
||||||
"format": "uint32",
|
"format": "uint32",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
},
|
},
|
||||||
|
"title": {
|
||||||
|
"description": "Human-readable title of the resource",
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"uri": {
|
"uri": {
|
||||||
"description": "URI representing the resource location (e.g., \"file:///path/to/file\" or \"str:///content\")",
|
"description": "URI representing the resource location (e.g., \"file:///path/to/file\" or \"str:///content\")",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|
@ -244,7 +226,7 @@
|
||||||
"name"
|
"name"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Annotated5": {
|
"Annotated4": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"annotations": {
|
"annotations": {
|
||||||
|
|
@ -272,6 +254,12 @@
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"title": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"uriTemplate": {
|
"uriTemplate": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
|
@ -626,6 +614,12 @@
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"title": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
|
@ -815,7 +809,7 @@
|
||||||
"resourceTemplates": {
|
"resourceTemplates": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/Annotated5"
|
"$ref": "#/definitions/Annotated4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -835,7 +829,7 @@
|
||||||
"resources": {
|
"resources": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/Annotated4"
|
"$ref": "#/definitions/Annotated3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -1145,6 +1139,12 @@
|
||||||
"name": {
|
"name": {
|
||||||
"description": "The name of the prompt",
|
"description": "The name of the prompt",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -1172,6 +1172,13 @@
|
||||||
"boolean",
|
"boolean",
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"description": "A human-readable title for the argument",
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -1274,7 +1281,7 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"resource": {
|
"resource": {
|
||||||
"$ref": "#/definitions/Annotated3"
|
"$ref": "#/definitions/Annotated2"
|
||||||
},
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
@ -1327,6 +1334,13 @@
|
||||||
"format": "uint32",
|
"format": "uint32",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
},
|
},
|
||||||
|
"title": {
|
||||||
|
"description": "Human-readable title of the resource",
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"const": "resource_link"
|
"const": "resource_link"
|
||||||
|
|
@ -1367,6 +1381,21 @@
|
||||||
"description": "Represents the MCP protocol version used for communication.\n\nThis ensures compatibility between clients and servers by specifying\nwhich version of the Model Context Protocol is being used.",
|
"description": "Represents the MCP protocol version used for communication.\n\nThis ensures compatibility between clients and servers by specifying\nwhich version of the Model Context Protocol is being used.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"RawAudioContent": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"mimeType": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"data",
|
||||||
|
"mimeType"
|
||||||
|
]
|
||||||
|
},
|
||||||
"RawEmbeddedResource": {
|
"RawEmbeddedResource": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -1441,6 +1470,13 @@
|
||||||
"format": "uint32",
|
"format": "uint32",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
},
|
},
|
||||||
|
"title": {
|
||||||
|
"description": "Human-readable title of the resource",
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"uri": {
|
"uri": {
|
||||||
"description": "URI representing the resource location (e.g., \"file:///path/to/file\" or \"str:///content\")",
|
"description": "URI representing the resource location (e.g., \"file:///path/to/file\" or \"str:///content\")",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|
@ -1817,6 +1853,13 @@
|
||||||
"null"
|
"null"
|
||||||
],
|
],
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"description": "A human-readable title for the tool",
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ async fn main() -> Result<()> {
|
||||||
capabilities: ClientCapabilities::default(),
|
capabilities: ClientCapabilities::default(),
|
||||||
client_info: Implementation {
|
client_info: Implementation {
|
||||||
name: "test sse client".to_string(),
|
name: "test sse client".to_string(),
|
||||||
|
title: None,
|
||||||
version: "0.0.1".to_string(),
|
version: "0.0.1".to_string(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ async fn main() -> Result<()> {
|
||||||
capabilities: ClientCapabilities::default(),
|
capabilities: ClientCapabilities::default(),
|
||||||
client_info: Implementation {
|
client_info: Implementation {
|
||||||
name: "test sse client".to_string(),
|
name: "test sse client".to_string(),
|
||||||
|
title: None,
|
||||||
version: "0.0.1".to_string(),
|
version: "0.0.1".to_string(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ impl ServerHandler for SamplingDemoServer {
|
||||||
Ok(ListToolsResult {
|
Ok(ListToolsResult {
|
||||||
tools: vec![Tool {
|
tools: vec![Tool {
|
||||||
name: "ask_llm".into(),
|
name: "ask_llm".into(),
|
||||||
|
title: None,
|
||||||
description: Some("Ask a question to the LLM through sampling".into()),
|
description: Some("Ask a question to the LLM through sampling".into()),
|
||||||
input_schema: Arc::new(
|
input_schema: Arc::new(
|
||||||
serde_json::from_value(serde_json::json!({
|
serde_json::from_value(serde_json::json!({
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue