【MCP】这啥?MCP Agent开发框架?还是Rust的?

218 阅读4分钟

挺久没有更新的了,最近忙着干啥呢?没错!写了一个简单的MCP Agent的开发框架。我们先来讲讲为什么,再来具体介绍这个MCP Agent。这里也有留下几个可以优化的小点,如果大家有想法的话可以参与一下开源🤓。

Github:github.com/CeerDecy/mc…

为什么?

其实在我的工作中对MCP的应用已经很多了,我在咱们公司呢也是主要负责基础MCP的开发工作以及部署。由于我们负责的MCP工具会用到LLM,LLM会再去调用别的MCP工具,骨子里其实更像是个披着 MCP 协议马甲的 Agent,只不过提供了MCP协议的交互方式。(顺便说一下,部署这块咱用的也是自己开发的一个Kubernetes Operator,后面也可以出个开源版本)

于是我就在公司中使用Golang简单搓了一个MCP Agent框架,来满足大部分MCP开发的需求。碰巧主播在学习Rust这门语言🤓,于是想着把这个MCP Agent框架使用Rust语言重构一下,巩固一下Rust知识,那将其开源出来也能够听取社区的意见。

1*CfU3OrObnsCucKF6bpf7OA.png

MCP Agent

既然有了以上简述,那自然而然就能联想到我们这个框架需要有两大部分:第一部分呢就是LLM的客户端;第二部分呢是MCP的客户端以及服务端,毕竟咱还要对外提供服务嘛!

LLM

主要功能:

  • 提供LLM交互的客户端

OK,那么先来讲第一部分:LLM客户端呢,我们使用的是async-openai这个库,目前大部分的LLM接口都能够支持openai的API,那我们暂时就实现openai这套逻辑其实就可以了,当然为了保证兼容,我们先抽象出来了一个trait,里边呢目前只有一个send函数。

#[async_trait]
pub trait LLM: Send + Sync {
    async fn send(&self, conversation: Conversation) -> ChatResponse;
}

这个代码呢目前再mcp-agent/llm这个包下面,从包名就可以看出来,这里的代码都是和llm client相关的。

Agent

主要功能:

  • 初始化所依赖的MCP工具
  • 构建ToolCall的Message
  • 执行LLM返回的ToolCalls

接下来可以看一下mcp-agent/agent这个包,那这里的代码呢主要是负责使用llm的客户端进行发送message,以及处理tool_call的功能。这里的重点呢其实是send以及handle_tool_calls这个函数,在send函数中根据llm的response,来判断是否要执行handle_tool_calls,当然执行完过后还要递归调用回去。这里可能直接使用loop性能会好一点,当然handle_tool_calls里也有优化的地方:

目前执行call_tool使用的是await,所以会阻塞,如果要执行call的tool多了以后会很影响执行时间,这边后续可以改为并行或并发执行。

    async fn handle_tool_calls(&self,toolcalls: Vec<ChatCompletionMessageToolCall>,conversation: &mut Conversation) -> Result<(), Box<dyn Error>> {
        for call in toolcalls {
            // ...
​
            if let Some(client) = self.tools_clients.get(&name) {
                let result = client
                    .call_tool(CallToolRequestParam {
                        name: name.into(),
                        arguments: serde_json::from_str::<Value>(&arguments)?
                            .as_object()
                            .cloned(),
                    })
                    .await?;
​
                // ...
            }
        }
        // ...
    }

Mcp-Server

主要功能:

  • 对外提供MCP服务
  • 对MCP工具注入Agent客户端

最后就是mcp-agent/mcp_server这个包,这个包呢主要是用来启动mcp服务器以对外提供服务,以及将Agent传递到工具层。这里其实有个点我想说,官方的rmcp这个库目前配置Tool的定义是使用宏来完成的,这就意味着Tool的参数、描述信息等都在编译器已经确定了而不是运行时,这就丧失了一定的灵活性,导致我没有办法像go一样通过闭包的方式来传递Agent客户端。

image.png

最后我只能通过改造注册函数的形式,提供一个Agent参数来变向为各种工具提供这个Agent客户端,这就意味着用户需要在自己的工具里维护这个Agent客户端,具体可以看一下example里的例子,代码在这。如果大家有啥好的想法欢迎提PR。

image.png

Help Me

对于一些想要参与开源的小伙伴,可以看一下这里:

  • agent的send函数改为使用loop(简单)
  • handle_tool_calls中的too_call可以改为并发或者并行(简单)
  • mcp tool的注册方式优化(困难)

Github:github.com/CeerDecy/mc…

1131749996635_.pic.jpg