MCP引入一段简单的LangGraph
前言
在上一篇文章中,我们讨论了怎么在构建MCP
。为了能够实现更复杂的功能,我们尝试将LangGraph
引入到MCP
中。
一段简单的意图识别
我们就不用大模型引入乱七八糟的机制了。就一个功能,检测输入进来的字符串有多长,奇数个字符就输出Hello, <your-input>
,偶数个字符就输出<your-input>, World!
。
于是,构建三个节点:意图识别节点、Hello
节点和World
节点。
每个节点都采用一个统一的传输格式,也就是包括:
- 意图标志位的
branch
- 输入的
text
- 输出的
answer
于是,我们先定义数据结构:
1 | class State(TypeDict): |
节点就像这样:
1 | def detect_node(state: State) -> State: |
然后就是建立LangGraph
:
1 | def build() -> StateGraph: |
MCP Server
既然有了意图识别的基础,服务器端就可以建立起来了:
1 | import asyncio |
P.S.:当然,你完全可以把这个
build_graph
方法放在另一个文件中,然后import
进来,效果当然是一样的。
MCP Client
这个部分可以参考上一篇文章,代码甚至都没有变化。
运行
首先,我们将server
启动起来,只需要运行MCP Server
那个文件即可;
然后,我们运行client
,同样运行MCP Client
文件即可。
于是,我们就可以看到这些:
- 当我们输入
LangGraph
的时候,由于是奇数个字符,所以走到了Hello, LangGraph!
的逻辑里面; - 当我们输入
vLLM
的时候,由于是偶数个字符,所以走到了vLLM, World!
的逻辑里面;
总结以及需要注意的小东西
这样,我们就将LangGraph
引入了MCP
,也就可以实现更复杂的逻辑了。
但是需要注意的是,MCP
不能返回字符串以外的内容。比如,在MCP Server
中,我们不能直接输出LangGraph
默认的TypeDict
返回值,这样就会报错:
1 | Error executing tool hello: 1 validation error for helloOutput |
所以在返回的时候,我使用的是:
1 | response.get("answer", "result") |
在获取结果的时候,如果没有拿到answer
中的字符串,那就直接返回一个result
算了。
而如果直接返回response
,那么返回结果就成了:
1 | { |
这样,MCP Client
在执行过程中,会使用send_request
方法发送CallToolRequest
,并在发送请求后立即使用model_validate
方法检查返回值是否符合要求。显然,TypeDict
与str
之间还是有着显著的差异,所以不通过检查。
因此,在使用MCP
的时候,所有的内容都只能使用str
传参。