Files
httprunner/uixt/mcp_server.md
lilong.129 6e1bd5bbe2 feat: optimize MCP tools response format with automatic schema generation
- Remove all manual ReturnSchema() methods from tools
- Implement automatic schema generation using reflection
- Unify response format to flat structure with action/success/message fields
- Simplify tool implementation by removing MCPResponse embedding
- Update documentation to reflect new architecture
- Achieve ~70% code reduction while maintaining type safety
2025-06-05 23:17:06 +08:00

15 KiB
Raw Blame History

HttpRunner MCP Server 完整说明文档

📖 概述

HttpRunner MCP Server 是基于 Model Context Protocol (MCP) 协议实现的 UI 自动化测试服务器,将 HttpRunner 的强大 UI 自动化能力通过标准化的 MCP 接口暴露给 AI 模型和其他客户端,支持移动端和 Web 端的 UI 自动化任务。

🏗️ 架构设计

整体架构

采用纯 ActionTool 架构,每个 UI 操作都作为独立的工具实现:

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   MCP Client    │    │   MCP Server    │    │  XTDriver Core  │
│   (AI Model)    │◄──►│  (mcp_server)   │◄──►│   (UI Engine)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │  Device Layer   │
                       │ Android/iOS/Web │
                       └─────────────────┘

核心组件

MCPServer4XTDriver

MCP 协议服务器主体:

type MCPServer4XTDriver struct {
    mcpServer     *server.MCPServer                // MCP 协议服务器
    mcpTools      []mcp.Tool                       // 注册的工具列表
    actionToolMap map[option.ActionName]ActionTool // 动作到工具的映射
}

ActionTool 接口

所有 MCP 工具的统一契约:

type ActionTool interface {
    Name() option.ActionName                                              // 工具名称
    Description() string                                                  // 工具描述
    Options() []mcp.ToolOption                                           // MCP 选项定义
    Implement() server.ToolHandlerFunc                                   // 工具实现逻辑
    ConvertActionToCallToolRequest(action MobileAction) (mcp.CallToolRequest, error) // 动作转换
}

模块化架构

MCP 工具按功能类别拆分为多个文件:

  • mcp_server.go: 核心服务器实现和工具注册
  • mcp_tools_device.go: 设备管理工具
  • mcp_tools_touch.go: 触摸操作工具
  • mcp_tools_swipe.go: 滑动和拖拽操作工具
  • mcp_tools_input.go: 输入和 IME 工具
  • mcp_tools_button.go: 按键操作工具
  • mcp_tools_app.go: 应用管理工具
  • mcp_tools_screen.go: 屏幕操作工具
  • mcp_tools_utility.go: 实用工具(睡眠、弹窗等)
  • mcp_tools_web.go: Web 操作工具
  • mcp_tools_ai.go: AI 驱动操作工具

架构特点

  • 完全解耦: 每个工具独立实现,无依赖关系
  • 统一接口: 所有工具遵循相同的 ActionTool 接口
  • 模块化组织: 按功能分类的清晰文件结构
  • 直接调用: MCP Request -> ActionTool.Implement() -> Driver Method

📋 响应格式

扁平化响应结构

所有工具使用统一的扁平化响应格式,所有字段在同一层级:

{
    "action": "list_packages",
    "success": true,
    "message": "Found 5 installed packages",
    "packages": ["com.example.app1", "com.example.app2"],
    "count": 2
}

标准字段

每个响应包含三个标准字段:

  • action: 执行的操作名称
  • success: 操作是否成功(布尔值)
  • message: 人类可读的结果描述

工具特定字段

每个工具根据功能返回特定数据字段,与标准字段在同一层级。

响应创建

统一的响应创建函数:

func NewMCPSuccessResponse(message string, actionTool ActionTool) *mcp.CallToolResult

该函数自动:

  • 提取操作名称
  • 设置成功状态
  • 使用反射提取工具字段
  • 创建扁平化响应

工具结构定义

工具结构体只包含返回数据字段:

type ToolListPackages struct {
    Packages []string `json:"packages" desc:"List of installed app package names on the device"`
    Count    int      `json:"count" desc:"Number of installed packages"`
}

自动模式生成

使用反射自动生成返回模式:

func GenerateReturnSchema(toolStruct interface{}) map[string]string

🎯 功能特性

支持的操作类别

设备管理mcp_tools_device.go

  • list_available_devices: 发现 Android/iOS 设备和模拟器
  • select_device: 通过平台和序列号选择特定设备

触摸操作mcp_tools_touch.go

  • tap_xy: 在相对坐标点击 (0-1 范围)
  • tap_abs_xy: 在绝对像素坐标点击
  • tap_ocr: 通过 OCR 识别文本并点击
  • tap_cv: 通过计算机视觉识别元素并点击
  • double_tap_xy: 在坐标处双击

