add minimal mistral support
This commit is contained in:
@@ -5,3 +5,4 @@ server.toml
|
||||
temporary_audio
|
||||
cli/src/human_interface/.AUTH_HEADER
|
||||
.idea
|
||||
/own_mcp/src/mcp/llmclient/mistral/.MISTRAL_API_KEY
|
||||
|
||||
Generated
+71
-25
@@ -1551,7 +1551,7 @@ dependencies = [
|
||||
"icalendar",
|
||||
"libdav",
|
||||
"own_assist_common 0.3.0",
|
||||
"rmcp",
|
||||
"rmcp 2.2.0",
|
||||
"serde",
|
||||
"thiserror 2.0.19",
|
||||
"tokio",
|
||||
@@ -1577,7 +1577,7 @@ dependencies = [
|
||||
"icalendar",
|
||||
"libdav",
|
||||
"own_assist_common 0.3.0",
|
||||
"rmcp",
|
||||
"rmcp 2.2.0",
|
||||
"serde",
|
||||
"thiserror 2.0.19",
|
||||
"tokio",
|
||||
@@ -1999,8 +1999,8 @@ dependencies = [
|
||||
"mcp_server_collection 0.2.2 (sparse+https://git.mboemer.de/api/packages/milan/cargo/)",
|
||||
"ollama-rs",
|
||||
"own_assist_common 0.4.1",
|
||||
"own_mcp 0.1.1 (sparse+https://git.mboemer.de/api/packages/milan/cargo/)",
|
||||
"rmcp",
|
||||
"own_mcp 0.1.1",
|
||||
"rmcp 2.2.0",
|
||||
"rodio",
|
||||
"serde",
|
||||
"thiserror 2.0.19",
|
||||
@@ -2050,25 +2050,6 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "own_mcp"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cpal 0.18.1",
|
||||
"env_logger",
|
||||
"hound",
|
||||
"log",
|
||||
"ollama-rs",
|
||||
"rand 0.10.2",
|
||||
"reqwest 0.13.4",
|
||||
"rmcp",
|
||||
"serde",
|
||||
"thiserror 2.0.19",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "own_mcp"
|
||||
version = "0.1.1"
|
||||
@@ -2083,7 +2064,28 @@ dependencies = [
|
||||
"ollama-rs",
|
||||
"rand 0.10.2",
|
||||
"reqwest 0.13.4",
|
||||
"rmcp",
|
||||
"rmcp 2.2.0",
|
||||
"serde",
|
||||
"thiserror 2.0.19",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "own_mcp"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"cpal 0.18.1",
|
||||
"env_logger",
|
||||
"hound",
|
||||
"log",
|
||||
"ollama-rs",
|
||||
"rand 0.10.2",
|
||||
"reqwest 0.13.4",
|
||||
"rmcp 3.0.0",
|
||||
"serde",
|
||||
"thiserror 2.0.19",
|
||||
"tokio",
|
||||
@@ -2531,7 +2533,7 @@ dependencies = [
|
||||
"process-wrap",
|
||||
"rand 0.10.2",
|
||||
"reqwest 0.13.4",
|
||||
"rmcp-macros",
|
||||
"rmcp-macros 2.2.0",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -2546,6 +2548,37 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rmcp"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcd2b6dd3b18129368955f32661a7718969e8c152c7d8866434c09cf15a512e0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.23.0",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"futures",
|
||||
"http",
|
||||
"oauth2",
|
||||
"pastey",
|
||||
"pin-project-lite",
|
||||
"process-wrap",
|
||||
"reqwest 0.13.4",
|
||||
"rmcp-macros 3.0.0",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sse-stream",
|
||||
"thiserror 2.0.19",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rmcp-macros"
|
||||
version = "2.2.0"
|
||||
@@ -2559,6 +2592,19 @@ dependencies = [
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rmcp-macros"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1aa4b9345795260a43fc23d6d05e096407c8b953903f673af7c4404b49fb2d6"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_json",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rodio"
|
||||
version = "0.22.2"
|
||||
|
||||
+4
-2
@@ -102,12 +102,14 @@ async fn main() {
|
||||
let ollama = ollama_config.ollama();
|
||||
let model_name = &ollama_config.model_config.name;
|
||||
|
||||
ollama_config.create_model(Some(tlt!("model_download_needed"))).await.inspect_err(exit_msg!(format!(
|
||||
ollama_config
|
||||
.create_model(Some(tlt!("model_download_needed")))
|
||||
.await
|
||||
.inspect_err(exit_msg!(format!(
|
||||
"failed creating ollama model `{model_name}`"
|
||||
)))
|
||||
.unwrap();
|
||||
|
||||
|
||||
let mcp_clients = config
|
||||
.mcp_clients()
|
||||
.await
|
||||
|
||||
+9
-7
@@ -1,20 +1,22 @@
|
||||
[package]
|
||||
name = "own_mcp"
|
||||
version = "0.1.1"
|
||||
version = "0.2.0"
|
||||
edition = "2024"
|
||||
license = "GPL-3.0"
|
||||
|
||||
[dependencies]
|
||||
ollama-rs = {version = "0.3.4", features = ["macros", "headers"]}
|
||||
ollama-rs = {version = "0.3.6", features = ["macros", "headers"]}
|
||||
reqwest = { version = "0.13.2", features = ["stream", "multipart", "form"] }
|
||||
tokio = { version = "1.50.0", features = ["rt", "rt-multi-thread", "macros"] }
|
||||
rmcp = {version="2.2.0", features = ["transport-streamable-http-client-reqwest", "reqwest", "client", "auth", "transport-child-process"]}
|
||||
rmcp = {version="3.0.0", features = ["transport-streamable-http-client-reqwest", "reqwest", "client", "auth", "transport-child-process"]}
|
||||
log = {version = "0.4.29"}
|
||||
env_logger = "0.11.10"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
thiserror = "2.0.17"
|
||||
env_logger = "0.11.11"
|
||||
serde = { version = "1.0.229", features = ["derive"] }
|
||||
thiserror = "2.0.19"
|
||||
url = "2.5.8"
|
||||
rand = "0.10.0"
|
||||
rand = "0.10.2"
|
||||
cpal = "0.18.1"
|
||||
hound = "3.5.1"
|
||||
bytes = "1.11.1"
|
||||
async-trait = "0.1.91"
|
||||
chrono = "0.4.45"
|
||||
+16
-22
@@ -1,9 +1,7 @@
|
||||
use crate::mcp::MCPClient;
|
||||
use ollama_rs::Ollama;
|
||||
use ollama_rs::error::OllamaError;
|
||||
use crate::mcp::llmclient::{LLMClient, LLMError};
|
||||
use ollama_rs::generation::chat::ChatMessage;
|
||||
use ollama_rs::generation::chat::request::ChatMessageRequest;
|
||||
use ollama_rs::generation::completion::request::GenerationRequest;
|
||||
use ollama_rs::generation::tools::{ToolCall, ToolInfo};
|
||||
use rmcp::ServiceError;
|
||||
use rmcp::model::{CallToolRequestParams, CallToolResult};
|
||||
@@ -77,7 +75,7 @@ impl MCPServerData {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AgentChat {
|
||||
ollama_client: Ollama,
|
||||
llm_client: Box<dyn LLMClient>,
|
||||
model: String,
|
||||
mcp_servers: HashMap<String, MCPServerData>,
|
||||
message_history: Vec<ChatMessage>,
|
||||
@@ -86,7 +84,7 @@ pub struct AgentChat {
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ChatError {
|
||||
#[error(transparent)]
|
||||
OllamaError(#[from] OllamaError),
|
||||
LLMError(#[from] LLMError),
|
||||
#[error(transparent)]
|
||||
ServiceError(#[from] ServiceError),
|
||||
#[error("the function name could not be parsed")]
|
||||
@@ -113,7 +111,7 @@ pub struct ToolUsage {
|
||||
|
||||
impl AgentChat {
|
||||
pub async fn new(
|
||||
ollama_client: Ollama,
|
||||
llm_client: Box<dyn LLMClient>,
|
||||
model: String,
|
||||
mcp_clients: HashMap<String, MCPClient>,
|
||||
) -> Result<Self, ServiceError> {
|
||||
@@ -126,17 +124,8 @@ impl AgentChat {
|
||||
servers.insert(server.name.clone(), server);
|
||||
}
|
||||
|
||||
// lets the ollama server load the model
|
||||
let ollama_client_clone = ollama_client.clone();
|
||||
let model_clone = model.clone();
|
||||
tokio::spawn(async move {
|
||||
let _ = ollama_client_clone
|
||||
.generate(GenerationRequest::new(model_clone, ""))
|
||||
.await;
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
ollama_client,
|
||||
llm_client,
|
||||
model,
|
||||
mcp_servers: servers,
|
||||
message_history: history,
|
||||
@@ -232,7 +221,7 @@ impl AgentChat {
|
||||
log::debug!("all tools: {all_tools:#?}");
|
||||
|
||||
let mut response = self
|
||||
.ollama_client
|
||||
.llm_client
|
||||
.send_chat_messages_with_history(
|
||||
&mut self.message_history,
|
||||
ChatMessageRequest::new(self.model.clone(), vec![ChatMessage::user(user_message)])
|
||||
@@ -288,7 +277,7 @@ impl AgentChat {
|
||||
}
|
||||
|
||||
response = self
|
||||
.ollama_client
|
||||
.llm_client
|
||||
.send_chat_messages_with_history(
|
||||
&mut self.message_history,
|
||||
ChatMessageRequest::new(self.model.clone(), Vec::new())
|
||||
@@ -375,7 +364,7 @@ impl AgentChat {
|
||||
|
||||
pub fn without_history(self) -> Self {
|
||||
Self {
|
||||
ollama_client: self.ollama_client,
|
||||
llm_client: self.llm_client,
|
||||
model: self.model,
|
||||
mcp_servers: self.mcp_servers,
|
||||
message_history: vec![],
|
||||
@@ -392,6 +381,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::mcp::chat::RestrictedTool;
|
||||
use crate::mcp::get_client;
|
||||
use ollama_rs::Ollama;
|
||||
use rmcp::model::Implementation;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -421,9 +411,13 @@ mod tests {
|
||||
.unwrap(),
|
||||
)]);
|
||||
|
||||
let mut chat = AgentChat::new(ollama, "lfm2.5-thinking:1.2b".to_string(), mcp_clients)
|
||||
.await
|
||||
.unwrap();
|
||||
let mut chat = AgentChat::new(
|
||||
Box::new(ollama),
|
||||
"lfm2.5-thinking:1.2b".to_string(),
|
||||
mcp_clients,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let tools: Vec<RestrictedTool> = chat.get_all_tools().cloned().collect();
|
||||
assert_eq!(tools.len(), 1);
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
use crate::mcp::llmclient::{LLMClient, LLMError};
|
||||
use async_trait::async_trait;
|
||||
use ollama_rs::generation::chat::ChatMessage as OllamaChatMessage;
|
||||
use ollama_rs::generation::chat::request::ChatMessageRequest as OllamaChatMessageRequest;
|
||||
use ollama_rs::generation::chat::{ChatMessageResponse, MessageRole};
|
||||
use ollama_rs::generation::tools::{ToolCall, ToolInfo};
|
||||
use ollama_rs::history::ChatHistory;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Mistral {
|
||||
api_key: String,
|
||||
system_prompt: Option<String>,
|
||||
}
|
||||
|
||||
impl Mistral {
|
||||
pub fn new(api_key: String) -> Mistral {
|
||||
Mistral {
|
||||
api_key,
|
||||
system_prompt: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_system_prompt(mut self, system_prompt: Option<String>) -> Mistral {
|
||||
self.system_prompt = system_prompt;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Message {
|
||||
content: String,
|
||||
role: MessageRole,
|
||||
#[serde(
|
||||
skip_serializing_if = "Vec::is_empty",
|
||||
default = "Vec::new",
|
||||
deserialize_with = "parse_tool_calls"
|
||||
)]
|
||||
tool_calls: Vec<ToolCall>,
|
||||
}
|
||||
|
||||
fn parse_tool_calls<'de, D>(d: D) -> Result<Vec<ToolCall>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(d).map(|x: Option<_>| x.unwrap_or(Vec::new()))
|
||||
}
|
||||
|
||||
impl From<OllamaChatMessage> for Message {
|
||||
fn from(message: OllamaChatMessage) -> Message {
|
||||
Message {
|
||||
content: message.content,
|
||||
role: message.role,
|
||||
tool_calls: message.tool_calls,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Message> for OllamaChatMessage {
|
||||
fn from(message: Message) -> OllamaChatMessage {
|
||||
OllamaChatMessage {
|
||||
role: message.role,
|
||||
content: message.content,
|
||||
tool_calls: message.tool_calls,
|
||||
images: None,
|
||||
thinking: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct ChatCompletionRequest {
|
||||
messages: Vec<Message>,
|
||||
model: String,
|
||||
tools: Vec<ToolInfo>,
|
||||
}
|
||||
|
||||
impl From<OllamaChatMessageRequest> for ChatCompletionRequest {
|
||||
fn from(request: OllamaChatMessageRequest) -> ChatCompletionRequest {
|
||||
ChatCompletionRequest {
|
||||
messages: request.messages.into_iter().map(|m| m.into()).collect(),
|
||||
model: request.model_name,
|
||||
tools: request.tools,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
struct ChatCompletionChoice {
|
||||
message: Message,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
struct ChatCompletionResponse {
|
||||
choices: Vec<ChatCompletionChoice>,
|
||||
model: String,
|
||||
#[serde(rename = "created")]
|
||||
created_unix_seconds: i64,
|
||||
}
|
||||
|
||||
impl TryFrom<ChatCompletionResponse> for ChatMessageResponse {
|
||||
type Error = LLMError;
|
||||
|
||||
fn try_from(value: ChatCompletionResponse) -> Result<ChatMessageResponse, LLMError> {
|
||||
let created = chrono::DateTime::from_timestamp(value.created_unix_seconds, 0)
|
||||
.ok_or(LLMError::Other("failed converting timestamp".to_string()))?;
|
||||
|
||||
Ok(ChatMessageResponse {
|
||||
model: value.model,
|
||||
created_at: created.to_rfc3339(),
|
||||
message: value
|
||||
.choices
|
||||
.first()
|
||||
.ok_or(LLMError::Other("answer does not exist".to_string()))?
|
||||
.message
|
||||
.clone()
|
||||
.into(),
|
||||
logprobs: None,
|
||||
done: false,
|
||||
final_data: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl LLMClient for Mistral {
|
||||
async fn send_chat_messages_with_history(
|
||||
&self,
|
||||
history: &mut Vec<OllamaChatMessage>,
|
||||
mut request: ollama_rs::generation::chat::request::ChatMessageRequest,
|
||||
) -> Result<ChatMessageResponse, LLMError> {
|
||||
if let Some(first_message) = history.first() // add system prompt as first message
|
||||
&& first_message.role == MessageRole::System
|
||||
&& let Some(system_prompt) = self.system_prompt.clone()
|
||||
{
|
||||
history.insert(
|
||||
0,
|
||||
OllamaChatMessage::new(MessageRole::System, system_prompt),
|
||||
);
|
||||
}
|
||||
|
||||
history.append(&mut request.messages);
|
||||
|
||||
request.messages = history.messages().to_vec();
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let chat_completion_request: ChatCompletionRequest = request.into();
|
||||
let response = client
|
||||
.post("https://api.mistral.ai/v1/chat/completions")
|
||||
.header("Authorization", format!("Bearer {}", self.api_key))
|
||||
.json(&chat_completion_request)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| LLMError::NetworkError(e.to_string()))?;
|
||||
|
||||
let response = response
|
||||
.error_for_status()
|
||||
.map_err(|e| LLMError::Other(e.to_string()))?;
|
||||
|
||||
let completion_response: ChatCompletionResponse = response
|
||||
.json()
|
||||
.await
|
||||
.map_err(|e| LLMError::Other(e.to_string()))?;
|
||||
let chat_message_response: ChatMessageResponse = completion_response.try_into()?;
|
||||
|
||||
Ok(chat_message_response)
|
||||
}
|
||||
|
||||
async fn preload_model(&self, _model: &str) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ollama_rs::generation::chat::request::ChatMessageRequest;
|
||||
use ollama_rs::generation::chat::{ChatMessage, MessageRole};
|
||||
use rmcp::schemars;
|
||||
|
||||
#[derive(schemars::JsonSchema)]
|
||||
struct BeepToolParameters {
|
||||
location: String,
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn sending_message() {
|
||||
let client = Mistral::new(include_str!(".MISTRAL_API_KEY").to_string());
|
||||
|
||||
let mut history = vec![];
|
||||
|
||||
dbg!(
|
||||
client
|
||||
.send_chat_messages_with_history(
|
||||
&mut history,
|
||||
ChatMessageRequest::new(
|
||||
"mistral-medium-3-5".to_string(),
|
||||
vec![ChatMessage::new(
|
||||
MessageRole::User,
|
||||
"Mach ein Geräusch in der Küche".to_string()
|
||||
)],
|
||||
)
|
||||
.tools(vec![ToolInfo {
|
||||
tool_type: ollama_rs::generation::tools::ToolType::Function,
|
||||
function: ollama_rs::generation::tools::ToolFunctionInfo {
|
||||
name: "make_sound".to_string(),
|
||||
description: "alerts the user with a beep".to_string(),
|
||||
parameters: schemars::schema_for!(BeepToolParameters),
|
||||
}
|
||||
}]),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
pub mod mistral;
|
||||
pub mod ollama;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use ollama_rs::generation::chat::request::ChatMessageRequest;
|
||||
use ollama_rs::generation::chat::{ChatMessage, ChatMessageResponse};
|
||||
use std::fmt::Debug;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum LLMError {
|
||||
#[error("network error: {0}")]
|
||||
NetworkError(String),
|
||||
#[error("llm error: {0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait LLMClient: Debug + Send + Sync {
|
||||
async fn send_chat_messages_with_history(
|
||||
&self,
|
||||
history: &mut Vec<ChatMessage>,
|
||||
request: ChatMessageRequest,
|
||||
) -> Result<ChatMessageResponse, LLMError>;
|
||||
|
||||
async fn preload_model(&self, model: &str);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
use crate::mcp::llmclient::{LLMClient, LLMError};
|
||||
use async_trait::async_trait;
|
||||
use ollama_rs::Ollama;
|
||||
use ollama_rs::error::OllamaError;
|
||||
use ollama_rs::generation::chat::request::ChatMessageRequest;
|
||||
use ollama_rs::generation::chat::{ChatMessage, ChatMessageResponse};
|
||||
use ollama_rs::generation::completion::request::GenerationRequest;
|
||||
|
||||
impl From<OllamaError> for LLMError {
|
||||
fn from(err: OllamaError) -> LLMError {
|
||||
match err {
|
||||
OllamaError::ToolCallError(e) => LLMError::Other(e.to_string()),
|
||||
OllamaError::JsonError(e) => LLMError::Other(e.to_string()),
|
||||
OllamaError::ReqwestError(e) => LLMError::NetworkError(e.to_string()),
|
||||
OllamaError::InternalError(e) => LLMError::Other(e.message),
|
||||
OllamaError::Other(e) => LLMError::Other(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl LLMClient for Ollama {
|
||||
async fn send_chat_messages_with_history(
|
||||
&self,
|
||||
history: &mut Vec<ChatMessage>,
|
||||
request: ChatMessageRequest,
|
||||
) -> Result<ChatMessageResponse, LLMError> {
|
||||
Ok(self
|
||||
.send_chat_messages_with_history(history, request)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn preload_model(&self, model: &str) {
|
||||
let _ = self
|
||||
.generate(GenerationRequest::new(model.to_string(), ""))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
pub mod chat;
|
||||
mod llmclient;
|
||||
mod translation;
|
||||
|
||||
pub use llmclient::mistral::Mistral;
|
||||
|
||||
use rmcp::model::InitializeRequestParams;
|
||||
use rmcp::service::{ClientInitializeError, RunningService};
|
||||
use rmcp::transport::streamable_http_client::StreamableHttpClientTransportConfig;
|
||||
@@ -48,8 +51,10 @@ pub fn guaranteed_mcp_server_name(
|
||||
) -> String {
|
||||
if let Some(user_specified_name) = user_specified_name {
|
||||
user_specified_name
|
||||
} else if let Some(peer_info) = client.peer_info() {
|
||||
peer_info.server_info.name.clone()
|
||||
} else if let Some(peer_info) = client.peer_info()
|
||||
&& let Some(server_info) = &peer_info.server_info
|
||||
{
|
||||
server_info.name.clone()
|
||||
} else {
|
||||
let random_name = generate_random_mcp_server_name();
|
||||
log::warn!(
|
||||
|
||||
Reference in New Issue
Block a user