一个为 AI 设计的串口调试 MCP (Model Context Protocol) 服务器,让 AI 助手能够直接发现、连接、采集和查询串口设备数据。
- 🔌 串口管理:发现可用串口、连接/断开设备
- 📊 数据采集:后台实时读取数据到环形缓冲区(最大10000条)
- 🔍 智能查询:按时间窗口查询,支持自动降采样
- 📤 命令交互:发送控制命令并读取设备响应
- 🛠️ 调试工具:数据注入、原始数据查看等辅助功能
- 📝 标准格式:YAML元数据 + CSV数据的标准输出格式
- Python >= 3.10
- UV 包管理器(推荐)或 pip
# 克隆仓库
git clone <repository-url>
cd serial_debug_mcp
# 使用 UV 创建虚拟环境并安装依赖
uv venv --python 3.10
uv pip install fastmcp pyserial
# 运行 MCP 服务器
uv run main.py# 创建虚拟环境
python -m venv .venv
source .venv/bin/activate # Linux/Mac
# 或 .venv\Scripts\activate # Windows
# 安装依赖
pip install fastmcp pyserial
# 运行
python main.py本 MCP 服务器支持两种传输模式,适用于不同的 AI 客户端:
适用场景: OpenCode、Claude Desktop 等本地工具 特点: 通过进程间通信,无网络端口 默认: 是
# 启动(默认模式)
uv run main.py
# 或明确指定
uv run main.py --stdioOpenCode 配置:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"serial_debug": {
"type": "local",
"command": ["uv", "run", "main.py"],
"enabled": true
}
}
}适用场景: VSCode、浏览器扩展、HTTP API 调用 特点: HTTP 服务,支持多客户端同时连接
# 启动 SSE 服务(默认端口 8000)
uv run main.py --sse
# 使用自定义端口(例如 15932)
uv run main.py --sse 15932启动后输出:
Starting MCP server in SSE mode...
Server: http://127.0.0.1:8000/sse
Health: http://127.0.0.1:8000/health
Docs: http://127.0.0.1:8000/docs
Use this URL in MCP clients:
http://127.0.0.1:8000/sse
VSCode 配置:
{
"servers": {
"serial_debug": {
"type": "sse",
"url": "http://127.0.0.1:8000/sse"
}
},
"inputs": []
}OpenCode 配置(SSE 模式):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"serial_debug": {
"type": "sse",
"url": "http://127.0.0.1:8000/sse"
}
}
}| 特性 | stdio 模式 | SSE 模式 |
|---|---|---|
| 启动方式 | uv run main.py |
uv run main.py --sse [port] |
| 配置类型 | type: "local" |
type: "sse" |
| 通信方式 | 标准输入输出 | HTTP SSE |
| 端口 | 无 | 8000(可自定义) |
| 多客户端 | 不支持 | 支持 |
| 适用工具 | OpenCode、Claude Desktop | VSCode、Web 工具 |
- OpenCode 用户:推荐使用 stdio 模式,配置简单
- VSCode 用户:使用 SSE 模式,先启动服务器再配置 URL
- 需要多工具共享:使用 SSE 模式,可同时连接多个 AI 客户端
| 工具 | 描述 | 返回值 |
|---|---|---|
list_ports |
列出所有可用串口 | JSON 数组 |
open_port |
打开指定串口 | 成功消息或错误 |
close_port |
关闭当前串口 | 成功消息或错误 |
open_port 参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
port |
string | 是 | - | 串口名称,如 "COM3" |
baudrate |
int | 否 | 115200 | 波特率 |
bytesize |
int | 否 | 8 | 数据位 (5/6/7/8) |
parity |
string | 否 | "N" | 校验位 (N/E/O) |
stopbits |
float | 否 | 1 | 停止位 (1/1.5/2) |
timeout |
float | 否 | 1 | 读超时(秒) |
| 工具 | 描述 | 返回值 |
|---|---|---|
start_capture |
开始后台采集数据到缓冲区 | "Capture started" 或错误 |
stop_capture |
停止采集(保留缓冲数据) | "Capture stopped" 或错误 |
clear_data |
清空缓冲区所有数据 | "Clear data success" |
| 工具 | 描述 | 返回值 |
|---|---|---|
query_data |
按时间窗口查询缓冲数据 | YAML + CSV 格式字符串 |
query_data 参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
start_time |
float | 否 | 0 | 起始 Unix 时间戳,0=从最早开始 |
end_time |
float | 否 | 0 | 结束 Unix 时间戳,0=到当前 |
max_points |
int | 否 | 1000 | 最多返回点数,超量自动降采样 |
输出格式示例:
---
data_rows: 3
start_time: "13:35:02.132"
end_time: "13:35:02.332"
---
recv_time, send_tick, left_encoder, right_encoder
13:35:02.132, 124832, 40, 37
13:35:02.232, 124834, 42, 39
13:35:02.332, 124836, 44, 41| 工具 | 描述 | 返回值 |
|---|---|---|
send_command |
向串口发送命令并可读取响应 | 响应数据或状态消息 |
send_command 参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
command |
string | 是 | - | 要发送的命令(自动加换行) |
expect_response |
bool | 否 | true | 是否等待响应 |
response_timeout |
float | 否 | 1.0 | 等待响应时间(秒),0=非阻塞 |
| 工具 | 描述 | 用途 |
|---|---|---|
send_raw_string |
发送任意字符串 | 模拟设备数据 |
debug_get_raw_data |
查看缓冲区原始数据 | 调试数据采集 |
debug_inject_data |
注入测试数据 | 测试 query_data |
用户: 查看有哪些串口可用
AI → list_ports()
← [{"name": "COM9", "description": "USB-SERIAL CH340"}]
用户: 连接 COM9,波特率 115200
AI → open_port(port="COM9", baudrate=115200)
← "Opened COM9 at 115200"
用户: 开始采集数据
AI → start_capture()
← "Capture started"
[等待设备发送数据...]
用户: 查看最近采集的100条数据
AI → query_data(max_points=100)
← [YAML元数据 + CSV数据]
用户: 只查看最近5秒的数据
AI → query_data(start_time=1739500000)
← [筛选后的数据]
用户: 停止采集
AI → stop_capture()
← "Capture stopped"
用户: 发送命令获取设备状态
AI → send_command(command="status", response_timeout=2)
← "ok\ntemp:25.5\nhumidity:60%"
用户: 发送命令不等待响应
AI → send_command(command="reboot", expect_response=false)
← "Command sent"
用户: 注入测试数据验证功能
AI → debug_inject_data(
data_lines="1000,10,20\n1001,11,21\n1002,12,22",
interval_ms=100
)
← "Injected 3 data entries"
用户: 查看缓冲区详情
AI → debug_get_raw_data(max_entries=5)
← "Buffer size: 3 (maxlen: 10000)\n[0] 12:34:56.789 | ..."
默认表头:["send_tick", "left_encoder", "right_encoder"]
可通过修改 main.py 中的 HEADERS 常量自定义。
- recv_time:
hh:mm:ss.ms(24小时制本地时间,毫秒3位) - 系统时间戳: Unix 时间戳(秒),用于
start_time/end_time参数
当数据量 N > max_points 时:
- 计算步长
step = N // max_points - 按步长等间隔抽取数据
- 保证分布均匀
所有工具在遇到错误时返回 "Error: " 开头的字符串:
"Error: No open port"- 未打开串口"Error: Capture already running"- 采集已在运行"Error: could not open port 'COM99': ..."- 无效串口"Error: No response within timeout"- 响应超时
- 框架: FastMCP 2.x (MCP协议实现)
- 串口库: pyserial (跨平台串口通信)
- 数据结构: collections.deque (环形缓冲区)
- 并发: threading (后台采集线程)
MIT License
欢迎提交 Issue 和 Pull Request!
- 初始版本发布
- 实现所有 6 个任务的核心功能
- 11 个 MCP 工具完整可用