@@ -38,12 +38,12 @@ controller = Controller(max_turns=10)
3838## 启动智能体
3939
4040``` python
41- _, resp = controller.run (agent = translator, message = " 请帮我翻译蛋白质。" )
41+ _, resp = controller.run_sync (agent = translator, message = " 请帮我翻译蛋白质。" )
4242```
4343
4444其中 ` message ` 参数代表用户的具体指令或者是用户与智能体对话的开始。
4545
46- ` controller.run ` 方法返回两个值, 其中第一个值代表最后响应的 ` Agent ` 对象 (暂时还用不到), 第二个值代表智能体最后的相应内容。在这个例子中, ` resp ` 的值应该是智能体翻译的结果 (不排除其中包含一些提示语)。
46+ ` controller.run_sync ` 方法返回两个值, 其中第一个值代表最后响应的 ` Agent ` 对象 (暂时还用不到), 第二个值代表智能体最后的相应内容。在这个例子中, ` resp ` 的值应该是智能体翻译的结果 (不排除其中包含一些提示语)。
4747
4848## 使用外部工具
4949
@@ -253,22 +253,111 @@ from course_graph.agent import Result
253253result = Result(context_variables = {' current_time' : ' 2024/09/02' })
254254```
255255
256+ ## MCP 支持
257+
258+ > [ !NOTE]
259+ > 目前 MCP 协议是通过 function call 功能实现的。
260+
261+ ### 获取一个 MCP Server
262+
263+ 你可以通过 [ Model Context Protocol servers] ( https://github.com/modelcontextprotocol/servers ) 等项目获取到大量的 MCP Server 资源。
264+
265+ 这里我们使用 Python SDK 实现一个简单的 MCP Server:
266+
267+ ``` python
268+ from mcp.server.fastmcp import FastMCP
269+ import json
270+
271+ mcp = FastMCP(' weather' )
272+
273+ @mcp.tool ()
274+ def get_weather (city : str ) -> str :
275+ """ 获取指定城市当天的天气
276+
277+ Args:
278+ city: 城市名称
279+
280+ Returns:
281+ dict: 天气信息
282+ """
283+ resp = {
284+ ' city' : city,
285+ ' temperature_high' : 20 ,
286+ ' temperature_low' : 18 ,
287+ ' temperature_unit' : ' C' ,
288+ ' weather' : ' sunny'
289+ }
290+ return json.dumps(resp, ensure_ascii = False )
291+
292+ if __name__ == ' __main__' :
293+ mcp.run(transport = ' stdio' )
294+ ```
295+
296+ 项目创建以及环境配置可以参考 [ 官方文档] ( https://modelcontextprotocol.io/quickstart/server ) 。 该 Server 可以通过以下命令启动:
297+
298+ ``` bash
299+ uv --directory examples/agent run mcp_server.py
300+ ```
301+
302+ ### 为智能体添加 MCP Server 并启动
303+
304+ ``` python
305+ from course_graph.agent import Agent, Controller, MCPServer
306+ from course_graph.llm import Qwen
307+ import asyncio
308+
309+ qwen = Qwen()
310+
311+ async def main ():
312+ async with MCPServer(
313+ type = ' stdio' ,
314+ command = ' uv' ,
315+ args = [' --directory' , ' examples/agent' , ' run' , ' mcp_server.py' ],
316+ ) as mcp_server:
317+
318+ agent = Agent(
319+ llm = qwen,
320+ mcp_server = [mcp_server]
321+ )
322+ await agent.initialize()
323+ controller = Controller()
324+ _, resp = await controller.run(agent, " 帮我查询南京今天的天气" )
325+ print (resp)
326+
327+ if __name__ == ' __main__' :
328+ asyncio.run(main())
329+ ```
330+
331+ 这里有三需要注意:
332+
333+ - MCP Server 必须使用 ` async with ` 语句块来启动。
334+
335+ - 如果给 ` Agent ` 传递了 ` mcp_server ` 参数, 必须调用 ` await agent.initialize() ` 方法等待初始化完成。
336+
337+ - ` Controller ` 必须使用异步的 ` run ` 方法来启动。不能使用同步的 ` run_sync ` 方法, 因为本质上 ` run_sync ` 只是 ` asyncio.run(controller.run(...)) ` 的包装。
338+
339+ ### MCP Server 与外部工具的比较
340+
341+ 这里 MCP 协议虽然是通过 function call 功能实现的, 但是缺失了自动注入上下文变量和当前 Agent 的功能。并且本地外部工具的优先级更高,如果遇到同名的工具函数,会优先调用本地函数。
342+
256343## Trace
257344
258345Trace 功能, 可以记录智能体的对话、工具调用、上下文变量变化等历史。 ` Controller ` 的 ` trace_callback ` 参数可以传递一个回调函数, 当 trace 事件发生时, 会调用该回调函数。
259346
260347``` python
348+ from pprint import pprint
349+
261350controller = Controller(trace_callback = pprint)
262351```
263352
264- 该回调函数需要接受一个 ` TraceEvent ` 类型的参数, 具体来说包含以下几种类型 :
353+ 该回调函数需要接受一个 ` TraceEvent ` 类型的参数, 其中事件类型包括 :
265354
266- - ` TraceEventUserMessage ` : 用户消息
267- - ` TraceEventAgentMessage ` : 智能体消息
268- - ` TraceEventAgentSwitch ` : 智能体切换
269- - ` TraceEventToolCall ` : 工具调用
270- - ` TraceEventToolResult ` : 工具调用结果
271- - ` TraceEventContextUpdate ` : 上下文变量更新
355+ - ` USER_MESSAGE ` : 用户消息
356+ - ` AGENT_MESSAGE ` : 智能体消息
357+ - ` AGENT_SWITCH ` : 智能体切换
358+ - ` TOOL_CALL ` : 工具调用
359+ - ` TOOL_RESULT ` : 工具调用结果
360+ - ` CONTEXT_UPDATE ` : 上下文变量更新
272361
273362## 多智能体编排
274363
0 commit comments