python
from langchain_core.messages import HumanMessage
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langchain_mcp_adapters.tools import load_mcp_tools
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_openai import ChatOpenAI
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.prebuilt import ToolNode
import asyncio
import os
from dotenv import load_dotenv
'''
执行脚本时需要确定api_key是否有效
'''
load_dotenv("../.env")
api_key = os.getenv("API_KEY")
# 定义状态
class MyState(TypedDict):
messages: Annotated[list, add_messages]
# 定义 agent 结点
def agent(state: MyState) -> MyState:
return {"messages": [model.invoke(state["messages"])]}
# LLM 是否调用工具
def is_call_tools(state: MyState) -> bool:
last_message = state["messages"][-1]
if last_message.tool_calls:
return True
return False
# 定义 mcp server 参数
mcp_server_param = [
StdioServerParameters(
command="npx",
args=["@playwright/mcp@latest"],
env=None
)
]
# 声明模型
model = ChatOpenAI(
model_name="Qwen3-Coder-Plus", # deepseek-chat
openai_api_key=api_key, # 填写 api-key
openai_api_base="https://apis.iflow.cn/v1" # 填写 base-url,https://api.deepseek.com
)
async def main():
try:
async with stdio_client(mcp_server_param[0]) as (read, write):
async with ClientSession(read, write) as session:
# 绑定工具
await session.initialize()
tools = await load_mcp_tools(session)
print("tools:", [tool.name for tool in tools])
global model
model = model.bind_tools(tools)
# 定义图结构
workflow = StateGraph(MyState)
workflow.add_node("agent", agent)
workflow.add_node("tools", ToolNode(tools=tools))
workflow.add_edge(START, "agent")
workflow.add_conditional_edges("agent", is_call_tools, {
True: "tools",
False: END
})
workflow.add_edge("tools", "agent")
# 构建图
graph = workflow.compile()
# 调用图
baidu_state = await graph.ainvoke({"messages": [HumanMessage("打开百度首页,然后搜索ai agent")]})
print("Baidu result:", baidu_state['messages'][-1].content)
except Exception as e:
print(f"Error occurred: {e}")
# Handle the exception gracefully
if __name__ == '__main__':
asyncio.run(main())
说明: 执行脚本时若打开浏览器即关闭,出现 Error occurred: unhandled errors in a TaskGroup (1 sub-exception),则执行pip install playwright即可解决