fix: replace undefined mapToStruct with parseActionOptions in MCP server

- Replace all mapToStruct calls with parseActionOptions function
- Add parseActionOptions implementation for MCP request parameter parsing
- Remove undefined mapToStruct function that was causing compilation errors
- Standardize parameter names (fromX/fromY/toX/toY -> from_x/from_y/to_x/to_y)
- Add AntiRisk support for TapAbsXY and Drag tools
- Improve parameter validation for Drag tool
- Update corresponding test cases to match new parameter names

This fixes compilation errors and ensures all MCP tools work correctly.
This commit is contained in:
lilong.129
2025-05-29 20:37:14 +08:00
parent dc20eaa816
commit 4e77ec4002
3 changed files with 152 additions and 127 deletions

View File

@@ -1 +1 @@
v5.0.0-beta-2505291922 v5.0.0-beta-2505292037

View File

@@ -311,9 +311,9 @@ func (t *ToolTapXY) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Get options directly since ActionOptions is now ActionOptions // Get options directly since ActionOptions is now ActionOptions
@@ -382,9 +382,9 @@ func (t *ToolTapAbsXY) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Get options directly since ActionOptions is now ActionOptions // Get options directly since ActionOptions is now ActionOptions
@@ -393,6 +393,11 @@ func (t *ToolTapAbsXY) Implement() server.ToolHandlerFunc {
// Add default options // Add default options
opts = append(opts, option.WithPreMarkOperation(true)) opts = append(opts, option.WithPreMarkOperation(true))
// Add AntiRisk support
if unifiedReq.AntiRisk {
opts = append(opts, option.WithAntiRisk(true))
}
// Validate required parameters // Validate required parameters
if unifiedReq.X == 0 || unifiedReq.Y == 0 { if unifiedReq.X == 0 || unifiedReq.Y == 0 {
return nil, fmt.Errorf("x and y coordinates are required") return nil, fmt.Errorf("x and y coordinates are required")
@@ -453,9 +458,9 @@ func (t *ToolTapByOCR) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Get options directly since ActionOptions is now ActionOptions // Get options directly since ActionOptions is now ActionOptions
@@ -517,9 +522,9 @@ func (t *ToolTapByCV) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Get options directly since ActionOptions is now ActionOptions // Get options directly since ActionOptions is now ActionOptions
@@ -578,9 +583,9 @@ func (t *ToolDoubleTapXY) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Validate required parameters // Validate required parameters
@@ -669,9 +674,9 @@ func (t *ToolLaunchApp) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
if unifiedReq.PackageName == "" { if unifiedReq.PackageName == "" {
@@ -722,9 +727,9 @@ func (t *ToolTerminateApp) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
if unifiedReq.PackageName == "" { if unifiedReq.PackageName == "" {
@@ -852,9 +857,9 @@ func (t *ToolPressButton) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Press button action logic // Press button action logic
@@ -964,9 +969,9 @@ func (t *ToolSwipeDirection) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
swipeDirection := unifiedReq.Direction.(string) swipeDirection := unifiedReq.Direction.(string)
@@ -1057,9 +1062,9 @@ func (t *ToolSwipeCoordinate) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Validate required parameters // Validate required parameters
@@ -1101,10 +1106,10 @@ func (t *ToolSwipeCoordinate) Implement() server.ToolHandlerFunc {
func (t *ToolSwipeCoordinate) ConvertActionToCallToolRequest(action MobileAction) (mcp.CallToolRequest, error) { func (t *ToolSwipeCoordinate) ConvertActionToCallToolRequest(action MobileAction) (mcp.CallToolRequest, error) {
if paramSlice, err := builtin.ConvertToFloat64Slice(action.Params); err == nil && len(paramSlice) == 4 { if paramSlice, err := builtin.ConvertToFloat64Slice(action.Params); err == nil && len(paramSlice) == 4 {
arguments := map[string]any{ arguments := map[string]any{
"fromX": paramSlice[0], "from_x": paramSlice[0],
"fromY": paramSlice[1], "from_y": paramSlice[1],
"toX": paramSlice[2], "to_x": paramSlice[2],
"toY": paramSlice[3], "to_y": paramSlice[3],
} }
// Add duration and press duration from options // Add duration and press duration from options
if duration := action.ActionOptions.Duration; duration > 0 { if duration := action.ActionOptions.Duration; duration > 0 {
@@ -1145,9 +1150,9 @@ func (t *ToolSwipeToTapApp) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Build action options from request structure // Build action options from request structure
@@ -1214,9 +1219,9 @@ func (t *ToolSwipeToTapText) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Build action options from request structure // Build action options from request structure
@@ -1286,9 +1291,9 @@ func (t *ToolSwipeToTapTexts) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Build action options from request structure // Build action options from request structure
@@ -1363,20 +1368,27 @@ func (t *ToolDrag) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Validate required parameters // Validate required parameters - check if coordinates are provided (not just non-zero)
if unifiedReq.FromX == 0 || unifiedReq.FromY == 0 || unifiedReq.ToX == 0 || unifiedReq.ToY == 0 { _, hasFromX := request.Params.Arguments["from_x"]
return nil, fmt.Errorf("fromX, fromY, toX, and toY coordinates are required") _, hasFromY := request.Params.Arguments["from_y"]
_, hasToX := request.Params.Arguments["to_x"]
_, hasToY := request.Params.Arguments["to_y"]
if !hasFromX || !hasFromY || !hasToX || !hasToY {
return nil, fmt.Errorf("from_x, from_y, to_x, and to_y coordinates are required")
} }
opts := []option.ActionOption{} opts := []option.ActionOption{}
if unifiedReq.Duration > 0 { if unifiedReq.Duration > 0 {
opts = append(opts, option.WithDuration(unifiedReq.Duration/1000.0)) opts = append(opts, option.WithDuration(unifiedReq.Duration/1000.0))
} }
if unifiedReq.AntiRisk {
opts = append(opts, option.WithAntiRisk(true))
}
// Drag action logic // Drag action logic
log.Info(). log.Info().
@@ -1397,27 +1409,22 @@ func (t *ToolDrag) Implement() server.ToolHandlerFunc {
func (t *ToolDrag) ConvertActionToCallToolRequest(action MobileAction) (mcp.CallToolRequest, error) { func (t *ToolDrag) ConvertActionToCallToolRequest(action MobileAction) (mcp.CallToolRequest, error) {
if paramSlice, err := builtin.ConvertToFloat64Slice(action.Params); err == nil && len(paramSlice) == 4 { if paramSlice, err := builtin.ConvertToFloat64Slice(action.Params); err == nil && len(paramSlice) == 4 {
arguments := map[string]any{ arguments := map[string]any{
"fromX": paramSlice[0], "from_x": paramSlice[0],
"fromY": paramSlice[1], "from_y": paramSlice[1],
"toX": paramSlice[2], "to_x": paramSlice[2],
"toY": paramSlice[3], "to_y": paramSlice[3],
} }
// Add duration from options // Add duration from options
if duration := action.ActionOptions.Duration; duration > 0 { if duration := action.ActionOptions.Duration; duration > 0 {
arguments["duration"] = duration * 1000 // convert to milliseconds arguments["duration"] = duration * 1000 // convert to milliseconds
} }
// Extract all action options
extractActionOptionsToArguments(action.GetOptions(), arguments)
return buildMCPCallToolRequest(t.Name(), arguments), nil return buildMCPCallToolRequest(t.Name(), arguments), nil
} }
return mcp.CallToolRequest{}, fmt.Errorf("invalid drag params: %v", action.Params) return mcp.CallToolRequest{}, fmt.Errorf("invalid drag parameters: %v", action.Params)
}
// mapToStruct convert map[string]any to target struct
func mapToStruct(m map[string]any, out interface{}) error {
b, err := json.Marshal(m)
if err != nil {
return err
}
return json.Unmarshal(b, out)
} }
// extractActionOptionsToArguments extracts action options and adds them to arguments map // extractActionOptionsToArguments extracts action options and adds them to arguments map
@@ -1448,15 +1455,18 @@ func extractActionOptionsToArguments(actionOptions []option.ActionOption, argume
} }
} }
// Add numeric options only if they have meaningful values // Add numeric options only if they have meaningful values and don't already exist
if tempOptions.MaxRetryTimes > 0 { if tempOptions.MaxRetryTimes > 0 {
arguments["max_retry_times"] = tempOptions.MaxRetryTimes arguments["max_retry_times"] = tempOptions.MaxRetryTimes
} }
if tempOptions.Index != 0 { if tempOptions.Index != 0 {
arguments["index"] = tempOptions.Index arguments["index"] = tempOptions.Index
} }
// Only set duration if it's not already set (to avoid overriding tool-specific conversions)
if tempOptions.Duration > 0 { if tempOptions.Duration > 0 {
arguments["duration"] = tempOptions.Duration if _, exists := arguments["duration"]; !exists {
arguments["duration"] = tempOptions.Duration
}
} }
if tempOptions.PressDuration > 0 { if tempOptions.PressDuration > 0 {
arguments["press_duration"] = tempOptions.PressDuration arguments["press_duration"] = tempOptions.PressDuration
@@ -1562,9 +1572,9 @@ func (t *ToolInput) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
if unifiedReq.Text == "" { if unifiedReq.Text == "" {
@@ -1613,9 +1623,9 @@ func (t *ToolWebLoginNoneUI) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Web login none UI action logic // Web login none UI action logic
@@ -1661,9 +1671,9 @@ func (t *ToolAppInstall) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// App install action logic // App install action logic
@@ -1710,9 +1720,9 @@ func (t *ToolAppUninstall) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// App uninstall action logic // App uninstall action logic
@@ -1759,9 +1769,9 @@ func (t *ToolAppClear) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// App clear action logic // App clear action logic
@@ -1808,9 +1818,9 @@ func (t *ToolSecondaryClick) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Validate required parameters // Validate required parameters
@@ -1863,9 +1873,9 @@ func (t *ToolHoverBySelector) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Hover by selector action logic // Hover by selector action logic
@@ -1912,9 +1922,9 @@ func (t *ToolTapBySelector) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Tap by selector action logic // Tap by selector action logic
@@ -1961,9 +1971,9 @@ func (t *ToolSecondaryClickBySelector) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Secondary click by selector action logic // Secondary click by selector action logic
@@ -2010,9 +2020,9 @@ func (t *ToolWebCloseTab) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Validate required parameters // Validate required parameters
@@ -2077,9 +2087,9 @@ func (t *ToolSetIme) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Set IME action logic // Set IME action logic
@@ -2126,9 +2136,9 @@ func (t *ToolGetSource) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Get source action logic // Get source action logic
@@ -2228,9 +2238,9 @@ func (t *ToolSleepMS) Options() []mcp.ToolOption {
func (t *ToolSleepMS) Implement() server.ToolHandlerFunc { func (t *ToolSleepMS) Implement() server.ToolHandlerFunc {
return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Validate required parameters // Validate required parameters
@@ -2279,9 +2289,9 @@ func (t *ToolSleepRandom) Options() []mcp.ToolOption {
func (t *ToolSleepRandom) Implement() server.ToolHandlerFunc { func (t *ToolSleepRandom) Implement() server.ToolHandlerFunc {
return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// Sleep random action logic // Sleep random action logic
@@ -2363,9 +2373,9 @@ func (t *ToolAIAction) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("setup driver failed: %w", err) return nil, fmt.Errorf("setup driver failed: %w", err)
} }
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
// AI action logic // AI action logic
@@ -2407,9 +2417,9 @@ func (t *ToolFinished) Options() []mcp.ToolOption {
func (t *ToolFinished) Implement() server.ToolHandlerFunc { func (t *ToolFinished) Implement() server.ToolHandlerFunc {
return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
var unifiedReq option.ActionOptions unifiedReq, err := parseActionOptions(request.Params.Arguments)
if err := mapToStruct(request.Params.Arguments, &unifiedReq); err != nil { if err != nil {
return nil, fmt.Errorf("parse parameters error: %w", err) return nil, err
} }
log.Info().Str("reason", unifiedReq.Content).Msg("task finished") log.Info().Str("reason", unifiedReq.Content).Msg("task finished")
@@ -2433,3 +2443,18 @@ func getFloat64ValueOrDefault(value float64, defaultValue float64) float64 {
} }
return value return value
} }
// parseActionOptions converts MCP request arguments to ActionOptions struct
func parseActionOptions(arguments map[string]any) (*option.ActionOptions, error) {
b, err := json.Marshal(arguments)
if err != nil {
return nil, fmt.Errorf("marshal arguments failed: %w", err)
}
var actionOptions option.ActionOptions
if err := json.Unmarshal(b, &actionOptions); err != nil {
return nil, fmt.Errorf("unmarshal to ActionOptions failed: %w", err)
}
return &actionOptions, nil
}

View File

@@ -455,7 +455,7 @@ func TestToolSwipe(t *testing.T) {
assert.Equal(t, 1.5, request.Params.Arguments["duration"]) assert.Equal(t, 1.5, request.Params.Arguments["duration"])
assert.Equal(t, 0.5, request.Params.Arguments["pressDuration"]) assert.Equal(t, 0.5, request.Params.Arguments["pressDuration"])
// Test ConvertActionToCallToolRequest with coordinate params ([]float64) // Test ConvertActionToCallToolRequest with coordinate params
coordinateAction := MobileAction{ coordinateAction := MobileAction{
Method: option.ACTION_Swipe, Method: option.ACTION_Swipe,
Params: []float64{0.1, 0.2, 0.8, 0.9}, Params: []float64{0.1, 0.2, 0.8, 0.9},
@@ -467,10 +467,10 @@ func TestToolSwipe(t *testing.T) {
request, err = tool.ConvertActionToCallToolRequest(coordinateAction) request, err = tool.ConvertActionToCallToolRequest(coordinateAction)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, string(option.ACTION_Swipe), request.Params.Name) assert.Equal(t, string(option.ACTION_Swipe), request.Params.Name)
assert.Equal(t, 0.1, request.Params.Arguments["fromX"]) assert.Equal(t, 0.1, request.Params.Arguments["from_x"])
assert.Equal(t, 0.2, request.Params.Arguments["fromY"]) assert.Equal(t, 0.2, request.Params.Arguments["from_y"])
assert.Equal(t, 0.8, request.Params.Arguments["toX"]) assert.Equal(t, 0.8, request.Params.Arguments["to_x"])
assert.Equal(t, 0.9, request.Params.Arguments["toY"]) assert.Equal(t, 0.9, request.Params.Arguments["to_y"])
assert.Equal(t, 2.0, request.Params.Arguments["duration"]) assert.Equal(t, 2.0, request.Params.Arguments["duration"])
assert.Equal(t, 1.0, request.Params.Arguments["pressDuration"]) assert.Equal(t, 1.0, request.Params.Arguments["pressDuration"])
@@ -556,10 +556,10 @@ func TestToolSwipeCoordinate(t *testing.T) {
request, err := tool.ConvertActionToCallToolRequest(action) request, err := tool.ConvertActionToCallToolRequest(action)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, string(option.ACTION_SwipeCoordinate), request.Params.Name) assert.Equal(t, string(option.ACTION_SwipeCoordinate), request.Params.Name)
assert.Equal(t, 0.1, request.Params.Arguments["fromX"]) assert.Equal(t, 0.1, request.Params.Arguments["from_x"])
assert.Equal(t, 0.2, request.Params.Arguments["fromY"]) assert.Equal(t, 0.2, request.Params.Arguments["from_y"])
assert.Equal(t, 0.8, request.Params.Arguments["toX"]) assert.Equal(t, 0.8, request.Params.Arguments["to_x"])
assert.Equal(t, 0.9, request.Params.Arguments["toY"]) assert.Equal(t, 0.9, request.Params.Arguments["to_y"])
assert.Equal(t, 2.0, request.Params.Arguments["duration"]) assert.Equal(t, 2.0, request.Params.Arguments["duration"])
assert.Equal(t, 1.0, request.Params.Arguments["pressDuration"]) assert.Equal(t, 1.0, request.Params.Arguments["pressDuration"])
@@ -724,10 +724,10 @@ func TestToolDrag(t *testing.T) {
request, err := tool.ConvertActionToCallToolRequest(action) request, err := tool.ConvertActionToCallToolRequest(action)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, string(option.ACTION_Drag), request.Params.Name) assert.Equal(t, string(option.ACTION_Drag), request.Params.Name)
assert.Equal(t, 0.1, request.Params.Arguments["fromX"]) assert.Equal(t, 0.1, request.Params.Arguments["from_x"])
assert.Equal(t, 0.2, request.Params.Arguments["fromY"]) assert.Equal(t, 0.2, request.Params.Arguments["from_y"])
assert.Equal(t, 0.8, request.Params.Arguments["toX"]) assert.Equal(t, 0.8, request.Params.Arguments["to_x"])
assert.Equal(t, 0.9, request.Params.Arguments["toY"]) assert.Equal(t, 0.9, request.Params.Arguments["to_y"])
assert.Equal(t, 2500.0, request.Params.Arguments["duration"]) // converted to milliseconds assert.Equal(t, 2500.0, request.Params.Arguments["duration"]) // converted to milliseconds
// Test ConvertActionToCallToolRequest with invalid params // Test ConvertActionToCallToolRequest with invalid params