ESP32 之 小智 AI 接入MCP 实战全指南
文章目录
一、什么是MCP
MCP 是什么?
MCP(Model Context Protocol,模型上下文协议)是一个由 Anthropic 发起的开源标准,用于将 AI 应用连接到外部系统
通过 MCP,AI 应用(例如小智 AI、ChatGPT 等)可以访问数据源(如本地文件、数据库)、工具(如搜索引擎、计算器)以及工作流(如专用的提示模板)等资源
可以形象地把 MCP 比作 AI 应用的“USB-C 接口”:就像 USB-C 提供统一标准让电子设备连接外围设备一样,MCP 为 AI 与外部系统的连接提供了一种标准化方式
基于 MCP,AI 模型不再是封闭的黑箱,而是能够通过标准协议与外界交互
MCP 协议采用客户端-服务器架构:AI 应用本身充当 MCP 主机(Host),在其内部运行一个或多个 MCP 客户端(Client)实例,每个客户端与一个 MCP 服务器(Server)建立一对一连接
MCP 服务器是提供具体功能或数据的程序,可以在本地运行(通过标准输入/输出通信)或远程运行(通过 HTTP/SSE 通信)
通过这种架构,MCP 主机可同时对接多个 MCP 服务器,从而集成多种工具和数据源
例如小智 AI 可以同时连接“文件系统MCP服务器”“数据库MCP服务器”等,实现对多种资源的访问
MCP 能做什么?
借助 MCP,AI 能力边界得以大幅拓展。MCP 为 AI 提供访问外界的标准接口,让 AI 模型可以“长出触手”去执行各种任务。例如一些实际场景包括:
-
个人助理:MCP 让聊天机器人访问你的日历、待办应用等,成为真正懂你的个人助理
-
自动编码:通过 MCP,AI 可以调用设计工具(如 Figma)接口,自动生成 Web 应用
-
企业数据分析:企业部署 MCP 服务器连接内部多个数据库,员工可通过对话式AI直接查询和分析数据
-
硬件设备控制:如果实现一个智能家居控制类的 MCP 服务器,小智 AI 就能化身家庭管家,通过 MCP 控制家中的灯光、电器开关等设备。再比如打造一个机器人控制 MCP,小智则可以下达运动指令,让机器人执行复杂动作。
MCP 协议的应用既可以是设备端控制,也可以是云端服务扩展
例如上图所示,小智 AI 利用 MCP 控制物联网设备(ESP32 微控板,实现对音频、灯光、传感器、马达等硬件的控制)和对接云端服务(如调用智能家居平台、知识库搜索、收发邮件、电脑操作等)[10]
这一切的背后,MCP 充当了标准化的“外接神经”,使AI模型能够以安全、受控的方式对现实世界产生影响[11]
简单来说凡是可以编程实现的功能,都有望通过 MCP 让 AI 来调用
这赋予了 AI 前所未有的扩展性和想象空间。
二、小智开源端接入 MCP
小智 AI 有社区开发的开源版本的服务端(xiaozhi-esp32-server 项目),开发者可以在本地部署并为其接入 MCP 工具。
下面将介绍开源端集成 MCP 的前提条件、配置步骤、代码结构,以及常见问题的排查。
前置条件
在开始之前,请确保准备好以下开发环境:
-
Python 3.8+:建议使用 Python 3.8 或以上版本作为运行 MCP 服务端的基础[12]。
-
可以使用 Anaconda 或 Python 自带的 venv 创建隔离环境以管理依赖。
-
MCP Python SDK:安装 MCP 官方提供的 Python SDK(如 pip install mcp)。
-
建议使用最新版本以获得最新特性(>=1.2.0)[12]。该 SDK 内置了 FastMCP 等工具类,方便快速开发 MCP 服务器。
-
其他依赖:根据具体工具功能,可能需要额外的第三方库。
-
例如本指南示例的“天气查询”工具将用到 httpx 异步HTTP库调用天气API,以及 pydantic 用于模型和数据验证[14]。在开始编码前,请根据项目说明安装好所需依赖库。
确认上述环境配置无误后,便可进行 MCP 接入的实际操作
接入流程
开源版小智服务端(这里以华南理工大学的开源版小智AI为例)接入 MCP 的流程可以分为三个主要步骤:
第一步:部署 MCP 接入点服务。开原版的小智AI服务端并没有集成mcp的接入点服务,而是需要自己额外运行一个mcp接入点,具体方法可以查看:https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/mcp-endpoint-enable.md
第二步:配置小智服务端连接 MCP 接入点。当 MCP 接入点服务成功运行后,需要让小智服务端知道它的存在。打开小智服务端的配置文件,将 MCP 接入点的信息填入。其中关键是一个访问令牌(Token)和服务 URL。开源版有两种部署模式:
-
如果是单模块部署(只运行了 xiaozhi-server 而无“智控台”前端),请打开 data/.config.yaml 配置文件,在其中找到 mcp_endpoint 字段,把第一步启动 MCP 服务时控制台打印出的 token 填入配置[18]。保存配置后,重启 xiaozhi-server。
-
如果使用的是全模块部署(包括智控台网页管理界面),则需要登录智控台。在顶部菜单选择“模型配置”,左侧选择“大语言模型”,找到小智对应的模型配置项,填入第一步获取的 Token 并保存。然后在服务端配置中启用该 MCP 接入点。完成配置后,重启小智服务端。
具体的接入流程可以参考文档:https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/mcp-endpoint-enable.md
第三步:部署并运行 MCP 工具服务。
MCP 接入点本身并不包含具体的工具逻辑,它更像一个中转站。我们需要自定义开发 MCP 工具服务器,然后让其通过接入点与小智交互。
在第四节我们会手把手教学如何编写一个mcp工具,在这里就不赘述了
三、小智官网版接入 MCP
获取 MCP 接入点
登录 xiaozhi.me 的控制台,进入智能体的配置角色页面,右下角可以看到该智能体专属的 MCP 接入点。
四、手把手写一个 MCP
下面我们将从零开始,开发一个简单的 MCP 工具服务,让小智 AI 学会一种新本领
这个过程将涵盖项目结构规划、代码编写、注册测试等环节
即使你的编程经验不丰富,也可按照步骤一步步完成,本次mcp工具服务的编写将基于小智官方的mcp简易项目进行,项目链接
打开链接后,可以找到页面中一个绿色的按钮,写着Code的按钮,点开它,然后你就看到Download ZIP的按钮。
点击它,下载本项目源码压缩包。下载到你电脑后,解压它,此时它的名字可能叫mcp-calculatorr-main
你需要把它重命名成mcp-calculator。
接下来我们用命令行进入项目目录即安装依赖
# 进入项目目录
cd mcp-calculator
conda remove -n mcp-calculator --all -y
conda create -n mcp-calculator python=3.10 -y
conda activate mcp-calculator
pip install -r requirements.txt
我们首先分析 mcp-calculator 示例项目的结构,了解关键文件及其作用。
这将帮助我们搭建自己的 MCP 工具服务。
-
**mcp_pipe.py**:主通信管道脚本,用于处理与小智服务器的 WebSocket 连接以及工具进程的启动管理。它会建立本地工具进程和小智 AI 服务端之间的通道,实现标准输入输出与 WebSocket 数据流的相互转发。
-
通过 mcp_pipe.py,我们的工具可以与小智 AI 双向通信,发送工具可用的工具信息并接收调用请求,再将执行结果返回给小智。
-
**calculator.py**:示例 MCP 工具实现文件,用于数学计算。
-
它定义了一个简单的计算工具(接收一个 Python 表达式字符串并返回计算结果),演示如何使用 FastMCP 库注册工具函数、描述功能并启动服务。
-
calculator.py 中通过装饰器 @mcp.tool() 将函数暴露为工具,并使用 mcp.run() 启动 MCP 服务。我们会参考其结构,开发自己的天气查询工具。
-
**mcp_config.json**:JSON 配置文件,用于定义可启动的 MCP 服务列表。通过这个配置,我们可以集中管理多个 MCP 工具服务。
-
例如示例中配置了一个本地 STDIO 工具(calculator)和两个远程服务接口(SSE 和 HTTP)供参考。
-
运行 mcp_pipe.py 时不带参数将按照此文件批量启动所有启用的工具服务,并跳过标记了 "disabled": true 的条目。这一机制方便我们同时注册、管理多个工具。
小结:上述结构体现了一个 MCP 工具服务 的标准组成:一个通信管道 (mcp_pipe.py),若干工具实现代码(如 calculator.py),以及可选的配置文件 (mcp_config.json) 用于批量管理服务。
理解这些模块的作用后,我们就能依葫芦画瓢构建自己的 MCP 工具。
接下来,我们将基于上述模板构建一个“天气查询”MCP 工具,演示从零开始的开发过程。
目标是让小智 AI 能调用我们编写的工具,查询指定城市的当前天气信息。
创建 MCP 服务实例
首先,新建一个 Python 脚本文件,例如 weather.py。在文件开头,我们导入 FastMCP 库并创建一个 MCP 服务实例,传入工具服务的名称,例如 "Weather"。这个名称用于标识整个工具服务,在工具列表中会作为服务器名称显示。例如:
from fastmcp import FastMCP
# 创建一个名为 "Weather" 的 MCP 服务实例
mcp = FastMCP("Weather")
我们的 MCP 服务对象 mcp 已初始化
FastMCP 会利用提供的名称构建工具
注意事项
-
MCP里工具的名字和参数的命名一定要清晰的让大模型知道它的作用,尽量不要用缩写,同时提供一段注释来说明工具的作用以及在何时使用。例如calculator让大模型知道它是个计算器,参数python_expression是要求大模型输入一个Python表达式。如果你要写一个bing_search工具,那么它的参数名应该是keywords。
-
函数内的文档注释(使用"""..."""引用的部分)引导大模型何时使用该工具,同时提及了可以在表达式中使用math和random两个库里的函数,这两个库我们已经在前面的代码中import进来了。
-
由于本示例项目中MCP Server中的标准输入输出被用来做数据传输,所以无法使用print来打印信息,改为通过logger来输出调试信息。
-
MCP的返回值通常是一个字符串或者JSON,示例中把计算结果放在一个JSON的result字段里进行返回。返回值的长度通常是有限制的,跟设备上的IoT指令一样,通常限制在1024字节内。
实现工具函数并注册
接下来,我们编写具体的工具功能函数
例如定义一个函数 get_weather(city: str) -> str,接受城市名称作为参数,返回该城市当前天气的描述信息
为了将此函数注册为 MCP 工具,我们使用 @mcp.tool() 装饰器来装饰它
FastMCP 框架通过装饰器自动收集工具函数的信息。
天气api的注册及API key获取方法
为了能够使用Python代码获得实时的天气情况,我们这里需要用到心知天气的的API:
- 打开心知天气https://www.seniverse.com/的官网,注册登录并点击控制台:
- 在控制台左侧产品管理栏中点击添加产品
- 申请免费版的API,点击左侧免费版,就可以看到API私钥了:
- 利用python requests库调用API获得天气情况(免费版的只能得到天气现象、天气现象代码和气温 3项数据)
下面是 weather.py 中工具函数的示例代码:
import json
import logging
from fastmcp import FastMCP
import requests
# 创建一个名为 "Weather" 的 MCP 服务实例
mcp = FastMCP("Weather")
# 请提前安装requests sdk: pip install requests
url = "https://api.seniverse.com/v3/weather/now.json"
@mcp.tool()
def get_weather(city):
"输入城市名称,获取该城市的天气情况"
params = {
"key": "xx", # 填写你的私钥
"location": city, # 你要查询的地区可以用代号,拼音或者汉字,文档在官方下载,这里举例北京
"language": "zh-Hans", # 中文简体
"unit": "c", # 获取气温
}
response = requests.get(url, params=params) # 发送get请求
temperature = response.json()['results'][0]['now'] # 接受消息中的json部分
logging.info(f"Temperature: {temperature}")
return temperature
# Start the server
if __name__ == "__main__":
mcp.run(transport="stdio")
上述代码要点如下:
-
通过 @mcp.tool() 将 get_weather 函数注册为 MCP 工具,使其对小智 AI 可见glama.ai。装饰器会将函数名称、参数类型和文档字符串等信息收集,稍后用于生成工具的元数据。
-
函数签名采用了类型标注 city: str -> dict 来明确输入参数类型和返回类型(这里选择返回一个包含天气和温度的字典)。这些类型信息将进入工具描述,用于约束小智传递的参数和预期结果格式
-
函数内部通过调用第三方天气 API 获取实时天气数据(实际开发中需替换为有效的 API 和密钥)。
-
根据 API 返回的数据结构,我们提取所需的信息(例如温度和天气状况)。
通过以上实现,我们的 get_weather 工具函数已经就绪并注册在 MCP 服务中了。同理我们还可以继续定义其他工具函数。例如,可以新增一个查询空气质量的工具:
@mcp.tool()
def get_air_quality(city: str) -> str:"""查询指定城市的当前空气质量指数 (AQI)。"""
# ...(与天气类似,调用相应API获取AQI数据并返回)...
像这样添加多项工具完全被 FastMCP 支持——只需用相同的装饰器注册多个函数即可,无需额外复杂操作。这一特性允许我们在一个 MCP 服务中并行注册多个工具(如同时支持天气和空气质量查询),提升扩展性。
通过 MCP 接入点接入小智 AI
实现 MCP 工具服务后,我们需要让小智 AI 知道它的存在
这一步通过 MCP 接入点来完成。MCP 接入点可以理解为小智服务端为我们提供的一个连接入口(通常是一个 WebSocket 地址),我们要让 mcp_pipe.py 去连接这个地址。
如何获取 Endpoint 地址:开源版参考第二节,官方参考第三节如何获得mcp接入点。拿到 Endpoint 后,在运行 mcp_pipe.py 前需要设置环境变量 MCP_ENDPOINT 为此地址,在本文提供的mcp示例中,基于官方版本进行改造,改成使用**.env文件读取MCP_ENDPOINT** 配置文件,只需要在**.env文件中,设置MCP_ENDPOINT=xx**即可。
然后有两种方式连接我们的工具服务:
-
方式一:直接运行单个工具脚本 – 在终端执行 python mcp_pipe.py weather.py。这会启动 mcp_pipe.py 并根据参数加载我们刚编写的 weather.py 工具。mcp_pipe.py 会作为客户端连接到小智 MCP服务器(通过 MCP_ENDPOINT),成功后启动 weather.py 进程,并将其STDIO管道接入 WebSocket。控制台上应能看到日志输出诸如“Connecting to WebSocket server... Successfully connected... Started server process: python weather.py”等glama.ai。
-
方式二:使用配置文件批量运行 – 将我们的工具加入 mcp_config.json 的 "mcpServers" 列表,然后直接执行 python mcp_pipe.py(不加参数)以启动所有配置的服务。例如,可以在 "mcpServers" 中新增一项:
"weather": {
"type": "stdio",
"command": "python",
"args": ["-m", "weather"]
}
确保 "weather" 条目未设置 "disabled" 或将其置为 false。然后运行管道脚本,它会读取配置并并行启动 "weather" 服务(以及其他已配置且未禁用的服务)。这一机制允许我们同时接入多个 MCP 工具。
例如既可以在配置中保留示例的 "local-stdio-calculator",又添加新的 "weather" 服务,那么执行一次命令即可启动计算器和天气查询两个工具,二者会分别通过各自子进程连接到小智.
无论采用哪种方式,成功连接后我们都可以在小智 AI 侧验证工具是否注册成功,参考下图操作方式,既可以获取mcp的接入点,也可测试mcp可用服务。
点击刷新接入点状态,可以看到mcp在线情况和启用的服务。这里我们使用python mcp_pipe.py启动全部工具,可以看到我们刚才写的获取天气工具和项目示例里的计算器工具
至此,我们的“天气查询” MCP 工具开发完毕。从创建服务、注册工具函数到启动监听,一共不到百行代码且结构清晰。这归功于 FastMCP 框架高度封装了协议细节,使开发者只需关注工具的业务逻辑,其它诸如消息格式、线程管理等均自动处理。
进阶扩展1:添加多个工具(如空气质量查询、天气趋势预测)
天气查询 MCP 可以有很多扩展方向。通过 MCP,一个服务器可以同时提供多个工具。我们已经提供了警报和预报两个工具,完全可以再加入更多:
-
空气质量查询:可新增一个 get_air_quality(city: str) 工具,调用类似 AQI 的API获取指定城市的空气质量指数,返回当前空气质量等级。这样,当用户问空气质量时,小智可以调用该工具。
-
天气趋势预测:在 get_forecast 基础上,再添加一个 get_weekly_trend(latitude, longitude),获取更长时间范围(比如一周)的预报数据,并计算整体趋势(比如本周降温还是升温)。这样用户问“这一周气温趋势如何”时,模型就能选择此工具。
-
多数据源整合:我们还可以整合其他天气服务的数据,例如紫外线指数、降雨概率等,作为不同的工具。MCP 服务器端可以同时注册这些工具,小智会各取所需。
当增加了新工具后,不要忘记:更新代码并重启 MCP 服务。小智获取到新工具后,就能够在对话中使用它们。确保为每个工具编写清晰的注释和描述和以及适当的 name,让模型可以正确识别用途并调用。
进阶拓展2:支持多工具的并行注册与调用
在实际应用中,我们往往希望扩展小智 AI 的不止一种能力。
MCP 协议和 FastMCP 框架天然支持同时注册和使用多个工具。实现多工具支持有两种常见方式:
方式一:单进程注册多个工具函数。正如前文所述,我们可以在一个脚本中用多个 @mcp.tool() 装饰不同的函数。例如在 weather.py 中同时定义 get_weather 和 get_air_quality 两个工具函数。
启动服务后,这两个工具会一起通过 Manifest 广告给小智 AI。模型在对话中既可以调用天气查询,也可以调用空气质量查询——两个工具共享同一个 MCP Endpoint 连接,由 FastMCP 自动区分名称路由到相应函数。这种方式的优点是实现简单、维护方便,而且由于共用一个进程,管理开销较小。
方式二:多进程分别注册不同工具。我们也可以选择将不同工具放在独立的脚本/服务中,通过配置文件同时运行。例如编写 weather.py 提供天气工具,另写一个 air_quality.py 提供空气质量工具。
在 mcp_config.json 中配置两个服务条目分别启动它们,然后让 mcp_pipe.py 同时管理这两个子进程连接到小智。
这样做的好处是工具彼此隔离,互不影响;某个工具崩溃重启时不影响其他工具的可用性。
不同工具可以用不同开发语言或依赖环境,各自独立部署(甚至一部分用HTTP远程提供,一部分本地STDIO提供)。
无论哪种方式,小智 AI 最终都会在工具列表中看到多个可用工具,并且可以并行或按需地调用它们。
例如我们同时提供了“查询天气”和“查询空气质量”两项服务,那么当用户问“北京今天空气质量怎么样?”,模型会选择调用 get_air_quality 工具;问“北京天气如何?”则调用 get_weather 工具。
如果用户提出复合问题(比如“两者都问”),模型甚至可能先后调用两个工具,再综合结果回答。这都在 MCP 协议的能力范围之内。
FastMCP 和 mcp_pipe 也为并行调用做了准备:mcp_pipe采用了 asyncio 协程同时维护多连接,且每个工具调用在服务器侧也是线程池中独立执行。因此,多工具情况下系统依然能够高效地同时处理多个请求。
开发者在实现多工具时需要注意避免工具名称冲突(每个工具函数应有唯一名称标识)并确保合理分配系统资源。如果工具众多,建议利用 mcp_config.json 配置来有选择地启用/停用部分工具服务(通过 "disabled": true 开关),根据需要动态调整接入的小智能力范围。














