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:
parent
31493cfbcc
commit
0be6067326
1 changed files with 8676 additions and 4466 deletions
113
examples/rig-integration/src/mcp_adaptor.rs
Normal file
113
examples/rig-integration/src/mcp_adaptor.rs
Normal 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)
|
||||
}
|
||||
Loading…
Reference in a new issue