#!/usr/bin/env python3
"""
ESP-IDF related tools for the FastMCP Server
"""
import subprocess
import os
from core.config import mcp, ESP_IDF_ENV
from tools.serial_tools import selected_port
@mcp.tool
def get_esp_idf_version() -> str:
"""Get the ESP-IDF version information."""
# 使用全局环境变量
result = subprocess.run(
["idf.py", "--version"],
capture_output=True,
text=True,
timeout=10,
env=ESP_IDF_ENV
)
if result.returncode != 0:
raise RuntimeError(f"Failed to get ESP-IDF version: {result.stderr}")
return result.stdout.strip()
@mcp.tool
def list_esp_targets() -> list:
"""List all supported ESP targets."""
# 使用全局环境变量
result = subprocess.run(
["idf.py", "--list-targets"],
capture_output=True,
text=True,
timeout=10,
env=ESP_IDF_ENV
)
if result.returncode != 0:
raise RuntimeError(f"Failed to list ESP targets: {result.stderr}")
targets = result.stdout.strip().split('\n')
# 过滤掉空行和非目标名称的行
targets = [target.strip() for target in targets if target.strip() and not target.startswith('ESP-IDF')]
return targets
@mcp.tool
def compile_project(project_path: str) -> dict:
"""Compile ESP-IDF project and return stdout and stderr. Use this tool to compile project instead of run build command directly."""
# 检查项目路径是否存在
if not os.path.exists(project_path):
raise ValueError(f"Project path {project_path} does not exist")
# 切换到项目目录并执行编译
try:
# 构建命令
cmd = ["idf.py", "build"]
# 如果选择了串口,添加端口参数
if selected_port:
cmd.extend(["-p", selected_port])
# 执行编译命令
result = subprocess.run(
cmd,
cwd=project_path,
capture_output=True,
text=True,
timeout=300, # 5分钟超时
env=ESP_IDF_ENV
)
return {
"returncode": result.returncode,
"stdout": result.stdout,
"stderr": result.stderr
}
except subprocess.TimeoutExpired:
raise RuntimeError("Compilation timed out after 5 minutes")
except Exception as e:
raise RuntimeError(f"Failed to compile project: {str(e)}")
@mcp.tool
def clean_project(project_path: str) -> dict:
"""Clean ESP-IDF project. Use this tool to clean project instead of run clean command directly."""
# 检查项目路径是否存在
if not os.path.exists(project_path):
raise ValueError(f"Project path {project_path} does not exist")
# 切换到项目目录并执行清理
try:
# 构建命令
cmd = ["idf.py", "fullclean"]
# 执行清理命令
result = subprocess.run(
cmd,
cwd=project_path,
capture_output=True,
text=True,
timeout=300, # 5分钟超时
env=ESP_IDF_ENV
)
return {
"returncode": result.returncode,
"stdout": result.stdout,
"stderr": result.stderr
}
except subprocess.TimeoutExpired:
raise RuntimeError("Clean operation timed out after 5 minutes")
except Exception as e:
raise RuntimeError(f"Failed to clean project: {str(e)}")
@mcp.tool
def set_target(project_path: str, target: str) -> dict:
"""Set the target chip for ESP-IDF project. Use this tool to set target instead of run set-target command directly."""
# 检查项目路径是否存在
if not os.path.exists(project_path):
raise ValueError(f"Project path {project_path} does not exist")
# 验证目标设备是否支持
supported_targets = list_esp_targets()
if target not in supported_targets:
raise ValueError(f"Target {target} is not supported. Supported targets: {supported_targets}")
# 切换到项目目录并执行设置目标设备命令
try:
# 构建命令
cmd = ["idf.py", "set-target", target]
# 执行设置目标设备命令
result = subprocess.run(
cmd,
cwd=project_path,
capture_output=True,
text=True,
timeout=300, # 5分钟超时
env=ESP_IDF_ENV
)
return {
"returncode": result.returncode,
"stdout": result.stdout,
"stderr": result.stderr
}
except subprocess.TimeoutExpired:
raise RuntimeError("Set target operation timed out after 5 minutes")
except Exception as e:
raise RuntimeError(f"Failed to set target: {str(e)}")