LangGraph实战:整合MCP(本地模式
LangGraph实战:整合MCP(本地模式)
概述
本文介绍在langgraph 的Agent中,使用MCP Client连接和调用MCP server的工具(函数),实现Agent的各个步骤的功能。本文使用stdio模式,没有使用sse协议。
我这里使用本地ollama,基础模型使用llama3.2:latest。
先安装Ollama服务,并下载对应的大模型。创建一个.env文件,并配置参数:
LLM_TEMPERATURE=0.2
OLLAMA_MODEL='llama3.2:latest'
OLLAMA_BASE_URL='http://127.0.0.1:11434'
PY_PROJECT_DIR='/root/do_langmcp/'
SSE_BASE_URL='http://172.16.1.3:8000/sse'
开发MCP Server
开发一个MCP Server,定义2个函数,用来计算简单interest和复合interest。这里我们使用FastMCP来开发MCP服务。其代码文件mcp-interest-server1.py如下:
from mcp.server.fastmcp import FastMCP
import logginglogging.basicConfig(format='%(levelname)s %(asctime)s - %(message)s', level=logging.INFO)
logger = logging.getLogger('interest_mcp_server')mcp = FastMCP('InterestCalculator')# 定义计算简单interest的工具函数
@mcp.tool()
def yearly_simple_interest(principal: float, rate:float) -> float:"""Tool to compute simple interest rate for a year."""logger.info(f'Simple interest -> Principal: {principal}, Rate: {rate}')return principal * rate / 100.00# 定义计算复合interest的工具函数
@mcp.tool()
def yearly_compound_interest(principal: float, rate:float) -> float:"""Tool to compute compound interest rate for a year."""logger.info(f'Compound interest -> Principal: {principal}, Rate: {rate}')return principal * (1 + rate / 100.0)# 定义运行工具的入口
if __name__ == '__main__':logger.info(f'Starting the interest MCP server...')mcp.run(transport='stdio')
使用langgraph开发agent来使用MCP Server
打开一个文件,使用langgraph创建一个最简单的agent,代码文件命名为mcp-client-inerest1.py,内容如下:
from dotenv import load_dotenv, find_dotenv
from langchain_ollama import ChatOllama
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_clientimport asyncio
import logging
import oslogging.basicConfig(format='%(levelname)s %(asctime)s - %(message)s', level=logging.INFO)logger = logging.getLogger('interest_mcp_client')load_dotenv(find_dotenv())home_dir = os.getenv('HOME')
llm_temperature = float(os.getenv('LLM_TEMPERATURE'))
ollama_model = os.getenv('OLLAMA_MODEL')
ollama_base_url = os.getenv('OLLAMA_BASE_URL')
py_project_dir = os.getenv('PY_PROJECT_DIR')server_params = StdioServerParameters(command='python',# Full absolute path to mcp server#args=[home_dir + py_project_dir + 'interest_mcp_server.py'],args=[py_project_dir + 'interest_mcp_server.py'],
)ollama_chat_llm = ChatOllama(base_url=ollama_base_url, model=ollama_model, temperature=llm_temperature)async def main():# 调用 MCP server,使用stdio/stdout,本地模式async with stdio_client(server_params) as (read, write):# 创建MCP client sessionasync with ClientSession(read, write) as session:# 链接到MCP serverawait session.initialize()# 获取工具列表tools = await load_mcp_tools(session)logger.info(f'Loaded MCP Tools -> {tools}')# 创建一个ReACT agentagent = create_react_agent(ollama_chat_llm, tools)# Case - 1 : 定义简单interestagent_response_1 = await agent.ainvoke({'messages': 'explain the definition of simple interest ?'})logger.info(agent_response_1['messages'][::-1])# Case - 2 : 计算简单interestagent_response_2 = await agent.ainvoke({'messages': 'compute the simple interest for a principal of 1000 at rate 3.75 ?'})logger.info(agent_response_2['messages'][::-1])# Case - 3 : 计算复合interestagent_response_3 = await agent.ainvoke({'messages': 'compute the compound interest for a principal of 1000 at rate 4.25 ?'})logger.info(agent_response_3['messages'][::-1])if __name__ == '__main__':asyncio.run(main())
运行代码
在运行之前要安装好对应的依赖包。然后执行以下命令:
python mcp-interest-server1.py
再运行client端
python mcp-interest-client1.py
此时,Langgraph定义的Agent将会根据问答来调用对应的工具完成功能。
输出如下:
(langx) root@tra:~/do_langmcp# python interest_mcp_client.py
INFO 2025-07-27 21:29:34,733 - Starting the interest MCP server...
INFO 2025-07-27 21:29:34,748 - Processing request of type ListToolsRequest
INFO 2025-07-27 21:29:34,752 - Loaded MCP Tools -> [StructuredTool(name='yearly_simple_interest', description='Tool to compute simple interest rate for a year.', args_schema={'properties': {'principal': {'title': 'Principal', 'type': 'number'}, 'rate': {'title': 'Rate', 'type': 'number'}}, 'required': ['principal', 'rate'], 'title': 'yearly_simple_interestArguments', 'type': 'object'}, response_format='content_and_artifact', coroutine=<function convert_mcp_tool_to_langchain_tool.<locals>.call_tool at 0x7f1e5bebd080>), StructuredTool(name='yearly_compound_interest', description='Tool to compute compound interest rate for a year.', args_schema={'properties': {'principal': {'title': 'Principal', 'type': 'number'}, 'rate': {'title': 'Rate', 'type': 'number'}}, 'required': ['principal', 'rate'], 'title': 'yearly_compound_interestArguments', 'type': 'object'}, response_format='content_and_artifact', coroutine=<function convert_mcp_tool_to_langchain_tool.<locals>.call_tool at 0x7f1e5bebd1c0>)]INFO 2025-07-27 21:29:42,622 - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
INFO 2025-07-27 21:29:42,722 - Processing request of type CallToolRequest
INFO 2025-07-27 21:29:42,722 - Simple interest -> Principal: 1000.0, Rate: 5.0
INFO 2025-07-27 21:30:05,234 - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
INFO 2025-07-27 21:30:05,237 - [AIMessage(content='Simple interest is a type of interest calculated on the initial principal amount (also known as the principal) that is borrowed or invested. It is a fixed rate of interest that is applied to the principal amount over a specific period of time, usually expressed in years.\n\nThe formula for calculating simple interest is:\n\nSimple Interest = Principal x Rate x Time\n\nWhere:\n\n* Principal is the initial amount borrowed or invested\n* Rate is the annual interest rate (in decimal form)\n* Time is the number of years the money is borrowed or invested for\n\nFor example, if you deposit $1,000 into a savings account with an annual interest rate of 5%, and it earns simple interest over one year, your total balance at the end of the year would be:\n\n$1,000 (initial principal) + $50 (simple interest) = $1,050\n\nSimple interest is often used in loans, credit cards, and other types of borrowing, where the lender charges a fixed rate of interest on the borrowed amount.', additional_kwargs={}, response_metadata={'model': 'llama3.2:latest', 'created_at': '2025-07-27T13:30:05.231338426Z', 'done': True, 'done_reason': 'stop', 'total_duration': 22502140979, 'load_duration': 23142327, 'prompt_eval_count': 100, 'prompt_eval_duration': 610240428, 'eval_count': 205, 'eval_duration': 21867524100, 'message': Message(role='assistant', content='Simple interest is a type of interest calculated on the initial principal amount (also known as the principal) that is borrowed or invested. It is a fixed rate of interest that is applied to the principal amount over a specific period of time, usually expressed in years.\n\nThe formula for calculating simple interest is:\n\nSimple Interest = Principal x Rate x Time\n\nWhere:\n\n* Principal is the initial amount borrowed or invested\n* Rate is the annual interest rate (in decimal form)\n* Time is the number of years the money is borrowed or invested for\n\nFor example, if you deposit $1,000 into a savings account with an annual interest rate of 5%, and it earns simple interest over one year, your total balance at the end of the year would be:\n\n$1,000 (initial principal) + $50 (simple interest) = $1,050\n\nSimple interest is often used in loans, credit cards, and other types of borrowing, where the lender charges a fixed rate of interest on the borrowed amount.', images=None, tool_calls=None)}, id='run-dbb336db-62dd-4f0e-94c9-c98661b4881b-0', usage_metadata={'input_tokens': 100, 'output_tokens': 205, 'total_tokens': 305}), ToolMessage(content='50.0', name='yearly_simple_interest', id='2e4f8534-e465-40f6-9dc6-48ce9c4dcc4b', tool_call_id='3dad76eb-6f6a-4f91-81be-85816e191f3c'), AIMessage(content='', additional_kwargs={}, response_metadata={'model': 'llama3.2:latest', 'created_at': '2025-07-27T13:29:42.717316979Z', 'done': True, 'done_reason': 'stop', 'total_duration': 7937280022, 'load_duration': 2685876507, 'prompt_eval_count': 236, 'prompt_eval_duration': 2687458417, 'eval_count': 26, 'eval_duration': 2562201643, 'message': Message(role='assistant', content='', images=None, tool_calls=None)}, id='run-d7b0b0f7-e96f-4979-97d8-4b41a7e51506-0', tool_calls=[{'name': 'yearly_simple_interest', 'args': {'principal': 1000, 'rate': 5}, 'id': '3dad76eb-6f6a-4f91-81be-85816e191f3c', 'type': 'tool_call'}], usage_metadata={'input_tokens': 236, 'output_tokens': 26, 'total_tokens': 262}), HumanMessage(content='explain the definition of simple interest ?', additional_kwargs={}, response_metadata={}, id='2d8300ee-3e5c-4be4-9f80-955bd70fd306')]
INFO 2025-07-27 21:30:10,352 - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
INFO 2025-07-27 21:30:10,451 - Processing request of type CallToolRequest
INFO 2025-07-27 21:30:10,451 - Simple interest -> Principal: 1000.0, Rate: 3.75
INFO 2025-07-27 21:30:14,101 - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
INFO 2025-07-27 21:30:14,104 - [AIMessage(content='The simple interest for a principal of $1000 at a rate of 3.75% per year is $37.50.', additional_kwargs={}, response_metadata={'model': 'llama3.2:latest', 'created_at': '2025-07-27T13:30:14.10082019Z', 'done': True, 'done_reason': 'stop', 'total_duration': 3643709262, 'load_duration': 38767002, 'prompt_eval_count': 113, 'prompt_eval_duration': 776158602, 'eval_count': 28, 'eval_duration': 2825826280, 'message': Message(role='assistant', content='The simple interest for a principal of $1000 at a rate of 3.75% per year is $37.50.', images=None, tool_calls=None)}, id='run-afa79785-5860-4fb2-9a1f-3c081512afd2-0', usage_metadata={'input_tokens': 113, 'output_tokens': 28, 'total_tokens': 141}), ToolMessage(content='37.5', name='yearly_simple_interest', id='af34b371-8376-4ca1-818c-8131ad571a8f', tool_call_id='adf2ef3f-b006-49e3-8cbc-afe02235b64a'), AIMessage(content='', additional_kwargs={}, response_metadata={'model': 'llama3.2:latest', 'created_at': '2025-07-27T13:30:10.447072592Z', 'done': True, 'done_reason': 'stop', 'total_duration': 5206010519, 'load_duration': 22561315, 'prompt_eval_count': 247, 'prompt_eval_duration': 2285719932, 'eval_count': 28, 'eval_duration': 2896718013, 'message': Message(role='assistant', content='', images=None, tool_calls=None)}, id='run-2725f604-9b91-44b1-b67c-08ff62f97d28-0', tool_calls=[{'name': 'yearly_simple_interest', 'args': {'principal': 1000, 'rate': 3.75}, 'id': 'adf2ef3f-b006-49e3-8cbc-afe02235b64a', 'type': 'tool_call'}], usage_metadata={'input_tokens': 247, 'output_tokens': 28, 'total_tokens': 275}), HumanMessage(content='compute the simple interest for a principal of 1000 at rate 3.75 ?', additional_kwargs={}, response_metadata={}, id='d3b0c616-1b43-405e-87ed-facd7f52dd4b')]
INFO 2025-07-27 21:30:19,140 - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
INFO 2025-07-27 21:30:19,241 - Processing request of type CallToolRequest
INFO 2025-07-27 21:30:19,241 - Compound interest -> Principal: 1000.0, Rate: 4.0
INFO 2025-07-27 21:30:24,475 - HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"
INFO 2025-07-27 21:30:24,477 - [AIMessage(content='The compound interest for a principal of $1000 at an annual interest rate of 4.25% is approximately $40.00.', additional_kwargs={}, response_metadata={'model': 'llama3.2:latest', 'created_at': '2025-07-27T13:30:24.474433132Z', 'done': True, 'done_reason': 'stop', 'total_duration': 5227214693, 'load_duration': 29359248, 'prompt_eval_count': 113, 'prompt_eval_duration': 756218295, 'eval_count': 29, 'eval_duration': 4438660227, 'message': Message(role='assistant', content='The compound interest for a principal of $1000 at an annual interest rate of 4.25% is approximately $40.00.', images=None, tool_calls=None)}, id='run-4c8b4d63-09be-4895-9661-584846ae4040-0', usage_metadata={'input_tokens': 113, 'output_tokens': 29, 'total_tokens': 142}), ToolMessage(content='1040.0', name='yearly_compound_interest', id='c4632978-29f2-46c8-ab50-9cc88ebb5160', tool_call_id='b3f050c4-945e-4973-b4d6-d6f0487080f9'), AIMessage(content='', additional_kwargs={}, response_metadata={'model': 'llama3.2:latest', 'created_at': '2025-07-27T13:30:19.237296128Z', 'done': True, 'done_reason': 'stop', 'total_duration': 5130142439, 'load_duration': 32479260, 'prompt_eval_count': 247, 'prompt_eval_duration': 2262897687, 'eval_count': 27, 'eval_duration': 2833620362, 'message': Message(role='assistant', content='', images=None, tool_calls=None)}, id='run-36abb871-91b7-45ad-bd79-f19d58ecba08-0', tool_calls=[{'name': 'yearly_compound_interest', 'args': {'principal': 1000, 'rate': 4}, 'id': 'b3f050c4-945e-4973-b4d6-d6f0487080f9', 'type': 'tool_call'}], usage_metadata={'input_tokens': 247, 'output_tokens': 27, 'total_tokens': 274}), HumanMessage(content='compute the compound interest for a principal of 1000 at rate 4.25 ?', additional_kwargs={}, response_metadata={}, id='72f5955d-b372-435f-86ee-1f0203486569')]
参考资料
- https://langchain-ai.github.io/langgraph/concepts/mcp/
- https://modelcontextprotocol.io/overview