langgraph+mcp+豆包API 实现本土大模型mcp
math_weather_server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Math")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
"""Multiply two numbers"""
return a * b
@mcp.tool()
def get_weather(location: str) -> str:
"""Get weather for location."""
return "It's always sunny in New York"
if __name__ == "__main__":
mcp.run(transport="stdio")
main.py
'''
名词介绍
名词介绍Agent在 LLM 语境下,Agent 是某种能自主理解意图、规划决策、执行复杂任务的智能体workflow工作流,指一系列自动化或半自动化的步骤,用于完成特定任务(如数据处理、模型处理等)MCPModel Context Protocol(模型上下文协议),规范了应用程序如何为 LLMs 提供上下文,类似AI应用的USB-C端口Langchain开源AI框架,用于构建基于大语言模型(LLM)的应用程序,支持模块化链式调用、记忆管理等LangGraphLangChain的扩展库,专注于通过图结构(如循环、分支)构建复杂的多步骤AI工作流
作者:MrGaoGang
链接:https://juejin.cn/post/7512237186647408667
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
'''
# 官方文档:: https://github.langchain.ac.cn/langgraph/agents/mcp/
import asyncio
async def main():
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
client = MultiServerMCPClient(
{
"math": {
"command": "python",
# Replace with absolute path to your math_server.py file
"args": ["math_weather_server.py"],
"transport": "stdio",
},
}
)
from langchain_openai import ChatOpenAI
tools = await client.get_tools()
llm=ChatOpenAI( base_url="https://ark.cn-beijing.volces.com/api/v3",
api_key='你的豆包APIkey',
model="doubao-1.5-lite-32k-250115")
agent = create_react_agent(
llm,
tools
)
math_response = await agent.ainvoke(
{"messages": [{"role": "user", "content": "what's (3 + 5) x 12?"}]}
)
weather_response = await agent.ainvoke(
{"messages": [{"role": "user", "content": "what is the weather in nyc?"}]}
)
print(math_response,weather_response)
asyncio.run(main())
效果展示:
root2@DESKTOP-2M26L51:/mnt/d/blender-mcp-main$ python 8.py
[07/01/25 09:29:50] INFO Processing request of type ListToolsRequest server.py:556
[07/01/25 09:30:04] INFO Processing request of type CallToolRequest server.py:556
[07/01/25 09:30:05] INFO Processing request of type CallToolRequest server.py:556
'messages': [HumanMessage(content="what's (3 + 5) x 12?", additional_kwargs={}, response_metadata={}, id='3627dddb-7f15-45e4-a20f-77901c3e3272'), AIMessage(content='先计算3+5,再将结果乘以12。调用add函数计算3+5,再调用multiply函数将add的结果乘以12。', additional_kwargs={'tool_calls': [{'id': 'call_kdi6bsfcir21ss1bhwtyodsl', 'function': {'arguments': ' {\n "a": 3,\n "b": 5\n }', 'name': 'add'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 90, 'prompt_tokens': 166, 'total_tokens': 256, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'doubao-1-5-lite-32k-250115', 'system_fingerprint': None, 'id': '0217513334038032b1cbd498254a886733ad2256aff389e6487fd', 'service_tier': 'default', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--4a707620-e046-4e39-85b0-973606ca963e-0', tool_calls=[{'name': 'add', 'args': {'a': 3, 'b': 5}, 'id': 'call_kdi6bsfcir21ss1bhwtyodsl', 'type': 'tool_call'}], usage_metadata={'input_tokens': 166, 'output_tokens': 90, 'total_tokens': 256, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}}), ToolMessage(content='8', name='add', id='b41c1e11-6179-4238-95fd-fd080f373b4d', tool_call_id='call_kdi6bsfcir21ss1bhwtyodsl'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_q2m078jvpo2c7empgz0qlrol', 'function': {'arguments': ' {"a": 8, "b": 12}', 'name': 'multiply'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 33, 'prompt_tokens': 250, 'total_tokens': 283, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'doubao-1-5-lite-32k-250115', 'system_fingerprint': None, 'id': '0217513334064462b1cbd498254a886733ad2256aff389eec04cd', 'service_tier': 'default', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--20a5b079-e260-4466-9ad9-5ce0440bac87-0', tool_calls=[{'name': 'multiply', 'args': {'a': 8, 'b': 12}, 'id': 'call_q2m078jvpo2c7empgz0qlrol', 'type': 'tool_call'}], usage_metadata={'input_tokens': 250, 'output_tokens': 33, 'total_tokens': 283, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}}), ToolMessage(content='96', name='multiply', id='7bcbd35a-ebc0-4f96-b688-11a7da53c2cf', tool_call_id='call_q2m078jvpo2c7empgz0qlrol'), AIMessage(content='(3 + 5) x 12 的结果是96。 先使用add函数得到3 + 5的结果为8,然后使用multiply函数将8乘以12,得到最终结果96。 ', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 49, 'prompt_tokens': 303, 'total_tokens': 352, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'doubao-1-5-lite-32k-250115', 'system_fingerprint': None, 'id': '0217513334077992b1cbd498254a886733ad2256aff389e289148', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--cf79fa54-ab9e-4d4a-87f0-4bdee4b3c8ff-0', usage_metadata={'input_tokens': 303, 'output_tokens': 49, 'total_tokens': 352, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})]} {'messages': [HumanMessage(content='what is the weather in nyc?', additional_kwargs={}, response_metadata={}, id='41818ebd-84bc-4f35-98d3-907618cad6c7'), AIMessage(content='User wants to know weather in nyc, call get_weather function with location as nyc.\n', additional_kwargs={'tool_calls': [{'id': 'call_842gdruqbzy86zsp0x1dpt7g', 'function': {'arguments': ' {\n "location": "nyc"\n }', 'name': 'get_weather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 73, 'prompt_tokens': 161, 'total_tokens': 234, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'doubao-1-5-lite-32k-250115', 'system_fingerprint': None, 'id': '0217513334090202b1cbd498254a886733ad2256aff389e6bd651', 'service_tier': 'default', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--85135ccb-ee3a-4b4b-bed7-d0e8cb68a994-0', tool_calls=[{'name': 'get_weather', 'args': {'location': 'nyc'}, 'id': 'call_842gdruqbzy86zsp0x1dpt7g', 'type': 'tool_call'}], usage_metadata={'input_tokens': 161, 'output_tokens': 73, 'total_tokens': 234, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}}), ToolMessage(content="It's always sunny in New York", name='get_weather', id='4ed70420-1ea0-43d4-a13f-ec972fdb60d4', tool_call_id='call_842gdruqbzy86zsp0x1dpt7g'), AIMessage(content='The weather in New York City is always sunny.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 235, 'total_tokens': 245, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'doubao-1-5-lite-32k-250115', 'system_fingerprint': None, 'id': '0217513334105362b1cbd498254a886733ad2256aff389e509a18', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--b336b2a5-dd67-4a36-ba45-6ee85ebd4183-0', usage_metadata={'input_tokens': 235, 'output_tokens': 10, 'total_tokens': 245, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})]