手势操作mcp_tools_swipe.go

  • swipe: 通用滑动,自动检测方向或坐标
  • swipe_direction: 方向滑动 (上/下/左/右)
  • swipe_coordinate: 基于坐标的精确滑动控制
  • drag: 两点间的拖拽操作
  • swipe_to_tap_app: 滑动查找并点击应用
  • swipe_to_tap_text: 滑动查找并点击文本
  • swipe_to_tap_texts: 滑动查找并点击多个文本中的一个

输入操作mcp_tools_input.go

  • input: 在焦点元素上输入文本
  • set_ime: 设置输入法编辑器

按键操作mcp_tools_button.go

  • press_button: 按设备按键 (home、back、音量等)
  • home: 按 home 键
  • back: 按 back 键

应用管理mcp_tools_app.go

  • list_packages: 列出所有已安装应用
  • app_launch: 通过包名启动应用
  • app_terminate: 终止运行中的应用
  • app_install: 从 URL/路径安装应用
  • app_uninstall: 通过包名卸载应用
  • app_clear: 清除应用数据和缓存

屏幕操作mcp_tools_screen.go

  • screenshot: 捕获屏幕为 Base64 编码图像
  • get_screen_size: 获取设备屏幕尺寸
  • get_source: 获取 UI 层次结构/源码

实用工具操作mcp_tools_utility.go

  • sleep: 等待指定秒数
  • sleep_ms: 等待指定毫秒数
  • sleep_random: 基于参数的随机等待
  • close_popups: 关闭弹窗/对话框

Web 操作mcp_tools_web.go

  • web_login_none_ui: 执行无 UI 交互的登录
  • secondary_click: 在指定坐标右键点击
  • hover_by_selector: 通过 CSS 选择器/XPath 悬停元素
  • tap_by_selector: 通过 CSS 选择器/XPath 点击元素
  • secondary_click_by_selector: 通过选择器右键点击元素
  • web_close_tab: 通过索引关闭浏览器标签页

AI 操作mcp_tools_ai.go

  • start_to_goal: 使用自然语言描述开始到目标的任务
  • ai_action: 使用自然语言提示执行 AI 驱动的动作
  • finished: 标记任务完成并返回结果消息

关键特性

反作弊支持

为敏感操作内置反检测机制:

  • 真实时间的触摸模拟
  • 设备指纹掩码
  • 行为模式随机化

统一参数处理

所有工具通过 parseActionOptions() 使用一致的参数解析:

  • 类型安全的 JSON 编组/解组
  • 自动验证和错误处理
  • 支持复杂嵌套参数

设备抽象

无缝的多平台支持:

  • Android 设备(通过 ADB
  • iOS 设备(通过 go-ios
  • Web 浏览器(通过 WebDriver
  • Harmony OS 设备

错误处理

全面的错误管理:

  • 结构化错误响应
  • 带上下文的详细日志记录
  • 优雅的故障恢复

📖 使用指南

创建和启动服务器

// 创建和启动 MCP 服务器
server := NewMCPServer()
err := server.Start() // 阻塞并通过 stdio 提供 MCP 协议服务

客户端交互流程

  1. 初始化连接: 建立 MCP 协议连接
  2. 工具发现: 客户端查询可用工具列表
  3. 工具调用: 客户端调用特定工具执行操作
  4. 响应处理: 服务器返回结构化响应

工具实现模式

每个工具遵循一致的实现模式:

type ToolExample struct {
    // Return data fields - these define the structure of data returned by this tool
    Field1 string `json:"field1" desc:"Description of field1"`
    Field2 int    `json:"field2" desc:"Description of field2"`
}

func (t *ToolExample) Name() option.ActionName {
    return option.ACTION_Example
}

func (t *ToolExample) Description() string {
    return "Description of what this tool does"
}

func (t *ToolExample) Options() []mcp.ToolOption {
    unifiedReq := &option.ActionOptions{}
    return unifiedReq.GetMCPOptions(option.ACTION_Example)
}

func (t *ToolExample) Implement() server.ToolHandlerFunc {
    return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
        // Setup driver
        driverExt, err := setupXTDriver(ctx, request.Params.Arguments)
        if err != nil {
            return nil, fmt.Errorf("setup driver failed: %w", err)
        }

        // Parse parameters
        unifiedReq, err := parseActionOptions(request.Params.Arguments)
        if err != nil {
            return nil, err
        }

        // Execute business logic
        // ... implementation ...

        // Create response
        message := "Operation completed successfully"
        returnData := ToolExample{
            Field1: "value1",
            Field2: 42,
        }

        return NewMCPSuccessResponse(message, &returnData), nil
    }
}

func (t *ToolExample) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
    // Convert action to MCP request
    arguments := map[string]any{
        "param1": action.Params,
    }
    return buildMCPCallToolRequest(t.Name(), arguments), nil
}

参数处理

统一参数结构

所有工具使用 option.ActionOptions 结构进行参数处理:

type ActionOptions struct {
    // Common fields
    Platform string `json:"platform,omitempty"`
    Serial   string `json:"serial,omitempty"`

    // Action-specific fields
    Text     string  `json:"text,omitempty"`
    X        float64 `json:"x,omitempty"`
    Y        float64 `json:"y,omitempty"`
    // ... more fields
}

参数解析

使用 parseActionOptions() 函数进行类型安全的参数解析:

unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err != nil {
    return nil, err
}

错误处理

错误响应

使用 NewMCPErrorResponse() 创建错误响应:

if err != nil {
    return NewMCPErrorResponse(fmt.Sprintf("Operation failed: %s", err.Error())), nil
}

错误响应格式

{
    "success": false,
    "message": "Error description"
}

🔧 开发指南

添加新工具

  1. 定义工具结构体
type ToolNewFeature struct {
    // Return data fields
    Result string `json:"result" desc:"Description of result"`
}
  1. 实现 ActionTool 接口
func (t *ToolNewFeature) Name() option.ActionName {
    return option.ACTION_NewFeature
}

func (t *ToolNewFeature) Description() string {
    return "Description of the new feature"
}

func (t *ToolNewFeature) Options() []mcp.ToolOption {
    unifiedReq := &option.ActionOptions{}
    return unifiedReq.GetMCPOptions(option.ACTION_NewFeature)
}

func (t *ToolNewFeature) Implement() server.ToolHandlerFunc {
    // Implementation logic
}

func (t *ToolNewFeature) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
    // Conversion logic
}
  1. 注册工具mcp_server.goNewMCPServer() 函数中添加:
