From 76da3a972455709049eed259ec2b3496433694d6 Mon Sep 17 00:00:00 2001 From: Alex Hancock Date: Fri, 18 Jul 2025 12:30:23 -0400 Subject: [PATCH] feat: switch from mcp_core::Role to rmcp::model::Role (#3488) --- Cargo.lock | 1 + .../core/computercontroller/script.rs | 2 +- .../core/computercontroller/web_scrape.rs | 2 +- .../eval_suites/core/developer/create_file.rs | 2 +- .../eval_suites/core/developer/list_files.rs | 2 +- .../core/developer/simple_repo_clone_test.rs | 2 +- .../eval_suites/core/developer_image/image.rs | 2 +- .../src/eval_suites/core/memory/save_fact.rs | 2 +- .../src/eval_suites/vibes/flappy_bird.rs | 2 +- .../src/eval_suites/vibes/goose_wiki.rs | 2 +- .../src/eval_suites/vibes/squirrel_census.rs | 2 +- crates/goose-cli/src/commands/session.rs | 6 ++-- crates/goose-cli/src/session/export.rs | 2 +- crates/goose-cli/src/session/mod.rs | 10 +++--- crates/goose-cli/src/session/output.rs | 2 +- crates/goose-mcp/src/developer/mod.rs | 2 +- crates/goose-server/src/openapi.rs | 31 +++++++++++++++++-- crates/goose/src/context_mgmt/summarize.rs | 5 +-- crates/goose/src/context_mgmt/truncate.rs | 3 +- crates/goose/src/message.rs | 2 +- .../goose/src/permission/permission_judge.rs | 5 +-- crates/goose/src/providers/claude_code.rs | 6 ++-- crates/goose/src/providers/factory.rs | 3 +- .../goose/src/providers/formats/anthropic.rs | 8 ++--- crates/goose/src/providers/formats/bedrock.rs | 3 +- .../goose/src/providers/formats/databricks.rs | 3 +- crates/goose/src/providers/formats/google.rs | 2 +- crates/goose/src/providers/formats/openai.rs | 3 +- .../goose/src/providers/formats/snowflake.rs | 2 +- crates/goose/src/providers/gemini_cli.rs | 2 +- crates/goose/src/providers/lead_worker.rs | 3 +- crates/goose/src/providers/sagemaker_tgi.rs | 2 +- crates/goose/src/providers/venice.rs | 3 +- crates/goose/src/scheduler.rs | 5 +-- crates/goose/src/session/storage.rs | 14 ++++----- crates/goose/src/token_counter.rs | 2 +- crates/goose/tests/agent.rs | 4 +-- crates/mcp-core/Cargo.toml | 1 + crates/mcp-core/src/content.rs | 2 +- crates/mcp-core/src/role.rs | 13 ++------ ui/desktop/openapi.json | 1 + ui/desktop/src/api/types.gen.ts | 3 ++ 42 files changed, 105 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e083444..2c1e2340 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5416,6 +5416,7 @@ dependencies = [ "async-trait", "base64 0.21.7", "chrono", + "rmcp", "schemars", "serde", "serde_json", diff --git a/crates/goose-bench/src/eval_suites/core/computercontroller/script.rs b/crates/goose-bench/src/eval_suites/core/computercontroller/script.rs index 4b92805f..b42243df 100644 --- a/crates/goose-bench/src/eval_suites/core/computercontroller/script.rs +++ b/crates/goose-bench/src/eval_suites/core/computercontroller/script.rs @@ -9,7 +9,7 @@ use crate::eval_suites::{ use crate::register_evaluation; use async_trait::async_trait; use goose::message::MessageContent; -use mcp_core::role::Role; +use rmcp::model::Role; use serde_json::{self, Value}; #[derive(Debug)] diff --git a/crates/goose-bench/src/eval_suites/core/computercontroller/web_scrape.rs b/crates/goose-bench/src/eval_suites/core/computercontroller/web_scrape.rs index 60b3c205..04fba60f 100644 --- a/crates/goose-bench/src/eval_suites/core/computercontroller/web_scrape.rs +++ b/crates/goose-bench/src/eval_suites/core/computercontroller/web_scrape.rs @@ -9,7 +9,7 @@ use crate::eval_suites::{ use crate::register_evaluation; use async_trait::async_trait; use goose::message::MessageContent; -use mcp_core::role::Role; +use rmcp::model::Role; use serde_json::{self, Value}; #[derive(Debug)] diff --git a/crates/goose-bench/src/eval_suites/core/developer/create_file.rs b/crates/goose-bench/src/eval_suites/core/developer/create_file.rs index 5cfe895d..154319c3 100644 --- a/crates/goose-bench/src/eval_suites/core/developer/create_file.rs +++ b/crates/goose-bench/src/eval_suites/core/developer/create_file.rs @@ -9,7 +9,7 @@ use crate::eval_suites::{ use crate::register_evaluation; use async_trait::async_trait; use goose::message::MessageContent; -use mcp_core::role::Role; +use rmcp::model::Role; use serde_json::{self, Value}; #[derive(Debug)] diff --git a/crates/goose-bench/src/eval_suites/core/developer/list_files.rs b/crates/goose-bench/src/eval_suites/core/developer/list_files.rs index 8881b690..8aea32cc 100644 --- a/crates/goose-bench/src/eval_suites/core/developer/list_files.rs +++ b/crates/goose-bench/src/eval_suites/core/developer/list_files.rs @@ -7,7 +7,7 @@ use crate::eval_suites::{ use crate::register_evaluation; use async_trait::async_trait; use goose::message::MessageContent; -use mcp_core::role::Role; +use rmcp::model::Role; use serde_json::{self, Value}; #[derive(Debug)] diff --git a/crates/goose-bench/src/eval_suites/core/developer/simple_repo_clone_test.rs b/crates/goose-bench/src/eval_suites/core/developer/simple_repo_clone_test.rs index dd280fbf..ffa8541e 100644 --- a/crates/goose-bench/src/eval_suites/core/developer/simple_repo_clone_test.rs +++ b/crates/goose-bench/src/eval_suites/core/developer/simple_repo_clone_test.rs @@ -7,7 +7,7 @@ use crate::eval_suites::{ use crate::register_evaluation; use async_trait::async_trait; use goose::message::MessageContent; -use mcp_core::role::Role; +use rmcp::model::Role; use serde_json::{self, Value}; #[derive(Debug)] diff --git a/crates/goose-bench/src/eval_suites/core/developer_image/image.rs b/crates/goose-bench/src/eval_suites/core/developer_image/image.rs index 34e43496..194605cc 100644 --- a/crates/goose-bench/src/eval_suites/core/developer_image/image.rs +++ b/crates/goose-bench/src/eval_suites/core/developer_image/image.rs @@ -8,7 +8,7 @@ use crate::register_evaluation; use async_trait::async_trait; use goose::message::MessageContent; use mcp_core::content::Content; -use mcp_core::role::Role; +use rmcp::model::Role; use serde_json::{self, Value}; #[derive(Debug)] diff --git a/crates/goose-bench/src/eval_suites/core/memory/save_fact.rs b/crates/goose-bench/src/eval_suites/core/memory/save_fact.rs index 91bebeea..4e3184e4 100644 --- a/crates/goose-bench/src/eval_suites/core/memory/save_fact.rs +++ b/crates/goose-bench/src/eval_suites/core/memory/save_fact.rs @@ -9,7 +9,7 @@ use crate::eval_suites::{ use crate::register_evaluation; use async_trait::async_trait; use goose::message::MessageContent; -use mcp_core::role::Role; +use rmcp::model::Role; use serde_json::{self, Value}; #[derive(Debug)] diff --git a/crates/goose-bench/src/eval_suites/vibes/flappy_bird.rs b/crates/goose-bench/src/eval_suites/vibes/flappy_bird.rs index 9cbca88a..edd2f4a5 100644 --- a/crates/goose-bench/src/eval_suites/vibes/flappy_bird.rs +++ b/crates/goose-bench/src/eval_suites/vibes/flappy_bird.rs @@ -7,7 +7,7 @@ use crate::eval_suites::{ use crate::register_evaluation; use async_trait::async_trait; use goose::message::MessageContent; -use mcp_core::role::Role; +use rmcp::model::Role; use serde_json::{self, Value}; use std::fs; diff --git a/crates/goose-bench/src/eval_suites/vibes/goose_wiki.rs b/crates/goose-bench/src/eval_suites/vibes/goose_wiki.rs index 480989e9..2609584c 100644 --- a/crates/goose-bench/src/eval_suites/vibes/goose_wiki.rs +++ b/crates/goose-bench/src/eval_suites/vibes/goose_wiki.rs @@ -7,7 +7,7 @@ use crate::eval_suites::{ use crate::register_evaluation; use async_trait::async_trait; use goose::message::MessageContent; -use mcp_core::role::Role; +use rmcp::model::Role; use serde_json::{self, Value}; use std::fs; diff --git a/crates/goose-bench/src/eval_suites/vibes/squirrel_census.rs b/crates/goose-bench/src/eval_suites/vibes/squirrel_census.rs index 84062b72..fd628a65 100644 --- a/crates/goose-bench/src/eval_suites/vibes/squirrel_census.rs +++ b/crates/goose-bench/src/eval_suites/vibes/squirrel_census.rs @@ -7,7 +7,7 @@ use crate::eval_suites::{ use crate::register_evaluation; use async_trait::async_trait; use goose::message::MessageContent; -use mcp_core::role::Role; +use rmcp::model::Role; use serde_json::{self, Value}; pub struct SquirrelCensus {} diff --git a/crates/goose-cli/src/commands/session.rs b/crates/goose-cli/src/commands/session.rs index ff8f37e4..20a0f3d2 100644 --- a/crates/goose-cli/src/commands/session.rs +++ b/crates/goose-cli/src/commands/session.rs @@ -241,7 +241,7 @@ fn export_session_to_markdown( for message in &messages { // Check if this is a User message containing only ToolResponses - let is_only_tool_response = message.role == mcp_core::role::Role::User + let is_only_tool_response = message.role == rmcp::model::Role::User && message .content .iter() @@ -263,8 +263,8 @@ fn export_session_to_markdown( // Output the role prefix except for tool response-only messages if !is_only_tool_response { let role_prefix = match message.role { - mcp_core::role::Role::User => "### User:\n", - mcp_core::role::Role::Assistant => "### Assistant:\n", + rmcp::model::Role::User => "### User:\n", + rmcp::model::Role::Assistant => "### Assistant:\n", }; markdown_output.push_str(role_prefix); } diff --git a/crates/goose-cli/src/session/export.rs b/crates/goose-cli/src/session/export.rs index 90d1c9a7..eb336bd4 100644 --- a/crates/goose-cli/src/session/export.rs +++ b/crates/goose-cli/src/session/export.rs @@ -2,7 +2,7 @@ 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 mcp_core::role::Role; +use rmcp::model::Role; use serde_json::Value; const MAX_STRING_LENGTH_MD_EXPORT: usize = 4096; // Generous limit for export diff --git a/crates/goose-cli/src/session/mod.rs b/crates/goose-cli/src/session/mod.rs index 5b51bd70..3fcc50e4 100644 --- a/crates/goose-cli/src/session/mod.rs +++ b/crates/goose-cli/src/session/mod.rs @@ -1187,7 +1187,7 @@ impl Session { let tool_requests = self .messages .last() - .filter(|msg| msg.role == mcp_core::role::Role::Assistant) + .filter(|msg| msg.role == rmcp::model::Role::Assistant) .map_or(Vec::new(), |msg| { msg.content .iter() @@ -1259,7 +1259,7 @@ impl Session { } else { // An interruption occurred outside of a tool request-response. if let Some(last_msg) = self.messages.last() { - if last_msg.role == mcp_core::role::Role::User { + if last_msg.role == rmcp::model::Role::User { match last_msg.content.first() { Some(MessageContent::ToolResponse(_)) => { // Interruption occurred after a tool had completed but not assistant reply @@ -1464,9 +1464,9 @@ impl Session { let msg = Message::from(prompt_message); // ensure we get a User - Assistant - User type pattern let expected_role = if i % 2 == 0 { - mcp_core::Role::User + rmcp::model::Role::User } else { - mcp_core::Role::Assistant + rmcp::model::Role::Assistant }; if msg.role != expected_role { @@ -1480,7 +1480,7 @@ impl Session { break; } - if msg.role == mcp_core::Role::User { + if msg.role == rmcp::model::Role::User { output::render_message(&msg, self.debug); } self.push_message(msg); diff --git a/crates/goose-cli/src/session/output.rs b/crates/goose-cli/src/session/output.rs index b3305821..d2c5f003 100644 --- a/crates/goose-cli/src/session/output.rs +++ b/crates/goose-cli/src/session/output.rs @@ -232,7 +232,7 @@ fn render_tool_response(resp: &ToolResponse, theme: Theme, debug: bool) { Ok(contents) => { for content in contents { if let Some(audience) = content.audience() { - if !audience.contains(&mcp_core::role::Role::User) { + if !audience.contains(&rmcp::model::Role::User) { continue; } } diff --git a/crates/goose-mcp/src/developer/mod.rs b/crates/goose-mcp/src/developer/mod.rs index ddc81831..b7851f02 100644 --- a/crates/goose-mcp/src/developer/mod.rs +++ b/crates/goose-mcp/src/developer/mod.rs @@ -36,7 +36,7 @@ use mcp_core::{ use mcp_server::router::CapabilitiesBuilder; use mcp_server::Router; -use mcp_core::role::Role; +use rmcp::model::Role; use self::editor_models::{create_editor_model, EditorModel}; use self::shell::{expand_path, get_shell_config, is_absolute_path, normalize_line_endings}; diff --git a/crates/goose-server/src/openapi.rs b/crates/goose-server/src/openapi.rs index ae77398f..ceb210fd 100644 --- a/crates/goose-server/src/openapi.rs +++ b/crates/goose-server/src/openapi.rs @@ -14,9 +14,36 @@ use goose::session::SessionMetadata; use mcp_core::content::{Annotations, Content, EmbeddedResource, ImageContent, TextContent}; use mcp_core::handler::ToolResultSchema; use mcp_core::resource::ResourceContents; -use mcp_core::role::Role; use mcp_core::tool::{Tool, ToolAnnotations}; -use utoipa::OpenApi; +use utoipa::{OpenApi, ToSchema}; + +/// A wrapper around rmcp::model::Role that implements ToSchema for utoipa +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)] +#[serde(rename_all = "camelCase")] +pub enum Role { + /// A human user or client making a request + User, + /// An AI assistant or server providing a response + Assistant, +} + +impl From for Role { + fn from(role: rmcp::model::Role) -> Self { + match role { + rmcp::model::Role::User => Role::User, + rmcp::model::Role::Assistant => Role::Assistant, + } + } +} + +impl From for rmcp::model::Role { + fn from(role: Role) -> Self { + match role { + Role::User => rmcp::model::Role::User, + Role::Assistant => rmcp::model::Role::Assistant, + } + } +} #[allow(dead_code)] // Used by utoipa for OpenAPI generation #[derive(OpenApi)] diff --git a/crates/goose/src/context_mgmt/summarize.rs b/crates/goose/src/context_mgmt/summarize.rs index 84ea104b..17c8478a 100644 --- a/crates/goose/src/context_mgmt/summarize.rs +++ b/crates/goose/src/context_mgmt/summarize.rs @@ -3,7 +3,7 @@ use crate::message::{Message, MessageContent}; use crate::providers::base::Provider; use crate::token_counter::{AsyncTokenCounter, TokenCounter}; use anyhow::Result; -use mcp_core::Role; +use rmcp::model::Role; use std::sync::Arc; // Constants for the summarization prompt and a follow-up user message. @@ -220,8 +220,9 @@ mod tests { use crate::providers::base::{Provider, ProviderMetadata, ProviderUsage, Usage}; use crate::providers::errors::ProviderError; use chrono::Utc; - use mcp_core::{tool::Tool, Role}; + use mcp_core::tool::Tool; use mcp_core::{Content, TextContent, ToolCall}; + use rmcp::model::Role; use serde_json::json; use std::sync::Arc; diff --git a/crates/goose/src/context_mgmt/truncate.rs b/crates/goose/src/context_mgmt/truncate.rs index 2bc49f92..e0e9d0bd 100644 --- a/crates/goose/src/context_mgmt/truncate.rs +++ b/crates/goose/src/context_mgmt/truncate.rs @@ -1,7 +1,8 @@ use crate::message::{Message, MessageContent}; use crate::utils::safe_truncate; use anyhow::{anyhow, Result}; -use mcp_core::{Content, ResourceContents, Role}; +use mcp_core::{Content, ResourceContents}; +use rmcp::model::Role; use std::collections::HashSet; use tracing::{debug, warn}; diff --git a/crates/goose/src/message.rs b/crates/goose/src/message.rs index ef207eb1..3ff05420 100644 --- a/crates/goose/src/message.rs +++ b/crates/goose/src/message.rs @@ -12,8 +12,8 @@ use mcp_core::content::{Content, ImageContent, TextContent}; use mcp_core::handler::ToolResult; use mcp_core::prompt::{PromptMessage, PromptMessageContent, PromptMessageRole}; use mcp_core::resource::ResourceContents; -use mcp_core::role::Role; use mcp_core::tool::ToolCall; +use rmcp::model::Role; use serde::{Deserialize, Serialize}; use serde_json::Value; use utoipa::ToSchema; diff --git a/crates/goose/src/permission/permission_judge.rs b/crates/goose/src/permission/permission_judge.rs index b8b5110e..40363f02 100644 --- a/crates/goose/src/permission/permission_judge.rs +++ b/crates/goose/src/permission/permission_judge.rs @@ -82,7 +82,7 @@ fn create_check_messages(tool_requests: Vec<&ToolRequest>) -> Vec { .collect(); let mut check_messages = vec![]; check_messages.push(Message::new( - mcp_core::Role::User, + rmcp::model::Role::User, Utc::now().timestamp(), vec![MessageContent::Text(TextContent { text: format!( @@ -270,7 +270,8 @@ mod tests { use crate::providers::errors::ProviderError; use chrono::Utc; use mcp_core::ToolCall; - use mcp_core::{tool::Tool, Role, ToolResult}; + use mcp_core::{tool::Tool, ToolResult}; + use rmcp::model::Role; use serde_json::json; use tempfile::NamedTempFile; diff --git a/crates/goose/src/providers/claude_code.rs b/crates/goose/src/providers/claude_code.rs index 0ee20336..e210c1b3 100644 --- a/crates/goose/src/providers/claude_code.rs +++ b/crates/goose/src/providers/claude_code.rs @@ -12,7 +12,7 @@ use crate::message::{Message, MessageContent}; use crate::model::ModelConfig; use mcp_core::content::TextContent; use mcp_core::tool::Tool; -use mcp_core::Role; +use rmcp::model::Role; pub const CLAUDE_CODE_DEFAULT_MODEL: &str = "default"; pub const CLAUDE_CODE_KNOWN_MODELS: &[&str] = &["default"]; @@ -330,7 +330,7 @@ impl ClaudeCodeProvider { // Extract the first user message text let description = messages .iter() - .find(|m| m.role == mcp_core::Role::User) + .find(|m| m.role == rmcp::model::Role::User) .and_then(|m| { m.content.iter().find_map(|c| match c { MessageContent::Text(text_content) => Some(&text_content.text), @@ -354,7 +354,7 @@ impl ClaudeCodeProvider { } let message = Message::new( - mcp_core::Role::Assistant, + rmcp::model::Role::Assistant, chrono::Utc::now().timestamp(), vec![MessageContent::Text(mcp_core::content::TextContent { text: description.clone(), diff --git a/crates/goose/src/providers/factory.rs b/crates/goose/src/providers/factory.rs index e627505b..e177c06b 100644 --- a/crates/goose/src/providers/factory.rs +++ b/crates/goose/src/providers/factory.rs @@ -177,7 +177,8 @@ mod tests { use crate::message::{Message, MessageContent}; use crate::providers::base::{ProviderMetadata, ProviderUsage, Usage}; use chrono::Utc; - use mcp_core::{content::TextContent, Role}; + use mcp_core::content::TextContent; + use rmcp::model::Role; use std::env; #[allow(dead_code)] diff --git a/crates/goose/src/providers/formats/anthropic.rs b/crates/goose/src/providers/formats/anthropic.rs index c4656058..e7907cf0 100644 --- a/crates/goose/src/providers/formats/anthropic.rs +++ b/crates/goose/src/providers/formats/anthropic.rs @@ -4,8 +4,8 @@ use crate::providers::base::Usage; use crate::providers::errors::ProviderError; use anyhow::{anyhow, Result}; use mcp_core::content::Content; -use mcp_core::role::Role; use mcp_core::tool::{Tool, ToolCall}; +use rmcp::model::Role; use serde_json::{json, Value}; use std::collections::HashSet; @@ -538,7 +538,7 @@ where // Yield partial text message let message = Message::new( - mcp_core::role::Role::Assistant, + Role::Assistant, chrono::Utc::now().timestamp(), vec![MessageContent::text(text)], ); @@ -573,7 +573,7 @@ where format!("Could not parse tool arguments: {}", args) ); let message = Message::new( - mcp_core::role::Role::Assistant, + Role::Assistant, chrono::Utc::now().timestamp(), vec![MessageContent::tool_request(tool_id, Err(error))], ); @@ -585,7 +585,7 @@ where let tool_call = ToolCall::new(&name, parsed_args); let message = Message::new( - mcp_core::role::Role::Assistant, + rmcp::model::Role::Assistant, chrono::Utc::now().timestamp(), vec![MessageContent::tool_request(tool_id, Ok(tool_call))], ); diff --git a/crates/goose/src/providers/formats/bedrock.rs b/crates/goose/src/providers/formats/bedrock.rs index 9a1651b5..4b8ba9f4 100644 --- a/crates/goose/src/providers/formats/bedrock.rs +++ b/crates/goose/src/providers/formats/bedrock.rs @@ -6,7 +6,8 @@ use aws_sdk_bedrockruntime::types as bedrock; use aws_smithy_types::{Document, Number}; use base64::Engine; use chrono::Utc; -use mcp_core::{Content, ResourceContents, Role, Tool, ToolCall, ToolError, ToolResult}; +use mcp_core::{Content, ResourceContents, Tool, ToolCall, ToolError, ToolResult}; +use rmcp::model::Role; use serde_json::Value; use super::super::base::Usage; diff --git a/crates/goose/src/providers/formats/databricks.rs b/crates/goose/src/providers/formats/databricks.rs index e47bd3e8..89cae498 100644 --- a/crates/goose/src/providers/formats/databricks.rs +++ b/crates/goose/src/providers/formats/databricks.rs @@ -6,7 +6,8 @@ use crate::providers::utils::{ }; use anyhow::{anyhow, Error}; use mcp_core::ToolError; -use mcp_core::{Content, Role, Tool, ToolCall}; +use mcp_core::{Content, Tool, ToolCall}; +use rmcp::model::Role; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; diff --git a/crates/goose/src/providers/formats/google.rs b/crates/goose/src/providers/formats/google.rs index 6c801d50..46806d3c 100644 --- a/crates/goose/src/providers/formats/google.rs +++ b/crates/goose/src/providers/formats/google.rs @@ -5,9 +5,9 @@ use crate::providers::errors::ProviderError; use crate::providers::utils::{is_valid_function_name, sanitize_function_name}; use anyhow::Result; use mcp_core::content::Content; -use mcp_core::role::Role; use mcp_core::tool::{Tool, ToolCall}; use rand::{distributions::Alphanumeric, Rng}; +use rmcp::model::Role; use serde_json::{json, Map, Value}; /// Convert internal Message format to Google's API message specification diff --git a/crates/goose/src/providers/formats/openai.rs b/crates/goose/src/providers/formats/openai.rs index 7660afe1..68db8be9 100644 --- a/crates/goose/src/providers/formats/openai.rs +++ b/crates/goose/src/providers/formats/openai.rs @@ -9,7 +9,8 @@ use anyhow::{anyhow, Error}; use async_stream::try_stream; use futures::Stream; use mcp_core::ToolError; -use mcp_core::{Content, Role, Tool, ToolCall}; +use mcp_core::{Content, Tool, ToolCall}; +use rmcp::model::Role; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; diff --git a/crates/goose/src/providers/formats/snowflake.rs b/crates/goose/src/providers/formats/snowflake.rs index c7cfe592..9e7fb6d1 100644 --- a/crates/goose/src/providers/formats/snowflake.rs +++ b/crates/goose/src/providers/formats/snowflake.rs @@ -4,8 +4,8 @@ use crate::providers::base::Usage; use crate::providers::errors::ProviderError; use anyhow::{anyhow, Result}; use mcp_core::content::Content; -use mcp_core::role::Role; use mcp_core::tool::{Tool, ToolCall}; +use rmcp::model::Role; use serde_json::{json, Value}; use std::collections::HashSet; diff --git a/crates/goose/src/providers/gemini_cli.rs b/crates/goose/src/providers/gemini_cli.rs index fc696bab..9eb1bce9 100644 --- a/crates/goose/src/providers/gemini_cli.rs +++ b/crates/goose/src/providers/gemini_cli.rs @@ -12,7 +12,7 @@ use crate::message::{Message, MessageContent}; use crate::model::ModelConfig; use mcp_core::content::TextContent; use mcp_core::tool::Tool; -use mcp_core::Role; +use rmcp::model::Role; pub const GEMINI_CLI_DEFAULT_MODEL: &str = "default"; pub const GEMINI_CLI_KNOWN_MODELS: &[&str] = &["default"]; diff --git a/crates/goose/src/providers/lead_worker.rs b/crates/goose/src/providers/lead_worker.rs index ea892342..ef33694b 100644 --- a/crates/goose/src/providers/lead_worker.rs +++ b/crates/goose/src/providers/lead_worker.rs @@ -455,7 +455,8 @@ mod tests { use crate::message::MessageContent; use crate::providers::base::{ProviderMetadata, ProviderUsage, Usage}; use chrono::Utc; - use mcp_core::{content::TextContent, Role}; + use mcp_core::content::TextContent; + use rmcp::model::Role; #[derive(Clone)] struct MockProvider { diff --git a/crates/goose/src/providers/sagemaker_tgi.rs b/crates/goose/src/providers/sagemaker_tgi.rs index c2ced2a5..2ee13e8b 100644 --- a/crates/goose/src/providers/sagemaker_tgi.rs +++ b/crates/goose/src/providers/sagemaker_tgi.rs @@ -17,7 +17,7 @@ use crate::message::{Message, MessageContent}; use crate::model::ModelConfig; use chrono::Utc; use mcp_core::content::TextContent; -use mcp_core::role::Role; +use rmcp::model::Role; pub const SAGEMAKER_TGI_DOC_LINK: &str = "https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints.html"; diff --git a/crates/goose/src/providers/venice.rs b/crates/goose/src/providers/venice.rs index 9046cdd5..5d1eab5e 100644 --- a/crates/goose/src/providers/venice.rs +++ b/crates/goose/src/providers/venice.rs @@ -10,7 +10,8 @@ use super::base::{ConfigKey, Provider, ProviderMetadata, ProviderUsage, Usage}; use super::errors::ProviderError; use crate::message::{Message, MessageContent}; use crate::model::ModelConfig; -use mcp_core::{tool::Tool, Role, ToolCall, ToolResult}; +use mcp_core::{tool::Tool, ToolCall, ToolResult}; +use rmcp::model::Role; // ---------- Capability Flags ---------- #[derive(Debug)] diff --git a/crates/goose/src/scheduler.rs b/crates/goose/src/scheduler.rs index bd1aee12..584a6815 100644 --- a/crates/goose/src/scheduler.rs +++ b/crates/goose/src/scheduler.rs @@ -1219,7 +1219,7 @@ async fn run_scheduled_job_internal( match message_result { Ok(AgentEvent::Message(msg)) => { - if msg.role == mcp_core::role::Role::Assistant { + if msg.role == rmcp::model::Role::Assistant { tracing::info!("[Job {}] Assistant: {:?}", job.id, msg.content); } all_session_messages.push(msg); @@ -1331,7 +1331,8 @@ mod tests { providers::base::{ProviderMetadata, ProviderUsage, Usage}, providers::errors::ProviderError, }; - use mcp_core::{content::TextContent, tool::Tool, Role}; + use mcp_core::{content::TextContent, tool::Tool}; + use rmcp::model::Role; // Removed: use crate::session::storage::{get_most_recent_session, read_metadata}; // `read_metadata` is still used by the test itself, so keep it or its module. use crate::session::storage::read_metadata; diff --git a/crates/goose/src/session/storage.rs b/crates/goose/src/session/storage.rs index 81fd0ff1..ceaa45c6 100644 --- a/crates/goose/src/session/storage.rs +++ b/crates/goose/src/session/storage.rs @@ -862,11 +862,11 @@ fn try_extract_partial_message(json_str: &str) -> Result { // Try to extract role let role = if json_str.contains("\"role\":\"user\"") { - mcp_core::role::Role::User + rmcp::model::Role::User } else if json_str.contains("\"role\":\"assistant\"") { - mcp_core::role::Role::Assistant + rmcp::model::Role::Assistant } else { - mcp_core::role::Role::User // Default fallback + rmcp::model::Role::User // Default fallback }; // Try to extract text content @@ -901,8 +901,8 @@ fn try_extract_partial_message(json_str: &str) -> Result { if !extracted_text.is_empty() { let message = match role { - mcp_core::role::Role::User => Message::user(), - mcp_core::role::Role::Assistant => Message::assistant(), + rmcp::model::Role::User => Message::user(), + rmcp::model::Role::Assistant => Message::assistant(), }; return Ok(message.with_text(format!("[PARTIALLY RECOVERED] {}", extracted_text))); @@ -1079,7 +1079,7 @@ pub async fn persist_messages_with_schedule_id( // Count user messages let user_message_count = messages .iter() - .filter(|m| m.role == mcp_core::role::Role::User && !m.as_concat_text().trim().is_empty()) + .filter(|m| m.role == rmcp::model::Role::User && !m.as_concat_text().trim().is_empty()) .count(); // Check if we need to update the description (after 1st or 3rd user message) @@ -1293,7 +1293,7 @@ pub async fn generate_description_with_schedule_id( // get context from messages so far, limiting each message to 300 chars for security let context: Vec = messages .iter() - .filter(|m| m.role == mcp_core::role::Role::User) + .filter(|m| m.role == rmcp::model::Role::User) .take(3) // Use up to first 3 user messages for context .map(|m| { let text = m.as_concat_text(); diff --git a/crates/goose/src/token_counter.rs b/crates/goose/src/token_counter.rs index 6db01dd3..6f519beb 100644 --- a/crates/goose/src/token_counter.rs +++ b/crates/goose/src/token_counter.rs @@ -371,8 +371,8 @@ pub async fn create_async_token_counter() -> Result { mod tests { use super::*; use crate::message::{Message, MessageContent}; - use mcp_core::role::Role; use mcp_core::tool::Tool; + use rmcp::model::Role; use serde_json::json; #[test] diff --git a/crates/goose/tests/agent.rs b/crates/goose/tests/agent.rs index 837a433c..7b951be2 100644 --- a/crates/goose/tests/agent.rs +++ b/crates/goose/tests/agent.rs @@ -635,7 +635,7 @@ mod final_output_tool_tests { let last_message = responses.last().unwrap(); // Check that the last message is an assistant message with our final output - assert_eq!(last_message.role, mcp_core::role::Role::Assistant); + assert_eq!(last_message.role, rmcp::model::Role::Assistant); let message_text = last_message.as_concat_text(); assert_eq!(message_text, r#"{"result":"Test output"}"#); @@ -753,7 +753,7 @@ mod final_output_tool_tests { } // Check that the last message after the llm stream is the message directing the agent to continue - assert_eq!(last_message.role, mcp_core::role::Role::User); + assert_eq!(last_message.role, rmcp::model::Role::User); let message_text = last_message.as_concat_text(); assert_eq!(message_text, FINAL_OUTPUT_CONTINUATION_MESSAGE); diff --git a/crates/mcp-core/Cargo.toml b/crates/mcp-core/Cargo.toml index 4f470798..893e63f5 100644 --- a/crates/mcp-core/Cargo.toml +++ b/crates/mcp-core/Cargo.toml @@ -8,6 +8,7 @@ workspace = true [dependencies] async-trait = "0.1" +rmcp = { workspace = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" diff --git a/crates/mcp-core/src/content.rs b/crates/mcp-core/src/content.rs index 91ede3d8..da728ac1 100644 --- a/crates/mcp-core/src/content.rs +++ b/crates/mcp-core/src/content.rs @@ -1,7 +1,7 @@ /// Content sent around agents, extensions, and LLMs /// The various content types can be display to humans but also understood by models /// They include optional annotations used to help inform agent usage -use super::role::Role; +use super::Role; use crate::resource::ResourceContents; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; diff --git a/crates/mcp-core/src/role.rs b/crates/mcp-core/src/role.rs index e15740d1..2d753e90 100644 --- a/crates/mcp-core/src/role.rs +++ b/crates/mcp-core/src/role.rs @@ -1,10 +1,3 @@ -/// Roles to describe the origin/ownership of content -use serde::{Deserialize, Serialize}; -use utoipa::ToSchema; - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)] -#[serde(rename_all = "lowercase")] -pub enum Role { - User, - Assistant, -} +// passthrough, which will be deleted with the rest of the mcp-core crate after it is no longer used +// needed because it has internal references in this crate which leak out to usages used in goose etc crates +pub use rmcp::model::Role; diff --git a/ui/desktop/openapi.json b/ui/desktop/openapi.json index 98be026b..59a29554 100644 --- a/ui/desktop/openapi.json +++ b/ui/desktop/openapi.json @@ -1998,6 +1998,7 @@ }, "Role": { "type": "string", + "description": "A wrapper around rmcp::model::Role that implements ToSchema for utoipa", "enum": [ "user", "assistant" diff --git a/ui/desktop/src/api/types.gen.ts b/ui/desktop/src/api/types.gen.ts index b29694e7..9238f246 100644 --- a/ui/desktop/src/api/types.gen.ts +++ b/ui/desktop/src/api/types.gen.ts @@ -338,6 +338,9 @@ export type ResourceContents = { uri: string; }; +/** + * A wrapper around rmcp::model::Role that implements ToSchema for utoipa + */ export type Role = 'user' | 'assistant'; export type RunNowResponse = {