如何让大模型自主调用MCP服务

38 阅读4分钟

如何让大模型自主调用MCP服务

【AI大模型教程】

在基于大模型(LLM)的应用开发中,我们希望模型不仅能回答问题,还能够调用一些外部服务用以完成更复杂的任务,例如:操作本地的数据库、调用API接口、运行脚本等,那么如何让大模型能够自主调用对应的外部服务呢?


MCP(Model Context Protocol)正是为此而生的标准协议,它让大模型通过统一的方式调用外部服务。

本文将通过一个完整示例,演示如何让大模型调用外部服务,具体场景是:让大模型通过用户的输入自主判断是否调用MySQL MCP服务并执行SQL、返回结果。

  1. 环境准备

准备Python环境:

python 3.10+

安装必要依赖:

pip install pymysql fastmcp langchain langchain-openai langgraph langchain-mcp-adapters
  1. 准备MCP服务

mysql_mcp.py 文件代码为:

import pymysql
from fastmcp import FastMCP
import json
# 初始化 MCP 服务
app = FastMCP("MySQL MCP")
# 数据库连接配置
DB_CONFIG = {
"host": "127.0.0.1",
"user": "root",
"port": 3308,
"password": "123456",
"database": "test_db",
"charset": "utf8mb4",
"cursorclass": pymysql.cursors.DictCursor
}
def run_query(sql: str):
"""执行 SQL 并返回结果"""
conn = pymysql.connect(**DB_CONFIG)
try:
with conn.cursor() as cursor:
cursor.execute(sql)
if sql.strip().lower().startswith("select"):
rows = cursor.fetchall()
# 统一转为字符串
return {"rows": json.loads(json.dumps(rows, default=str))}
else:
conn.commit()
return {
"status": "success",
"rows_affected": cursor.rowcount
}
finally:
conn.close()
# 定义工具
@app.tool()
def query_mysql(sql: str) -> dict:
"""
执行 MySQL 查询语句
参数:
sql: 要执行的 SQL 语句 (SELECT / INSERT / UPDATE / DELETE)
"""
try:
return run_query(sql)
except Exception as e:
return {"error": str(e)}
if __name__ == "__main__":
app.run(transport="stdio")

注意:本地的MySQL需要能够连接、需要有test_db库,需要有users表,表数据为:

  1. 大模型调用MySQL MCP服务的代码

test_mcp.py

import asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
import os
# 大模型请求地址
BASE_URL = "https://api.openai.com/v1/"
# key
API_KEY = "sk-xxx-your-key"
# 模型名称
MODEL_NAME = "gpt-4o"
async def main():
try:
# 初始化MCP客户端 stdio 方式
client = MultiServerMCPClient({
"MySQL-MCP": {
"command": "python",
"args": [os.path.abspath("mysql_mcp.py")],   # 注意mcp的路径
"transport": "stdio"
}
# 其它MCP
})
# 获取工具
tools = await client.get_tools()
if not tools:
raise ValueError("未获取到任何工具")
# 初始化一个 ChatOpenAI 实例,用于与大模型交互
llm = ChatOpenAI(
base_url=BASE_URL,
openai_api_key=API_KEY,
model=MODEL_NAME,
timeout=60.0,
max_retries=2
)
# 创建agent
agent = create_react_agent(llm, tools)
while True:
user_input = input("\n 请输入需求(或输入 exit 退出):\n> ")
if user_input.strip().lower() == "exit":
break
async for chunk in agent.astream({"messages": user_input}):
print(chunk)
except Exception as e:
print(f"程序初始化失败: {e}")
if __name__ == "__main__":
asyncio.run(main())

代码解析

  • MultiServerMCPClient 初始化
  • 配置MCP服务,指定启动命令(如:python mysql_mcp.py)、参数和通信方式(这里是 stdio)。
  • 可以同时接入多个MCP服务(如:MySQL、Redis、Web API等等)。
  • 获取工具(get_tools)
  • MCP会返回一个工具清单(类似API描述),大模型就知道能调用什么方法。
  • ChatOpenAI初始化
  • 通过ChatOpenAI封装大模型调用,配置base_url、API Key、模型名称、超时和重试机制。
  • 创建ReAct Agent
  • 使用create_react_agent,让大模型采用Reason + Act的模式:
  • 先思考该做什么(Reason),

  • 再调用MCP工具(Act),

  • 最后输出结果。

  1. 实际运行效果

先来个计算题:“ 89+2等于几?”

可以看到大模型自己已经判断不需要调用Msyql MCP服务,那么我们再来个查询:“帮我查询users表有哪些数据”

再来个查询:“帮我查询users表中年龄最小的是谁?”

再来个创建数据表:“帮我创建一个book表并写入一些数据”

生成的book表

生成的表数据

注意:本MySQL MCP服务仅仅用于学习,用于生产环境一定要做好sql执行限制,防止不可逆操作造成损失。

总结

通过以上示例,我们完成了一个**大模型+**MCP****的闭环调用。核心思路是:

  • MCP提供工具能力(如:执行SQL)

  • 大模型通过LangGraph的Agent机制选择合适工具

  • 结果自然返回给用户

有了MCP,大模型不仅能“告诉你”,还可以“帮你做”。

知识扩展

我们看下MultiServerMCPClient类

除了stdio方式还可以使用streamable_http方式请求MCP,新版本已经不再建议使用SSE方式。