&ToolNewFeature{},

测试工具

单元测试

func TestToolNewFeature(t *testing.T) {
    tool := &ToolNewFeature{}

    // Test Name
    assert.Equal(t, option.ACTION_NewFeature, tool.Name())

    // Test Description
    assert.NotEmpty(t, tool.Description())

    // Test Options
    options := tool.Options()
    assert.NotEmpty(t, options)

    // Test schema generation
    schema := GenerateReturnSchema(tool)
    assert.Contains(t, schema, "result")
}

集成测试

func TestToolNewFeatureIntegration(t *testing.T) {
    // Create mock request
    request := mcp.CallToolRequest{
        Params: mcp.CallToolRequestParams{
            Arguments: map[string]any{
                "param1": "value1",
            },
        },
    }

    // Execute tool
    tool := &ToolNewFeature{}
    handler := tool.Implement()
    result, err := handler(context.Background(), request)

    // Verify result
    assert.NoError(t, err)
    assert.NotNil(t, result)
}

最佳实践

工具设计

  • 单一职责: 每个工具只负责一个特定功能
  • 清晰命名: 使用描述性的工具名称
  • 完整文档: 提供详细的描述和参数说明
  • 错误处理: 提供有意义的错误消息

响应设计

  • 一致性: 所有工具使用相同的响应格式
  • 信息丰富: 返回足够的信息供客户端使用
  • 类型安全: 使用适当的数据类型
  • 描述性: 提供清晰的字段描述

性能优化

  • 延迟加载: 只在需要时初始化资源
  • 资源复用: 复用驱动程序连接
  • 错误快速失败: 尽早检测和报告错误
  • 日志记录: 提供适当的日志级别

📊 工具统计

总计

  • 总工具数: 40+ 个
  • 文件数: 9 个工具文件
  • 支持平台: Android、iOS、Web、Harmony OS

按类别分布

  • 设备管理: 2 个工具
  • 触摸操作: 5 个工具
  • 手势操作: 7 个工具
  • 输入操作: 2 个工具
  • 按键操作: 3 个工具
  • 应用管理: 6 个工具
  • 屏幕操作: 3 个工具
  • 实用工具: 4 个工具
  • Web 操作: 6 个工具
  • AI 操作: 3 个工具

🚀 性能特性

优化成果

  • 代码减少: 相比原始实现减少约 70% 的样板代码
  • 一致性: 100% 的工具使用统一响应格式
  • 自动化: 完全自动化的模式生成
  • 类型安全: 保持完整的类型安全性
  • 零手动定义: 无需手动定义响应模式

架构优势

  • 极简化: 单函数调用创建响应
  • 可维护性: 清晰的代码结构和分离关注点
  • 开发体验: 直观的 API 和最小认知开销
  • 自文档化: 代码即文档的设计

📝 总结

HttpRunner MCP Server 提供了一个强大、灵活且易于使用的 UI 自动化平台。通过采用扁平化响应格式和自动化模式生成,实现了极简化的架构,同时保持了完整的功能性和类型安全性。

该架构的主要优势:

  • 统一性: 所有工具遵循相同的模式
  • 简洁性: 最小化的样板代码
  • 可扩展性: 易于添加新功能
  • 可维护性: 清晰的代码组织
  • 性能: 优化的响应创建和处理

无论是进行移动应用测试、Web 自动化还是 AI 驱动的 UI 操作HttpRunner MCP Server 都提供了必要的工具和基础设施来支持各种自动化需求。