# math_server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Math")
@mcp.tool()
def add(a: int, b: int) -> int:
"""两个数相加"""
return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
"""两个数相乘"""
return a * b
@mcp.tool()
def get_weather(city: str) -> str:
"""获取指定城市的天气信息"""
return f"{city}天气:晴,25℃"
if __name__ == "__main__":
mcp.run(transport="stdio")
上面是工具tool_server.py
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
import asyncio
# model = ChatOpenAI(
# model="qwen-plus",
# api_key="sk-b770a417906a46ea99508a5f1ef030bc",
# base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
# )
# model = ChatOpenAI(
# model="qianwen3",
# api_key="sk-xxx",
# base_url="http://localhost:9001/v1/",
# # system_message="你是一个AI助手,需要借助工具回答用户问题" # 部分LLM支持该参数
# )
model = ChatOpenAI(
model="qwen3:0.6b",
api_key="sk-xxx",
base_url="http://127.0.0.1:11434/v1",
extra_body={"enable_thinking": True}
)
# model = OpenAI(
# api_key="sk-xxx",
# base_url="http://localhost:9001/v1/"
# )
server_params = StdioServerParameters(
command="python",
args=["math_server.py"]
)
# server_params = StdioServerParameters(
# command="python",
# args=["weather_server.py"]
# )
async def main():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await load_mcp_tools(session)
print(tools)
print("---" * 20)
agent = create_react_agent(model, tools)
# print(agent)
agent_response = await agent.ainvoke({"messages": "石家庄天气?"})
print(agent_response)
print("---" * 20)
for message in agent_response['messages']:
print("--1-" * 20)
print(message.type + ":" + message.content)
if __name__ == "__main__":
asyncio.run(main())
第二个py是client.py,运行结果
C:\Users\41684\AppData\Local\Programs\Python\Python313\python.exe C:\Users\41684\Desktop\work\study\pythonProject1\client.py
[06/09/25 15:10:27] INFO Processing request of type server.py:556
ListToolsRequest
[StructuredTool(name='add', description='两个数相加', args_schema={'properties': {'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}, 'required': ['a', 'b'], 'title': 'addArguments', 'type': 'object'}, response_format='content_and_artifact', coroutine=<function convert_mcp_tool_to_langchain_tool.<locals>.call_tool at 0x000001BFD9F3FCE0>), StructuredTool(name='multiply', description='两个数相乘', args_schema={'properties': {'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}, 'required': ['a', 'b'], 'title': 'multiplyArguments', 'type': 'object'}, response_format='content_and_artifact', coroutine=<function convert_mcp_tool_to_langchain_tool.<locals>.call_tool at 0x000001BFD9FA9BC0>), StructuredTool(name='get_weather', description='获取指定城市的天气信息', args_schema={'properties': {'city': {'title': 'City', 'type': 'string'}}, 'required': ['city'], 'title': 'get_weatherArguments', 'type': 'object'}, response_format='content_and_artifact', coroutine=<function convert_mcp_tool_to_langchain_tool.<locals>.call_tool at 0x000001BFD9FA9C60>)]
------------------------------------------------------------
[06/09/25 15:10:33] INFO Processing request of type server.py:556
CallToolRequest
{'messages': [HumanMessage(content='石家庄天气?', additional_kwargs={}, response_metadata={}, id='fc32465d-6442-462e-86f2-a33fbdff2abb'), AIMessage(content='<think>\n好的,用户问的是“石家庄天气?”,我需要用提供的工具来获取天气信息。首先,检查可用的工具,发现有一个get_weather功能,需要参数是城市名。用户没有给出具体城市,所以可能需要询问或者假设城市是石家庄。不过根据指示,如果用户的问题中已经明确提到城市,可以直接使用。但这里用户直接提问,所以应该直接调用该工具,参数为city:石家庄。确认无误后,生成相应的调用JSON。\n</think>\n\n', additional_kwargs={'tool_calls': [{'id': 'call_fh08hvc4', 'function': {'arguments': '{"city":"石家庄"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 125, 'prompt_tokens': 249, 'total_tokens': 374, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'qwen3:0.6b', 'system_fingerprint': 'fp_ollama', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--ace228fc-2264-45e2-9f98-72f69f623b07-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '石家庄'}, 'id': 'call_fh08hvc4', 'type': 'tool_call'}], usage_metadata={'input_tokens': 249, 'output_tokens': 125, 'total_tokens': 374, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content='石家庄天气:晴,25℃', name='get_weather', id='ed05c6a1-064c-47b9-a70c-fe7ed2fe50b0', tool_call_id='call_fh08hvc4'), AIMessage(content='<think>\n好的,用户之前询问了石家庄的天气情况,我调用了get_weather工具,并返回了天气信息。现在用户可能希望进一步了解或有其他问题需要帮助。需要确认用户是否有其他请求,或者是否需要更多的信息。如果用户没有进一步提问,应该总结之前的回答,并保持开放的态度,以便提供更好的帮助。\n</think>\n\n石家庄当前天气:晴,温度25℃。需要我为您整理一下近期天气数据吗?或者您还有其他问题想询问?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 103, 'prompt_tokens': 376, 'total_tokens': 479, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'qwen3:0.6b', 'system_fingerprint': 'fp_ollama', 'finish_reason': 'stop', 'logprobs': None}, id='run--2eb9186e-ec8c-47b7-a595-d721605ccce2-0', usage_metadata={'input_tokens': 376, 'output_tokens': 103, 'total_tokens': 479, 'input_token_details': {}, 'output_token_details': {}})]}
------------------------------------------------------------
--1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1-
human:石家庄天气?
--1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1-
ai:<think>
好的,用户问的是“石家庄天气?”,我需要用提供的工具来获取天气信息。首先,检查可用的工具,发现有一个get_weather功能,需要参数是城市名。用户没有给出具体城市,所以可能需要询问或者假设城市是石家庄。不过根据指示,如果用户的问题中已经明确提到城市,可以直接使用。但这里用户直接提问,所以应该直接调用该工具,参数为city:石家庄。确认无误后,生成相应的调用JSON。
</think>
--1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1-
tool:石家庄天气:晴,25℃
--1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1---1-
ai:<think>
好的,用户之前询问了石家庄的天气情况,我调用了get_weather工具,并返回了天气信息。现在用户可能希望进一步了解或有其他问题需要帮助。需要确认用户是否有其他请求,或者是否需要更多的信息。如果用户没有进一步提问,应该总结之前的回答,并保持开放的态度,以便提供更好的帮助。
</think>
石家庄当前天气:晴,温度25℃。需要我为您整理一下近期天气数据吗?或者您还有其他问题想询问?
Process finished with exit code 0
我们可以看到调用了tool_server.py中的 get_weather的方法