AI Agent智能体与MCP开发实践:基于Qwen3大模型 AI技术作家 AI应用开发专家王晓华新作【行情 报价 价格 评测】-京东
王晓华智能体开发入门书《AI Agent智能体与MCP开发实践:基于Qwen3大模型》全文试读~更新到12章_ai agent智能体与mcp开发实践王晓华电子版课本-CSDN博客
目录
[10.1 多种MCP连接协议详解](#10.1 多种MCP连接协议详解)
[10.1.1 stdio与SSE传输协议](#10.1.1 stdio与SSE传输协议)
[10.1.2 基于SSE传输协议的MCP服务端](#10.1.2 基于SSE传输协议的MCP服务端)
[10.1.3 可视化验证基于SSE协议的MCP服务](#10.1.3 可视化验证基于SSE协议的MCP服务)
[10.2 局域网MCP服务器的搭建与使用实战](#10.2 局域网MCP服务器的搭建与使用实战)
[10.2.1 局域网MCP服务端的搭建](#10.2.1 局域网MCP服务端的搭建)
[10.2.2 局域网MCP客户端连接MCP服务](#10.2.2 局域网MCP客户端连接MCP服务)
[10.3 基于腾讯云的MCP服务架设与使用](#10.3 基于腾讯云的MCP服务架设与使用)
[10.3.1 高效便捷的MCP云服务平台](#10.3.1 高效便捷的MCP云服务平台)
[10.3.2 腾讯云MCP服务部署代码的编写](#10.3.2 腾讯云MCP服务部署代码的编写)
[10.3.4 腾讯云的持久化服务的开启](#10.3.4 腾讯云的持久化服务的开启)
[10.4 本章小结](#10.4 本章小结)
在前面章节中,已详细讲解了MCP服务的单机搭建流程。在实际操作过程中,我们选用stdio来处理MCP模型。stdio作为一种便捷且实用的工具,能够以简易的方式实现单机MCP服务,帮助我们快速搭建起基础的单机服务环境。
然而,除了利用stdio搭建单机MCP服务外,我们还能通过搭建在线MCP服务,为更广泛的用户群体提供服务。具体而言,可借助SSE协议,在局域网内搭建MCP服务,满足局域网内用户的访问需求;同时,以同样的方法也可以将MCP服务成功部署到云端,实现服务的广泛覆盖。本章将深入介绍搭建在线MCP服务的方法。
10.1 多种MCP连接协议详解
在前期构建MCP服务的过程中,我们选用stdio来处理MCP模型。stdio协议主要适用于单机部署场景,为单机环境下的MCP服务搭建提供了支持。与之相对,SSE协议则是面向在线部署场景的利器。
本节首先聚焦于SSE协议,对它进行深入介绍,让读者了解其特性与优势;随后,将详细讲解在云上部署MCP服务的方法。通过这种部署方式,我们能够突破单机服务的限制,为更广泛的用户群体提供MCP服务,满足不同场景下的使用需求。
10.1.1 stdio与SSE传输协议
MCP的设计兼容了两种核心传输机制---标准输入/输出(stdio)与服务器发送事件(SSE),它们分别针对不同的应用场景和技术需求。
stdio传输通过标准输入/输出流实现通信,特别适用于本地集成和命令行工具,其本质是客户端与服务器在同一台机器上运行,通过子进程的方式建立直接连接。在这种机制下,客户端将MCP服务器作为子进程启动,通信过程通过进程的标准输入(stdio in)和标准输出(stdio out)进行,每条消息以换行符分隔并采用RPC格式编码,从而实现高效的进程间交互,如图10-1所示。
例如,当客户端向服务器的stdio in写入请求时,服务器处理后通过stdio out返回响应。这种模式无须依赖网络协议栈,显著降低了延迟和开销,同时避免了网络暴露带来的安全风险,尤其适合单客户端场景或安全敏感操作。
相比之下,SSE传输则面向基于网络的远程通信需求。它通过HTTP/HTTPS协议建立持久连接,允许服务器主动向客户端推送事件流,如图10-2所示。

图10-1 stdio传输流程

图10-2 SSE传输流程
具体说明如下:
- 客户端首先请求连接到服务器的SSE端点,随后服务器通过该通道持续发送事件更新。
- 客户端向服务器的请求则通过单独的HTTP POST端点完成,形成双向但非对称的通信模式。
可以看到,这种设计使SSE能够轻松穿透防火墙,兼容现有Web基础设施,同时支持多客户端同时接入中央服务器,适用于公共服务、跨网络访问或多用户协作的场景。
例如,集中式的数据库查询工具可通过SSE部署在远程服务器上,由多个用户通过HTTP协议访问,而无须在每台本地设备安装独立实例。
两种传输方式在模型部署上呈现显著差异。stdio的本地性决定了其部署必须与客户端绑定,服务器可执行文件需随客户端安装,更新时需逐个处理,资源消耗完全依赖本地硬件,但这也使其能够无缝集成本地系统资源(如文件系统或进程)。
反观SSE,其远程托管特性支持集中式部署,服务器只需在单一节点安装即可服务所有客户端,更新和维护可通过中心化操作即时生效,资源使用转向服务器端,但需额外配置网络安全策略以保障通信安全。
例如,本地文件搜索工具若采用stdio,则需与客户端共存于用户机器并直接访问本地数据;而基于SSE的同类工具则可能通过代理模式,在远程服务器上运行并通过网络传递结果。
在具体选择传输协议时,需要权衡多维因素:若追求极低延迟和简化部署,且场景局限于单机环境,则stdio更具优势;若需支持多客户端、远程访问或公共服务,则SSE更为合适。此外,混合架构也为复杂需求提供折中方案,例如通过stdio实现本地高速处理,同时借助SSE连接云端服务扩展功能。
总之,这两种传输机制的并存体现了MCP对灵活性的重视,既满足本地化工具的轻量化需求,又适应分布式系统的规模化挑战。
10.1.2 基于SSE传输协议的MCP服务端
本小节将完成基于SSE协议的MCP服务端。下面是一个简单的使用SSE协议实现的MCP服务:
from mcp.server import FastMCP
from datetime import datetime
设置的MCP Server的名称与端口号
mcp = FastMCP("GetCurrentTime", port=8000)
@mcp.tool()
def get_current_time():
"""
获取当前时间的函数,输出格式为{"time": YYYY-MM-DD HH:MM:SS}。
参数:
无
返回:
字典,包含当前时间的字符串表示。
"""
获取当前日期和时间
now = datetime.now()
将日期和时间格式化为字符串
formatted_time = now.strftime("%Y-%m-%d %H:%M:%S")
创建包含当前时间的字典
current_time = {"time": formatted_time}
return current_time
if name == "main":
print("Starting MCP server...")
mcp.run(transport='stdio')
mcp.run(transport='sse') # mcp dev main_sse.py
在上面代码中,采用了一个简单的获取服务器时间的示例来进行处理,并通过原有MCP服务完成代码的编写。
10.1.3 可视化验证基于SSE协议的MCP服务
前面我们使用原始mcp库完成了基础代码的编写,本小节将完成代码的验证服务。
- 可视化MCP验证端的安装
在具体流程上,首先需要安装Node.js和npm。可以从官方网站下载和安装Node.js,如图10-3所示。

图10-3 下载Node.js
下载Node.js安装文件后,双击运行并按安装向导提示完成Node.js的安装过程,如图10-4所示。npm则在安装Node.js过程中同时完成安装。

图10-4 安装Node.js
重启终端后,分别输入node -v和npm -v命令查看Node.js和npm的版本,出现版本信息即为安装成功,如图10-5所示。

图10-5 Node.js和npm安装成功
接下来,回到MCP服务的可视化验证过程,在终端输入以下代码:
mcp dev mcp++++ sse++++server.py
提示安装必要插件,如图10-6所示。

图10-6 安装MCP的必要插件
按回车键,等待后台处理完毕并提示启动,如图10-7所示。

图10-7 MCP客户端服务的启动
- 基于SSE协议的MCP服务启动
在进一步可视化验证MCP服务之前,还需要完成MCP服务的启动。在这里,我们直接运行10.1.2节中编写的简单MCP服务代码。
运行后,可以看到如下所示的提示信息:
Starting MCP server...
INFO: Started server process 17068
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
读者可以自行验证。
- 可视化MCP客户端的使用
在完成了MCP服务的启用与MCP验证端的启用之后,接下来就完成可视化MCP客户端的使用。读者在浏览器中可以打开如图10-8所示的网址。

图10-8 可视化MCP验证端地址
打开后的页面如图10-9所示。

图10-9 服务器端验证
读者需要在这个验证页面中填写Transport Type、URL,即选择对应的连接协议与URL,内容与图10-9一致。之后单击Connect按钮进行连接。
连接成功的页面如图10-10所示。

图10-10 验证端连接页面
在连接成功的页面中我们选择Tools标签,单击List Tools按钮列出所有可用工具,如图10-11所示。

图10-11 列出的工具名称与说明
之后在列出的工具函数名上单击,右侧出现工具测试按钮,如图10-12所示。

图10-12 工具测试按钮
最后单击右侧的Run Tool按钮进行工具的运行验证,如图10-13所示。

图10-13 工具测试结果
可以看到,工具正常运行并返回对应的结果与时间。
10.2 局域网MCP服务器的搭建与使用实战
上一节介绍了MCP的原始库的编写与部署方法,并通过实际编程完成了MCP工具的部署与使用。此外,我们还可以使用更专业的Python互联网服务库编写MCP服务,通过网络服务的形式为使用者提供服务。本节将完成基于网络的MCP服务器的搭建与使用。
10.2.1 局域网MCP服务端的搭建
我们通过MCP官方提供的配置可以完成MCP的服务器搭建,但对于新手来说,还需要了解和掌握服务器的配置,并对文件的命名与代码的编写有一定的要求。为了简易使用MCP在线服务器,我们可以使用现成的Python库来完成MCP服务器的搭建。首先需要安装两个库,打开终端输入如下命令:
pip install fastapi
pip install fastapi_mcp
fastapi与fastapi_mcp是用于通过网络对MCP服务提供支持的Python库。在安装完毕后,我们可以直接移植前面已经准备好的函数,完整的服务器代码如下:
from fastapi import FastAPI, HTTPException
from fastapi_mcp import FastApiMCP
from pydantic import BaseModel
from datetime import datetime
初始化FastAPI应用
app = FastAPI(title="AI计算服务", description="提供基础数学计算、时间查询和天气模拟功能")
数学运算端点
@app.get("/add", operation_id="add_numbers")
def add_numbers(a: int, b: int):
"""计算两个整数的和"""
return {"result": a + b}
@app.get("/multiply", operation_id="multiply_numbers")
def multiply_numbers(a: int, b: int):
"""计算两个整数的乘积"""
return {"result": a * b}
时间获取端点
@app.get("/datetime", operation_id="date_time")
def date_time():
"""获取当前系统时间"""
return {"datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
@app.post("/weather", operation_id="get_weather")
def get_weather(city_name: str):
"""获取指定城市天气信息"""
return {
"city": city_name,
"temperature": "23℃"
}
初始化MCP服务器
mcp = FastApiMCP(
app,
name="Math & Weather API",
description="提供数学运算和天气查询服务的MCP接口",
base_url="http://localhost:8000",
include_operations=[
"add_numbers",
"multiply_numbers",
"date_time",
"get_weather"
]
)
mcp.mount()
if name == "main":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
上面的代码比较简单,整体逻辑就是先定义服务器的名称与描述,之后将不同的工具函数进行注册并提供访问地址和端口,最后挂载和启动MCP服务器。直接运行上面代码,结果如图10-14所示。

图10-14 MCP服务器的启动
从运行结果可以看到,我们已经正常启动了MCP服务,接下来将完成客户端的编写。
10.2.2 局域网MCP客户端连接MCP服务
本小节将完成在线MCP服务的连接和使用。我们编写一个新的MCP客户端代码,使之可以完成获取MCP服务的功能,代码如下:
import asyncio
import json
import logging
from mcp.client.session import ClientSession
from mcp.client.sse import sse_client
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(name)
工具描述转换器
def transform_tools(tools):
tool_list = \[\]
for tool in tools:
parameters = {}
required = tool.inputSchema.get('required', \[\])
for name, prop in tool.inputSchema'properties'.items():
parametersname = {
'type': prop'type',
'description': prop.get('description', ''),
'required': name in required
}
tool_list.append({
'name': tool.name,
'description': tool.description,
'parameters': parameters
})
return json.dumps(tool_list, ensure_ascii=False, indent=2)
from openai import OpenAI
def ask_llm(question, tools_list):
TODO: 实现与LLM的交互逻辑
这里只是一个示例,实际应用中需要根据具体情况进行实现
system_prompt = tools_list + '\n 根据以上描述,用户要求:%s,请生成一个工具调用命令,要求以JSON格式输出{"tool":工具名,"tool_input":参数字典},只输出JSON,不要输出其他内容' % (
question)
client = OpenAI(
api_key="sk-17f687f6c5ac4647a9d9f649598a7cfe",
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
response = client.chat.completions.create(
model="qwen-plus",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": "Hello"},
],
max_tokens=1024,
temperature=0.99,
stream=False
)
generated_text = response.choices0.message.content # 提取文本内容
return generated_text, client # 返回文本而非response对象
def llm_Qwen3(question,client):
response = client.chat.completions.create(
model="qwen-plus",
messages=[
{"role": "user", "content": question},
],
max_tokens=1024,
temperature=0.99,
stream=False
)
generated_text = response.choices0.message.content # 提取文本内容
return generated_text
async def main(question = "25+38是多少?"):
async with sse_client("http://localhost:8000/mcp") as streams:
async with ClientSession(streams0, streams1) as session:
await session.initialize()
获取工具列表
tools = (await session.list_tools()).tools
s = transform_tools(tools) +"\n"
response, client = ask_llm(question, s)
清理Markdown标记
response = response.strip().replace('```json', '').replace('```', '').strip()
print(response)
mtools = json.loads(response) # 现在response是纯JSON字符串
print("mtools: --> ",mtools)
if 'tool' in mtools:
tool_name = mtools'tool'
tool_input = mtools'tool_input'
调用工具
print("调用工具:", tool_name, tool_input)
ret = await session.call_tool(tool_name, tool_input)
if ret:
try:
r = json.loads(ret.content0.text)
except:
r = ret.content0.text
print("工具返回结果:", r)
questions = f"用户的问题是{question},根据{tool_name}的返回结果为:{r},根据以上信息,回答问题。"
r = llm_Qwen3(questions,client)
return r
if name == "main":
questions = '计算一下356\*125', '25+38是多少?', '现在的时间是什么时候?', 'Shanghai天气怎么样?', '请给我讲一个笑话'
for question in questions:
response = asyncio.run(main(question))
print(response)
print("--------------------------------------------------------")
在上面代码中,我们主要修改了MCP连接地址,从而完成MCP工具的调用与结果获取。读者可以自行验证。
10.3 基于腾讯云的MCP服务架设与使用
上一节详细讲解了局域网MCP服务器的程序设计方法。通过精心设计与编写程序,我们实现了灵活的服务部署,既能在单机环境下模拟搭建MCP服务,满足本地开发、测试等需求,又能在局域网内架设MCP服务,方便局域网内的设备进行访问与交互,适用于企业内部协作、小型办公网络等场景。
不过,在实际应用中,仅在单机和局域网场景下部署MCP服务是远远不够的,我们有时还需要将MCP服务部署到互联网上。通过对外提供服务的形式架设MCP服务,使其能够被外部用户访问,从而拓展服务范围和应用场景,比如为不同地区的用户提供远程服务支持。
在网上架设服务器有多种途径。一种方式是个人自行提供硬件设备,并向相关服务器托管机构申请对应的IP地址和访问许可。但这种方式操作起来相对复杂,对个人技术能力和硬件资源要求也比较高。
相比之下,作为高效与高性价比结合的MCP云服务平台,腾讯云提供了丰富的服务器配置选项、稳定的网络环境和专业的技术支持,用户可以根据自身需求选择合适的服务器套餐,快速完成服务器的搭建与部署,无须过多关注硬件维护和网络配置等复杂问题,能够更加专注于MCP服务的开发与应用。
注意:为了免去购买云服务器的麻烦,读者可以在本地计算机上搭建Ubuntu 22.04 LTS虚拟机来学习本节内容,或者直接跳过本节内容,在需要部署云服务时再来学习一下。
10.3.1 高效便捷的MCP云服务平台
当我们使用MCP云服务平台时,首先需要登录云服务提供商的网站,购买相应的服务。操作起来十分便捷,只需打开腾讯云的官方在线地址,进入页面后,找到轻量应用服务器专区。
在这个专区里,腾讯云为用户提供了极具吸引力的选择。读者可以选择适合的轻量服务器,单击"立即购买"按钮后,会进入服务器购买页面,如图10-15所示。

图10-15 轻量服务器购买页面
在轻量服务器购买页面中,选择离我们较近的地域来部署服务器,系统镜像建议使用标准镜像Ubuntu 22.04 LTS,这也是比较常用的镜像。当然,读者也可以选择自己熟悉的其他版本的系统镜像。
购买完毕后我们会收到邮件通知,此时单击腾讯云首页右上角的"控制台"即可进入购买的云服务界面,如图10-16所示。

图10-16 腾讯云控制台页面
进入控制台之后,单击"轻量应用服务器"标签进入轻量服务器的控制面板,如图10-17所示。

图10-17 轻量服务器的控制面板
接下来单击"登录"按钮,可以进入我们购买的服务器操作界面,如图10-18所示。

图10-18 服务器操作界面
我们进入的是服务器操作界面,类似于Windows系统的终端。在这里可以直接使用命令行对它进行操作,例如直接使用pip安装对应的Python库。下一步就是单击左上方的SFTP按钮打开文件传输服务,如图10-19所示。

图10-19 文件存储与服务运行模块
在图10-19所示的界面左边,我们单击"上传"按钮上传文件,或者单击"新建文件夹"按钮创建一个新的文件夹。读者可以自行验证。
10.3.2 腾讯云MCP服务部署代码的编写
本小节将编写腾讯云MCP服务部署代码。首先,我们需要在腾讯云服务器中安装以下两个Python库,命令如下:
pip install fastmcp
pip install fastapi_mcp
之后,在本地计算机上编写可部署在腾讯云上的MCP服务代码,如下所示:
from fastmcp import FastMCP
from datetime import datetime
import math
初始化MCP服务器
mcp = FastMCP("MathWeatherAPI", host="0.0.0.0", port=929)
@mcp.tool()
def add_numbers(a: int, b: int):
"""计算两个整数的和"""
return {"result": a + b}
@mcp.tool()
def multiply_numbers(a: int, b: int):
"""计算两个整数的乘积"""
return {"result": a * b}
@mcp.tool()
def get_current_time():
"""获取当前系统时间"""
return {"datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
@mcp.tool()
def get_weather(city_name: str):
"""获取指定城市天气信息"""
return {
"city": city_name,
"temperature": "23℃"
}
if name == "main":
mcp.run(transport="sse")
我们将上面的代码整体上传到腾讯云服务器,可以直接放在根目录root下,也可以创建一个新的文件夹"mcp_server"用于分类存放。这里选择存放在新创建的文件夹mcp_server下,如图10-20所示。

图10-20 上传MCP服务源码
上传完毕后,我们可以在右侧终端直接运行python3 mcp_servers/weather_mcp.py命令,注意命令中的脚本文件地址要从根目录开始并符合我们放置程序的位置,如图10-21所示。

图10-21 放置程序并启动MCP服务
10.3.3 腾讯云端口的开启以及在线MCP服务的验证
在验证我们编写的在线MCP服务之前,还需要打开特定的腾讯云服务端口。回到轻量级服务器管理页面,我们首先记录对应的IPv4地址,之后单击右侧的三个点并在弹出菜单中单击"查看详情"菜单项,如图10-22所示。

图10-22 单击"查看详情"菜单项
在服务器的详情页面中单击"防火墙"标签,如图10-23所示。

图10-23 进入防火墙界面
之后单击"添加规则"按钮,填入我们设定的端口号,如图10-24所示。

图10-24 打开防火墙端口号
MCP启动状态的提示信息如图10-25所示。

图10-25 MCP服务启动状态
使用npx命令打开本地的MCP调试接口,命令行如下:
npx @modelcontextprotocol/inspector
启动本地的MCP远程接口,如图10-26所示。

图10-26 inspector启动
我们使用浏览器打开对应的地址,在页面上单击List Tools按钮后,将展示所有的函数。我们以get_weather工具为例查询一下上海的天气信息,结果如图10-27所示。

图10-27 查验在线MCP工具内容
读者可以自行验证。
10.3.4 腾讯云的持久化服务的开启
在前面小节中,我们完成了MCP服务在腾讯云上的部署以及验证,读者已经掌握了基本的MCP部署方法。但是,这些部署与验证,全部都是我们手动完成的,而对于在线服务的部署,还需要额外进行托管。
我们只需要单击腾讯云服务器创建的远程托管服务,如图10-28所示。

图10-28 进入远程托管界面
新建托管会话后,可以自动对服务器进行托管。具体与基本终端操作一致,读者可以自行研究一下。
10.4 本章小结
在本章中,我们深入探讨了基于云上环境的MCP服务的连接与使用方法。同时,借助原生的可视化验证服务对代码展开了测试工作。令人欣喜的是,仅通过简捷的可视化操作,我们便成功验证了前期精心编写的简易MCP服务。
此外,我们顺利完成了基于Python语言的自定义在线MCP客户端的编写及使用。这一系列连贯且完整的操作流程,为我们深入理解MCP服务的基本使用流程与方法提供了强大的助力。
