Replace mcp_core::content types with rmcp::model types (#3500)

This commit is contained in:
Jack Amadeo
2025-07-18 17:23:25 -04:00
committed by GitHub
parent a2309d9436
commit d5291461ca
66 changed files with 867 additions and 856 deletions
+65 -36
View File
@@ -1,8 +1,6 @@
use goose::message::{Message, MessageContent, ToolRequest, ToolResponse};
use goose::utils::safe_truncate;
use mcp_core::content::Content as McpContent;
use mcp_core::resource::ResourceContents;
use rmcp::model::Role;
use rmcp::model::{RawContent, ResourceContents, Role};
use serde_json::Value;
const MAX_STRING_LENGTH_MD_EXPORT: usize = 4096; // Generous limit for export
@@ -219,8 +217,8 @@ pub fn tool_response_to_markdown(resp: &ToolResponse, export_all_content: bool)
}
}
match content {
McpContent::Text(text_content) => {
match &content.raw {
RawContent::Text(text_content) => {
let trimmed_text = text_content.text.trim();
if (trimmed_text.starts_with('{') && trimmed_text.ends_with('}'))
|| (trimmed_text.starts_with('[') && trimmed_text.ends_with(']'))
@@ -236,7 +234,7 @@ pub fn tool_response_to_markdown(resp: &ToolResponse, export_all_content: bool)
md.push_str("\n\n");
}
}
McpContent::Image(image_content) => {
RawContent::Image(image_content) => {
if image_content.mime_type.starts_with("image/") {
// For actual images, provide a placeholder that indicates it's an image
md.push_str(&format!(
@@ -252,7 +250,7 @@ pub fn tool_response_to_markdown(resp: &ToolResponse, export_all_content: bool)
));
}
}
McpContent::Resource(resource) => {
RawContent::Resource(resource) => {
match &resource.resource {
ResourceContents::TextResourceContents {
uri,
@@ -299,6 +297,9 @@ pub fn tool_response_to_markdown(resp: &ToolResponse, export_all_content: bool)
}
}
}
RawContent::Audio(_) => {
md.push_str("[audio content not displayed in Markdown export]\n\n")
}
}
}
}
@@ -360,8 +361,8 @@ pub fn message_to_markdown(message: &Message, export_all_content: bool) -> Strin
mod tests {
use super::*;
use goose::message::{Message, ToolRequest, ToolResponse};
use mcp_core::content::{Content as McpContent, TextContent};
use mcp_core::tool::ToolCall;
use rmcp::model::{Content, RawTextContent, TextContent};
use serde_json::json;
#[test]
@@ -521,12 +522,14 @@ mod tests {
#[test]
fn test_tool_response_to_markdown_text() {
let text_content = TextContent {
text: "Command executed successfully".to_string(),
raw: RawTextContent {
text: "Command executed successfully".to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "test-id".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let result = tool_response_to_markdown(&tool_response, true);
@@ -538,12 +541,14 @@ mod tests {
fn test_tool_response_to_markdown_json() {
let json_text = r#"{"status": "success", "data": "test"}"#;
let text_content = TextContent {
text: json_text.to_string(),
raw: RawTextContent {
text: json_text.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "test-id".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let result = tool_response_to_markdown(&tool_response, true);
@@ -640,12 +645,14 @@ if __name__ == "__main__":
hello_world()"#;
let text_content = TextContent {
text: python_code.to_string(),
raw: RawTextContent {
text: python_code.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "shell-cat".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let request_result = tool_request_to_markdown(&tool_request, true);
@@ -677,12 +684,14 @@ if __name__ == "__main__":
let git_output = " M src/main.rs\n?? temp.txt\n A new_feature.rs";
let text_content = TextContent {
text: git_output.to_string(),
raw: RawTextContent {
text: git_output.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "git-status".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let request_result = tool_request_to_markdown(&tool_request, true);
@@ -722,12 +731,14 @@ warning: unused variable `x`
Finished dev [unoptimized + debuginfo] target(s) in 2.45s"#;
let text_content = TextContent {
text: build_output.to_string(),
raw: RawTextContent {
text: build_output.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "cargo-build".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let response_result = tool_response_to_markdown(&tool_response, true);
@@ -765,12 +776,14 @@ warning: unused variable `x`
}"#;
let text_content = TextContent {
text: api_response.to_string(),
raw: RawTextContent {
text: api_response.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "curl-api".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let response_result = tool_response_to_markdown(&tool_response, true);
@@ -797,12 +810,14 @@ warning: unused variable `x`
};
let text_content = TextContent {
text: "File created successfully".to_string(),
raw: RawTextContent {
text: "File created successfully".to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "editor-write".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let request_result = tool_request_to_markdown(&tool_request, true);
@@ -850,12 +865,14 @@ def process_data(data: List[Dict]) -> List[Dict]:
return [item for item in data if item.get('active', False)]"#;
let text_content = TextContent {
text: python_code.to_string(),
raw: RawTextContent {
text: python_code.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "editor-view".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let response_result = tool_response_to_markdown(&tool_response, true);
@@ -883,12 +900,14 @@ def process_data(data: List[Dict]) -> List[Dict]:
Command failed with exit code 2"#;
let text_content = TextContent {
text: error_output.to_string(),
raw: RawTextContent {
text: error_output.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "shell-error".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let response_result = tool_response_to_markdown(&tool_response, true);
@@ -919,12 +938,14 @@ Command failed with exit code 2"#;
5^2 = 25"#;
let text_content = TextContent {
text: script_output.to_string(),
raw: RawTextContent {
text: script_output.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "script-exec".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let request_result = tool_request_to_markdown(&tool_request, true);
@@ -962,12 +983,14 @@ drwx------ 3 user staff 96 Dec 6 16:20 com.apple.launchd.abc
/tmp"#;
let text_content = TextContent {
text: multi_output.to_string(),
raw: RawTextContent {
text: multi_output.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "multi-cmd".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let request_result = tool_request_to_markdown(&_tool_request, true);
@@ -1001,12 +1024,14 @@ src/database.rs:23:async fn query_users(pool: &Pool) -> Result<Vec<User>> {
src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Result<Response> {"#;
let text_content = TextContent {
text: grep_output.to_string(),
raw: RawTextContent {
text: grep_output.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "grep-search".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let request_result = tool_request_to_markdown(&tool_request, true);
@@ -1037,12 +1062,14 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
let json_output = r#"{"status": "success", "data": {"count": 42}}"#;
let text_content = TextContent {
text: json_output.to_string(),
raw: RawTextContent {
text: json_output.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "json-test".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let response_result = tool_response_to_markdown(&tool_response, true);
@@ -1074,12 +1101,14 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
found 0 vulnerabilities"#;
let text_content = TextContent {
text: npm_output.to_string(),
raw: RawTextContent {
text: npm_output.to_string(),
},
annotations: None,
};
let tool_response = ToolResponse {
id: "npm-install".to_string(),
tool_result: Ok(vec![McpContent::Text(text_content)]),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
};
let request_result = tool_request_to_markdown(&tool_request, true);
+28 -2
View File
@@ -35,9 +35,9 @@ use goose::providers::pricing::initialize_pricing_cache;
use goose::session;
use input::InputResult;
use mcp_core::handler::ToolError;
use mcp_core::prompt::PromptMessage;
use mcp_core::protocol::JsonRpcMessage;
use mcp_core::protocol::JsonRpcNotification;
use rmcp::model::PromptMessage;
use rand::{distributions::Alphanumeric, Rng};
use rustyline::EditMode;
@@ -359,7 +359,33 @@ impl Session {
pub async fn get_prompt(&mut self, name: &str, arguments: Value) -> Result<Vec<PromptMessage>> {
let result = self.agent.get_prompt(name, arguments).await?;
Ok(result.messages)
// Convert mcp_core::prompt::PromptMessage to rmcp::model::PromptMessage
let converted_messages = result
.messages
.into_iter()
.map(|msg| rmcp::model::PromptMessage {
role: match msg.role {
mcp_core::prompt::PromptMessageRole::User => {
rmcp::model::PromptMessageRole::User
}
mcp_core::prompt::PromptMessageRole::Assistant => {
rmcp::model::PromptMessageRole::Assistant
}
},
content: match msg.content {
mcp_core::prompt::PromptMessageContent::Text { text } => {
rmcp::model::PromptMessageContent::Text { text }
}
mcp_core::prompt::PromptMessageContent::Image { image } => {
rmcp::model::PromptMessageContent::Image { image }
}
mcp_core::prompt::PromptMessageContent::Resource { resource } => {
rmcp::model::PromptMessageContent::Resource { resource }
}
},
})
.collect();
Ok(converted_messages)
}
/// Process a single message and get the response
+1 -1
View File
@@ -252,7 +252,7 @@ fn render_tool_response(resp: &ToolResponse, theme: Theme, debug: bool) {
if debug {
println!("{:#?}", content);
} else if let mcp_core::content::Content::Text(text) = content {
} else if let Some(text) = content.as_text() {
print_markdown(&text.text, theme);
}
}