Move whole rmcp crate to offcial rust sdk (#44)

* get rid of async-trait

* move rmcp to official-rust-sdk

* replace master with main

* update readme, change license

* fix typo

* Update README.md

Co-authored-by: Jefry Dewangga <jefrydco@gmail.com>

* fix typos

---------

Co-authored-by: = <=>
Co-authored-by: Jefry Dewangga <jefrydco@gmail.com>
This commit is contained in:
4t145 2025-03-28 05:33:41 +08:00 • committed by GitHub
commit 0be6067326
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -0,0 +1,113 @@
use std::collections::HashMap;
use rig::tool::{ToolDyn as RigTool, ToolEmbeddingDyn, ToolSet};
use rmcp::{
RoleClient,
model::{CallToolRequestParam, CallToolResult, Tool as McpTool},
service::{RunningService, ServerSink},
};
pub struct McpToolAdaptor {
tool: McpTool,
server: ServerSink,
}
impl RigTool for McpToolAdaptor {
fn name(&self) -> String {
self.tool.name.to_string()
}
fn definition(
&self,
_prompt: String,
) -> std::pin::Pin<Box<dyn Future<Output = rig::completion::ToolDefinition> + Send + Sync + '_>>
{
Box::pin(std::future::ready(rig::completion::ToolDefinition {
name: self.name(),
description: self.tool.description.to_string(),
parameters: self.tool.schema_as_json_value(),
}))
}
fn call(
&self,
args: String,
) -> std::pin::Pin<
Box<dyn Future<Output = Result<String, rig::tool::ToolError>> + Send + Sync + '_>,
> {
let server = self.server.clone();
Box::pin(async move {
let call_mcp_tool_result = server
.call_tool(CallToolRequestParam {
name: self.tool.name.clone(),
arguments: serde_json::from_str(&args)
.map_err(rig::tool::ToolError::JsonError)?,
})
.await
.map_err(|e| rig::tool::ToolError::ToolCallError(Box::new(e)))?;
Ok(convert_mcp_call_tool_result_to_string(call_mcp_tool_result))
})
}
}
impl ToolEmbeddingDyn for McpToolAdaptor {
fn embedding_docs(&self) -> Vec<String> {
vec![
self.tool.description.clone().to_string(),
format!("Tool name: {}", self.tool.name),
format!("Tool capability: {}", self.tool.description),
]
}
fn context(&self) -> serde_json::Result<serde_json::Value> {
Ok(serde_json::json!({
"tool_name": self.tool.name,
}))
}
}
pub struct McpManager {
pub clients: HashMap<String, RunningService<RoleClient, ()>>,
}
impl McpManager {
pub async fn get_tool_set(&self) -> anyhow::Result<ToolSet> {
let mut tool_set = ToolSet::default();
let mut task = tokio::task::JoinSet::<anyhow::Result<_>>::new();
for client in self.clients.values() {
let server = client.peer().clone();
task.spawn(get_tool_set(server));
}
let results = task.join_all().await;
for result in results {
match result {
Err(e) => {
eprintln!("Failed to get tool set: {:?}", e);
}
Ok(tools) => {
tool_set.add_tools(tools);
}
}
}
Ok(tool_set)
}
}
pub fn convert_mcp_call_tool_result_to_string(result: CallToolResult) -> String {
serde_json::to_string(&result).unwrap()
}
pub async fn get_tool_set(server: ServerSink) -> anyhow::Result<ToolSet> {
let tools = server.list_all_tools().await?;
let mut tool_set = ToolSet::default();
for tool in tools {
eprintln!("get tool: {}", tool.name);
let adaptor = McpToolAdaptor {
tool: tool.clone(),
server: server.clone(),
};
tool_set.add_tool(adaptor);
}
Ok(tool_set)
}