update to RMCP 0.6.2 (#4523)

This commit is contained in:
Max Novich
2025-09-05 06:54:10 -07:00
committed by GitHub
parent 0db329bac4
commit 195f389972
24 changed files with 191 additions and 24 deletions
Generated
+4 -4
View File
@@ -5467,9 +5467,9 @@ dependencies = [
[[package]] [[package]]
name = "rmcp" name = "rmcp"
version = "0.6.0" version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb21cd3555f1059f27e4813827338dec44429a08ecd0011acc41d9907b160c00" checksum = "817ef98583b16628962dd8214ee89e9a9df6a79de9b487eb29ceddb1f610a7f6"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"chrono", "chrono",
@@ -5495,9 +5495,9 @@ dependencies = [
[[package]] [[package]]
name = "rmcp-macros" name = "rmcp-macros"
version = "0.6.0" version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5d16ae1ff3ce2c5fd86c37047b2869b75bec795d53a4b1d8257b15415a2354" checksum = "9712e19c12a2812bffa85ab71714e2a342a9d7e79656e6f74f650475b8094090"
dependencies = [ dependencies = [
"darling 0.21.0", "darling 0.21.0",
"proc-macro2", "proc-macro2",
+1 -1
View File
@@ -14,7 +14,7 @@ description = "An AI agent"
uninlined_format_args = "allow" uninlined_format_args = "allow"
[workspace.dependencies] [workspace.dependencies]
rmcp = { version = "0.6.0", features = ["schemars", "auth"] } rmcp = { version = "0.6.2", features = ["schemars", "auth"] }
# Patch for Windows cross-compilation issue with crunchy # Patch for Windows cross-compilation issue with crunchy
[patch.crates-io] [patch.crates-io]
@@ -95,9 +95,10 @@ impl McpClientTrait for MockClient {
if let Some(handler) = self.handlers.get(name) { if let Some(handler) = self.handlers.get(name) {
match handler(&arguments) { match handler(&arguments) {
Ok(content) => Ok(CallToolResult { Ok(content) => Ok(CallToolResult {
content: content, content,
is_error: None, is_error: None,
structured_content: None, structured_content: None,
meta: None,
}), }),
Err(_e) => Err(Error::UnexpectedResponse), Err(_e) => Err(Error::UnexpectedResponse),
} }
+20
View File
@@ -256,6 +256,7 @@ pub fn tool_response_to_markdown(resp: &ToolResponse, export_all_content: bool)
uri, uri,
mime_type, mime_type,
text, text,
meta: _,
} => { } => {
// Extract file extension from the URI for syntax highlighting // Extract file extension from the URI for syntax highlighting
let file_extension = uri.split('.').next_back().unwrap_or(""); let file_extension = uri.split('.').next_back().unwrap_or("");
@@ -287,6 +288,7 @@ pub fn tool_response_to_markdown(resp: &ToolResponse, export_all_content: bool)
uri, uri,
mime_type, mime_type,
blob, blob,
..
} => { } => {
md.push_str(&format!( md.push_str(&format!(
"**Binary File:** `{}` (type: {}, {} bytes)\n\n", "**Binary File:** `{}` (type: {}, {} bytes)\n\n",
@@ -297,6 +299,10 @@ pub fn tool_response_to_markdown(resp: &ToolResponse, export_all_content: bool)
} }
} }
} }
RawContent::ResourceLink(_link) => {
// Show a simple placeholder for resource links when exporting
md.push_str("[resource link]\n\n");
}
RawContent::Audio(_) => { RawContent::Audio(_) => {
md.push_str("[audio content not displayed in Markdown export]\n\n") md.push_str("[audio content not displayed in Markdown export]\n\n")
} }
@@ -527,6 +533,7 @@ mod tests {
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: "Command executed successfully".to_string(), text: "Command executed successfully".to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -546,6 +553,7 @@ mod tests {
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: json_text.to_string(), text: json_text.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -650,6 +658,7 @@ if __name__ == "__main__":
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: python_code.to_string(), text: python_code.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -689,6 +698,7 @@ if __name__ == "__main__":
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: git_output.to_string(), text: git_output.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -736,6 +746,7 @@ warning: unused variable `x`
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: build_output.to_string(), text: build_output.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -781,6 +792,7 @@ warning: unused variable `x`
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: api_response.to_string(), text: api_response.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -815,6 +827,7 @@ warning: unused variable `x`
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: "File created successfully".to_string(), text: "File created successfully".to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -870,6 +883,7 @@ def process_data(data: List[Dict]) -> List[Dict]:
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: python_code.to_string(), text: python_code.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -905,6 +919,7 @@ Command failed with exit code 2"#;
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: error_output.to_string(), text: error_output.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -943,6 +958,7 @@ Command failed with exit code 2"#;
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: script_output.to_string(), text: script_output.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -988,6 +1004,7 @@ drwx------ 3 user staff 96 Dec 6 16:20 com.apple.launchd.abc
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: multi_output.to_string(), text: multi_output.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -1029,6 +1046,7 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: grep_output.to_string(), text: grep_output.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -1067,6 +1085,7 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: json_output.to_string(), text: json_output.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
@@ -1106,6 +1125,7 @@ found 0 vulnerabilities"#;
let text_content = TextContent { let text_content = TextContent {
raw: RawTextContent { raw: RawTextContent {
text: npm_output.to_string(), text: npm_output.to_string(),
meta: None,
}, },
annotations: None, annotations: None,
}; };
+12 -4
View File
@@ -642,6 +642,7 @@ impl AutoVisualiserRouter {
uri: "ui://sankey/diagram".to_string(), uri: "ui://sankey/diagram".to_string(),
mime_type: Some("text/html".to_string()), mime_type: Some("text/html".to_string()),
blob: base64_encoded, blob: base64_encoded,
meta: None,
}; };
Ok(vec![ Ok(vec![
@@ -686,6 +687,7 @@ impl AutoVisualiserRouter {
uri: "ui://radar/chart".to_string(), uri: "ui://radar/chart".to_string(),
mime_type: Some("text/html".to_string()), mime_type: Some("text/html".to_string()),
blob: base64_encoded, blob: base64_encoded,
meta: None,
}; };
Ok(vec![ Ok(vec![
@@ -730,6 +732,7 @@ impl AutoVisualiserRouter {
uri: "ui://treemap/visualization".to_string(), uri: "ui://treemap/visualization".to_string(),
mime_type: Some("text/html".to_string()), mime_type: Some("text/html".to_string()),
blob: base64_encoded, blob: base64_encoded,
meta: None,
}; };
Ok(vec![ Ok(vec![
@@ -774,6 +777,7 @@ impl AutoVisualiserRouter {
uri: "ui://chord/diagram".to_string(), uri: "ui://chord/diagram".to_string(),
mime_type: Some("text/html".to_string()), mime_type: Some("text/html".to_string()),
blob: base64_encoded, blob: base64_encoded,
meta: None,
}; };
Ok(vec![ Ok(vec![
@@ -818,6 +822,7 @@ impl AutoVisualiserRouter {
uri: "ui://donut/chart".to_string(), uri: "ui://donut/chart".to_string(),
mime_type: Some("text/html".to_string()), mime_type: Some("text/html".to_string()),
blob: base64_encoded, blob: base64_encoded,
meta: None,
}; };
Ok(vec![ Ok(vec![
@@ -879,6 +884,7 @@ impl AutoVisualiserRouter {
uri: "ui://map/visualization".to_string(), uri: "ui://map/visualization".to_string(),
mime_type: Some("text/html".to_string()), mime_type: Some("text/html".to_string()),
blob: base64_encoded, blob: base64_encoded,
meta: None,
}; };
Ok(vec![ Ok(vec![
@@ -923,6 +929,7 @@ impl AutoVisualiserRouter {
uri: "ui://chart/interactive".to_string(), uri: "ui://chart/interactive".to_string(),
mime_type: Some("text/html".to_string()), mime_type: Some("text/html".to_string()),
blob: base64_encoded, blob: base64_encoded,
meta: None,
}; };
Ok(vec![ Ok(vec![
@@ -1175,8 +1182,8 @@ mod tests {
assert_eq!(content[0].audience().unwrap(), &vec![Role::User]); assert_eq!(content[0].audience().unwrap(), &vec![Role::User]);
// Check it's a resource with HTML content // Check it's a resource with HTML content
// Content is Annotated<RawContent>, deref to get RawContent // Content is Annotated<RawContent>, access underlying RawContent via *
if let RawContent::Resource(resource) = &**&content[0] { if let RawContent::Resource(resource) = &*content[0] {
if let ResourceContents::BlobResourceContents { uri, mime_type, .. } = if let ResourceContents::BlobResourceContents { uri, mime_type, .. } =
&resource.resource &resource.resource
{ {
@@ -1212,12 +1219,13 @@ mod tests {
assert_eq!(content[0].audience().unwrap(), &vec![Role::User]); assert_eq!(content[0].audience().unwrap(), &vec![Role::User]);
// Check it's a resource with HTML content // Check it's a resource with HTML content
// Content is Annotated<RawContent>, deref to get RawContent // Content is Annotated<RawContent>, access underlying RawContent via *
if let RawContent::Resource(resource) = &**&content[0] { if let RawContent::Resource(resource) = &*content[0] {
if let ResourceContents::BlobResourceContents { if let ResourceContents::BlobResourceContents {
uri, uri,
mime_type, mime_type,
blob, blob,
..
} = &resource.resource } = &resource.resource
{ {
assert_eq!(uri, "ui://radar/chart"); assert_eq!(uri, "ui://radar/chart");
@@ -3,7 +3,7 @@ use ignore::gitignore::{Gitignore, GitignoreBuilder};
use include_dir::{include_dir, Dir}; use include_dir::{include_dir, Dir};
use indoc::{formatdoc, indoc}; use indoc::{formatdoc, indoc};
use rmcp::{ use rmcp::{
handler::server::{router::tool::ToolRouter, tool::Parameters}, handler::server::{router::tool::ToolRouter, wrapper::Parameters},
model::{ model::{
CallToolResult, Content, ErrorCode, ErrorData, GetPromptRequestParam, GetPromptResult, CallToolResult, Content, ErrorCode, ErrorData, GetPromptRequestParam, GetPromptResult,
Implementation, ListPromptsResult, LoggingLevel, LoggingMessageNotificationParam, Implementation, ListPromptsResult, LoggingLevel, LoggingMessageNotificationParam,
@@ -1242,7 +1242,7 @@ impl DeveloperServer {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use rmcp::handler::server::tool::Parameters; use rmcp::handler::server::wrapper::Parameters;
use rmcp::model::NumberOrString; use rmcp::model::NumberOrString;
use rmcp::service::serve_directly; use rmcp::service::serve_directly;
use serial_test::serial; use serial_test::serial;
+3 -1
View File
@@ -9,7 +9,7 @@ use goose::session::info::SessionInfo;
use goose::session::SessionMetadata; use goose::session::SessionMetadata;
use rmcp::model::{ use rmcp::model::{
Annotations, Content, EmbeddedResource, ImageContent, RawEmbeddedResource, RawImageContent, Annotations, Content, EmbeddedResource, ImageContent, RawEmbeddedResource, RawImageContent,
RawTextContent, ResourceContents, Role, TextContent, Tool, ToolAnnotations, RawResource, RawTextContent, ResourceContents, Role, TextContent, Tool, ToolAnnotations,
}; };
use utoipa::{OpenApi, ToSchema}; use utoipa::{OpenApi, ToSchema};
@@ -319,6 +319,7 @@ derive_utoipa!(TextContent as TextContentSchema);
derive_utoipa!(RawTextContent as RawTextContentSchema); derive_utoipa!(RawTextContent as RawTextContentSchema);
derive_utoipa!(RawImageContent as RawImageContentSchema); derive_utoipa!(RawImageContent as RawImageContentSchema);
derive_utoipa!(RawEmbeddedResource as RawEmbeddedResourceSchema); derive_utoipa!(RawEmbeddedResource as RawEmbeddedResourceSchema);
derive_utoipa!(RawResource as RawResourceSchema);
derive_utoipa!(Tool as ToolSchema); derive_utoipa!(Tool as ToolSchema);
derive_utoipa!(ToolAnnotations as ToolAnnotationsSchema); derive_utoipa!(ToolAnnotations as ToolAnnotationsSchema);
derive_utoipa!(Annotations as AnnotationsSchema); derive_utoipa!(Annotations as AnnotationsSchema);
@@ -425,6 +426,7 @@ impl<'__s> ToSchema<'__s> for AnnotatedSchema {
RawTextContentSchema, RawTextContentSchema,
RawImageContentSchema, RawImageContentSchema,
RawEmbeddedResourceSchema, RawEmbeddedResourceSchema,
RawResourceSchema,
AnnotatedSchema, AnnotatedSchema,
ToolResponse, ToolResponse,
ToolRequest, ToolRequest,
+2
View File
@@ -21,7 +21,9 @@ rmcp = { workspace = true, features = [
"reqwest", "reqwest",
"transport-child-process", "transport-child-process",
"transport-sse-client", "transport-sse-client",
"transport-sse-client-reqwest",
"transport-streamable-http-client", "transport-streamable-http-client",
"transport-streamable-http-client-reqwest",
] } ] }
anyhow = "1.0" anyhow = "1.0"
thiserror = "1.0" thiserror = "1.0"
@@ -1154,6 +1154,7 @@ mod tests {
content: vec![], content: vec![],
is_error: None, is_error: None,
structured_content: None, structured_content: None,
meta: None,
}), }),
_ => Err(Error::TransportClosed), _ => Err(Error::TransportClosed),
} }
@@ -255,6 +255,7 @@ mod tests {
vec![MessageContent::Text( vec![MessageContent::Text(
RawTextContent { RawTextContent {
text: "Summary of conversation".to_string(), text: "Summary of conversation".to_string(),
meta: None,
} }
.no_annotation(), .no_annotation(),
)], )],
@@ -101,6 +101,7 @@ mod tests {
vec![MessageContent::Text( vec![MessageContent::Text(
RawTextContent { RawTextContent {
text: "Summarized content".to_string(), text: "Summarized content".to_string(),
meta: None,
} }
.no_annotation(), .no_annotation(),
)], )],
+24 -3
View File
@@ -168,7 +168,13 @@ impl fmt::Display for MessageContent {
impl MessageContent { impl MessageContent {
pub fn text<S: Into<String>>(text: S) -> Self { pub fn text<S: Into<String>>(text: S) -> Self {
MessageContent::Text(RawTextContent { text: text.into() }.no_annotation()) MessageContent::Text(
RawTextContent {
text: text.into(),
meta: None,
}
.no_annotation(),
)
} }
pub fn image<S: Into<String>, T: Into<String>>(data: S, mime_type: T) -> Self { pub fn image<S: Into<String>, T: Into<String>>(data: S, mime_type: T) -> Self {
@@ -176,6 +182,7 @@ impl MessageContent {
RawImageContent { RawImageContent {
data: data.into(), data: data.into(),
mime_type: mime_type.into(), mime_type: mime_type.into(),
meta: None,
} }
.no_annotation(), .no_annotation(),
) )
@@ -317,6 +324,7 @@ impl From<Content> for MessageContent {
RawContent::Image(image) => { RawContent::Image(image) => {
MessageContent::Image(image.optional_annotate(content.annotations)) MessageContent::Image(image.optional_annotate(content.annotations))
} }
RawContent::ResourceLink(_link) => MessageContent::text("[Resource link]"),
RawContent::Resource(resource) => { RawContent::Resource(resource) => {
let text = match &resource.resource { let text = match &resource.resource {
ResourceContents::TextResourceContents { text, .. } => text.clone(), ResourceContents::TextResourceContents { text, .. } => text.clone(),
@@ -347,6 +355,7 @@ impl From<PromptMessage> for Message {
PromptMessageContent::Image { image } => { PromptMessageContent::Image { image } => {
MessageContent::image(image.data.clone(), image.mime_type.clone()) MessageContent::image(image.data.clone(), image.mime_type.clone())
} }
PromptMessageContent::ResourceLink { .. } => MessageContent::text("[Resource link]"),
PromptMessageContent::Resource { resource } => { PromptMessageContent::Resource { resource } => {
// For resources, convert to text content with the resource text // For resources, convert to text content with the resource text
match &resource.resource { match &resource.resource {
@@ -445,6 +454,7 @@ impl Message {
self.with_content(MessageContent::Text( self.with_content(MessageContent::Text(
RawTextContent { RawTextContent {
text: sanitized_text, text: sanitized_text,
meta: None,
} }
.no_annotation(), .no_annotation(),
)) ))
@@ -756,6 +766,7 @@ mod tests {
image: RawImageContent { image: RawImageContent {
data: "base64data".to_string(), data: "base64data".to_string(),
mime_type: "image/jpeg".to_string(), mime_type: "image/jpeg".to_string(),
meta: None,
} }
.no_annotation(), .no_annotation(),
}; };
@@ -781,10 +792,15 @@ mod tests {
uri: "file:///test.txt".to_string(), uri: "file:///test.txt".to_string(),
mime_type: Some("text/plain".to_string()), mime_type: Some("text/plain".to_string()),
text: "Resource content".to_string(), text: "Resource content".to_string(),
meta: None,
}; };
let prompt_content = PromptMessageContent::Resource { let prompt_content = PromptMessageContent::Resource {
resource: RawEmbeddedResource { resource }.no_annotation(), resource: RawEmbeddedResource {
resource,
meta: None,
}
.no_annotation(),
}; };
let prompt_message = PromptMessage { let prompt_message = PromptMessage {
@@ -807,10 +823,15 @@ mod tests {
uri: "file:///test.bin".to_string(), uri: "file:///test.bin".to_string(),
mime_type: Some("application/octet-stream".to_string()), mime_type: Some("application/octet-stream".to_string()),
blob: "binary_data".to_string(), blob: "binary_data".to_string(),
meta: None,
}; };
let prompt_content = PromptMessageContent::Resource { let prompt_content = PromptMessageContent::Resource {
resource: RawEmbeddedResource { resource }.no_annotation(), resource: RawEmbeddedResource {
resource,
meta: None,
}
.no_annotation(),
}; };
let prompt_message = PromptMessage { let prompt_message = PromptMessage {
+1
View File
@@ -221,6 +221,7 @@ mod tests {
"Response from {} with model {}", "Response from {} with model {}",
self.name, self.model_config.model_name self.name, self.model_config.model_name
), ),
meta: None,
} }
.no_annotation(), .no_annotation(),
)], )],
@@ -124,6 +124,9 @@ pub fn to_bedrock_tool_result_content_block(
RawContent::Image(image) => { RawContent::Image(image) => {
bedrock::ToolResultContentBlock::Image(to_bedrock_image(&image.data, &image.mime_type)?) bedrock::ToolResultContentBlock::Image(to_bedrock_image(&image.data, &image.mime_type)?)
} }
RawContent::ResourceLink(_link) => {
bedrock::ToolResultContentBlock::Text("[Resource link]".to_string())
}
RawContent::Resource(resource) => match &resource.resource { RawContent::Resource(resource) => match &resource.resource {
ResourceContents::TextResourceContents { text, .. } => { ResourceContents::TextResourceContents { text, .. } => {
match to_bedrock_document(tool_use_id, &resource.resource)? { match to_bedrock_document(tool_use_id, &resource.resource)? {
@@ -381,6 +384,7 @@ mod tests {
let image = RawImageContent { let image = RawImageContent {
data: TEST_IMAGE_BASE64.to_string(), data: TEST_IMAGE_BASE64.to_string(),
mime_type: mime_type.to_string(), mime_type: mime_type.to_string(),
meta: None,
} }
.no_annotation(); .no_annotation();
@@ -396,6 +400,7 @@ mod tests {
let image = RawImageContent { let image = RawImageContent {
data: TEST_IMAGE_BASE64.to_string(), data: TEST_IMAGE_BASE64.to_string(),
mime_type: "image/bmp".to_string(), mime_type: "image/bmp".to_string(),
meta: None,
} }
.no_annotation(); .no_annotation();
@@ -411,6 +416,7 @@ mod tests {
let image = RawImageContent { let image = RawImageContent {
data: "invalid_base64_data!!!".to_string(), data: "invalid_base64_data!!!".to_string(),
mime_type: "image/png".to_string(), mime_type: "image/png".to_string(),
meta: None,
} }
.no_annotation(); .no_annotation();
@@ -425,6 +431,7 @@ mod tests {
let image = RawImageContent { let image = RawImageContent {
data: TEST_IMAGE_BASE64.to_string(), data: TEST_IMAGE_BASE64.to_string(),
mime_type: "image/png".to_string(), mime_type: "image/png".to_string(),
meta: None,
} }
.no_annotation(); .no_annotation();
@@ -490,6 +490,7 @@ mod tests {
vec![MessageContent::Text( vec![MessageContent::Text(
RawTextContent { RawTextContent {
text: format!("Response from {}", self.name), text: format!("Response from {}", self.name),
meta: None,
} }
.no_annotation(), .no_annotation(),
)], )],
@@ -656,6 +657,7 @@ mod tests {
vec![MessageContent::Text( vec![MessageContent::Text(
RawTextContent { RawTextContent {
text: format!("Response from {}", self.name), text: format!("Response from {}", self.name),
meta: None,
} }
.no_annotation(), .no_annotation(),
)], )],
@@ -203,6 +203,7 @@ mod tests {
vec![MessageContent::Text(TextContent { vec![MessageContent::Text(TextContent {
raw: RawTextContent { raw: RawTextContent {
text: self.response.clone(), text: self.response.clone(),
meta: None,
}, },
annotations: None, annotations: None,
})], })],
+1
View File
@@ -374,6 +374,7 @@ pub fn load_image_file(path: &str) -> Result<ImageContent, ProviderError> {
Ok(RawImageContent { Ok(RawImageContent {
mime_type: mime_type.to_string(), mime_type: mime_type.to_string(),
data, data,
meta: None,
} }
.no_annotation()) .no_annotation())
} }
+1
View File
@@ -1406,6 +1406,7 @@ mod tests {
vec![MessageContent::Text( vec![MessageContent::Text(
RawTextContent { RawTextContent {
text: "Mocked scheduled response".to_string(), text: "Mocked scheduled response".to_string(),
meta: None,
} }
.no_annotation(), .no_annotation(),
)], )],
+1
View File
@@ -277,6 +277,7 @@ impl ProviderTester {
let image_content = RawImageContent { let image_content = RawImageContent {
data: base64_image, data: base64_image,
mime_type: "image/png".to_string(), mime_type: "image/png".to_string(),
meta: None,
} }
.no_annotation(); .no_annotation();
-2
View File
@@ -220,8 +220,6 @@ where
} }
JsonRpcMessage::Response(_) JsonRpcMessage::Response(_)
| JsonRpcMessage::Notification(_) | JsonRpcMessage::Notification(_)
| JsonRpcMessage::BatchRequest(_)
| JsonRpcMessage::BatchResponse(_)
| JsonRpcMessage::Error(_) => { | JsonRpcMessage::Error(_) => {
// Ignore responses, notifications, batch messages and error messages for now // Ignore responses, notifications, batch messages and error messages for now
continue; continue;
+1
View File
@@ -235,6 +235,7 @@ pub trait Router: Send + Sync + 'static {
uri: uri.to_string(), uri: uri.to_string(),
mime_type: Some("text/plain".to_string()), mime_type: Some("text/plain".to_string()),
text: contents, text: contents,
meta: None,
}], }],
}; };
+68 -4
View File
@@ -1559,12 +1559,12 @@
"$ref": "#/components/schemas/Role" "$ref": "#/components/schemas/Role"
} }
}, },
"priority": { "lastModified": {
"type": "number"
},
"timestamp": {
"type": "string", "type": "string",
"format": "date-time" "format": "date-time"
},
"priority": {
"type": "number"
} }
} }
}, },
@@ -1683,6 +1683,13 @@
"$ref": "#/components/schemas/Annotated" "$ref": "#/components/schemas/Annotated"
} }
] ]
},
{
"allOf": [
{
"$ref": "#/components/schemas/RawResource"
}
]
} }
] ]
}, },
@@ -1893,6 +1900,10 @@
"resource" "resource"
], ],
"properties": { "properties": {
"_meta": {
"type": "object",
"additionalProperties": true
},
"annotations": { "annotations": {
"anyOf": [ "anyOf": [
{ {
@@ -2390,6 +2401,10 @@
"mimeType" "mimeType"
], ],
"properties": { "properties": {
"_meta": {
"type": "object",
"additionalProperties": true
},
"annotations": { "annotations": {
"anyOf": [ "anyOf": [
{ {
@@ -2877,6 +2892,10 @@
"resource" "resource"
], ],
"properties": { "properties": {
"_meta": {
"type": "object",
"additionalProperties": true
},
"resource": { "resource": {
"$ref": "#/components/schemas/ResourceContents" "$ref": "#/components/schemas/ResourceContents"
} }
@@ -2889,6 +2908,10 @@
"mimeType" "mimeType"
], ],
"properties": { "properties": {
"_meta": {
"type": "object",
"additionalProperties": true
},
"data": { "data": {
"type": "string" "type": "string"
}, },
@@ -2897,12 +2920,41 @@
} }
} }
}, },
"RawResource": {
"type": "object",
"required": [
"uri",
"name"
],
"properties": {
"description": {
"type": "string"
},
"mimeType": {
"type": "string"
},
"name": {
"type": "string"
},
"size": {
"type": "integer",
"minimum": 0
},
"uri": {
"type": "string"
}
}
},
"RawTextContent": { "RawTextContent": {
"type": "object", "type": "object",
"required": [ "required": [
"text" "text"
], ],
"properties": { "properties": {
"_meta": {
"type": "object",
"additionalProperties": true
},
"text": { "text": {
"type": "string" "type": "string"
} }
@@ -3102,6 +3154,10 @@
"text" "text"
], ],
"properties": { "properties": {
"_meta": {
"type": "object",
"additionalProperties": true
},
"mimeType": { "mimeType": {
"type": "string" "type": "string"
}, },
@@ -3120,6 +3176,10 @@
"blob" "blob"
], ],
"properties": { "properties": {
"_meta": {
"type": "object",
"additionalProperties": true
},
"blob": { "blob": {
"type": "string" "type": "string"
}, },
@@ -3643,6 +3703,10 @@
"text" "text"
], ],
"properties": { "properties": {
"_meta": {
"type": "object",
"additionalProperties": true
},
"annotations": { "annotations": {
"anyOf": [ "anyOf": [
{ {
+1
View File
@@ -39,6 +39,7 @@
"start-alpha-gui": "ALPHA=true npm run start-gui" "start-alpha-gui": "ALPHA=true npm run start-gui"
}, },
"dependencies": { "dependencies": {
"@tanstack/react-form": "^0.13.0",
"@ai-sdk/openai": "^2.0.14", "@ai-sdk/openai": "^2.0.14",
"@ai-sdk/ui-utils": "^1.2.11", "@ai-sdk/ui-utils": "^1.2.11",
"@mcp-ui/client": "^5.9.0", "@mcp-ui/client": "^5.9.0",
+34 -2
View File
@@ -13,8 +13,8 @@ export type Annotated = RawTextContent | RawImageContent | RawEmbeddedResource;
export type Annotations = { export type Annotations = {
audience?: Array<Role>; audience?: Array<Role>;
lastModified?: string;
priority?: number; priority?: number;
timestamp?: string;
}; };
export type Author = { export type Author = {
@@ -65,7 +65,7 @@ export type ConfigResponse = {
}; };
}; };
export type Content = RawTextContent | RawImageContent | RawEmbeddedResource | Annotated; export type Content = RawTextContent | RawImageContent | RawEmbeddedResource | Annotated | RawResource;
export type ContextLengthExceeded = { export type ContextLengthExceeded = {
msg: string; msg: string;
@@ -141,6 +141,9 @@ export type DeleteRecipeRequest = {
}; };
export type EmbeddedResource = { export type EmbeddedResource = {
_meta?: {
[key: string]: unknown;
};
annotations?: Annotations | { annotations?: Annotations | {
[key: string]: unknown; [key: string]: unknown;
}; };
@@ -322,6 +325,9 @@ export type GetToolsQuery = {
}; };
export type ImageContent = { export type ImageContent = {
_meta?: {
[key: string]: unknown;
};
annotations?: Annotations | { annotations?: Annotations | {
[key: string]: unknown; [key: string]: unknown;
}; };
@@ -472,15 +478,32 @@ export type ProvidersResponse = {
}; };
export type RawEmbeddedResource = { export type RawEmbeddedResource = {
_meta?: {
[key: string]: unknown;
};
resource: ResourceContents; resource: ResourceContents;
}; };
export type RawImageContent = { export type RawImageContent = {
_meta?: {
[key: string]: unknown;
};
data: string; data: string;
mimeType: string; mimeType: string;
}; };
export type RawResource = {
description?: string;
mimeType?: string;
name: string;
size?: number;
uri: string;
};
export type RawTextContent = { export type RawTextContent = {
_meta?: {
[key: string]: unknown;
};
text: string; text: string;
}; };
@@ -580,10 +603,16 @@ export type RedactedThinkingContent = {
}; };
export type ResourceContents = { export type ResourceContents = {
_meta?: {
[key: string]: unknown;
};
mimeType?: string; mimeType?: string;
text: string; text: string;
uri: string; uri: string;
} | { } | {
_meta?: {
[key: string]: unknown;
};
blob: string; blob: string;
mimeType?: string; mimeType?: string;
uri: string; uri: string;
@@ -790,6 +819,9 @@ export type SummarizationRequested = {
}; };
export type TextContent = { export type TextContent = {
_meta?: {
[key: string]: unknown;
};
annotations?: Annotations | { annotations?: Annotations | {
[key: string]: unknown; [key: string]: unknown;
}; };