refactor: BuildMCPCallToolRequest

This commit is contained in:
lilong.129
2025-07-03 18:18:34 +08:00
parent 7673a64184
commit 7393f7aab3
13 changed files with 69 additions and 132 deletions

View File

@@ -1 +1 @@
v5.0.0-250702
v5.0.0-250703

View File

@@ -5,7 +5,6 @@ import (
"time"
"github.com/cloudwego/eino/schema"
"github.com/mark3labs/mcp-go/mcp"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
@@ -313,24 +312,16 @@ func (dExt *XTDriver) invokeToolCall(ctx context.Context, toolCall schema.ToolCa
return err
}
// Merge StartToGoal options into tool call arguments
// This ensures options like PreMarkOperation are passed to specific tool implementations
extractActionOptionsToArguments(opts, arguments)
// Execute the action
req := mcp.CallToolRequest{
Params: struct {
Name string `json:"name"`
Arguments map[string]any `json:"arguments,omitempty"`
Meta *struct {
ProgressToken mcp.ProgressToken `json:"progressToken,omitempty"`
} `json:"_meta,omitempty"`
}{
Name: toolCall.Function.Name,
Arguments: arguments,
},
// Create a MobileAction with options to reuse BuildMCPCallToolRequest
action := option.MobileAction{
Options: option.NewActionOptions(opts...),
}
req := BuildMCPCallToolRequest(
option.ActionName(toolCall.Function.Name),
arguments,
action,
)
_, err = dExt.client.CallTool(ctx, req)
if err != nil {
return err

View File

@@ -158,7 +158,10 @@ type ActionTool interface {
}
// BuildMCPCallToolRequest is a helper function to build mcp.CallToolRequest
func BuildMCPCallToolRequest(toolName option.ActionName, arguments map[string]any) mcp.CallToolRequest {
func BuildMCPCallToolRequest(toolName option.ActionName, arguments map[string]any, action option.MobileAction) mcp.CallToolRequest {
// Automatically extract action options and add them to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return mcp.CallToolRequest{
Params: struct {
Name string `json:"name"`

View File

@@ -62,11 +62,7 @@ func (t *ToolStartToGoal) ConvertActionToCallToolRequest(action option.MobileAct
arguments := map[string]any{
"prompt": prompt,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid start to goal params: %v", action.Params)
}
@@ -122,11 +118,7 @@ func (t *ToolAIAction) ConvertActionToCallToolRequest(action option.MobileAction
arguments := map[string]any{
"prompt": prompt,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid AI action params: %v", action.Params)
}
@@ -187,11 +179,7 @@ func (t *ToolAIQuery) ConvertActionToCallToolRequest(action option.MobileAction)
arguments := map[string]any{
"prompt": prompt,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid AI query params: %v", action.Params)
}
@@ -237,7 +225,7 @@ func (t *ToolFinished) ConvertActionToCallToolRequest(action option.MobileAction
arguments := map[string]any{
"content": reason,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid finished params: %v", action.Params)
}

View File

@@ -4,10 +4,11 @@ import (
"context"
"fmt"
"github.com/httprunner/httprunner/v5/uixt/option"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
"github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/uixt/option"
)
// ToolListPackages implements the list_packages tool call.
@@ -53,7 +54,7 @@ func (t *ToolListPackages) Implement() server.ToolHandlerFunc {
}
func (t *ToolListPackages) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return BuildMCPCallToolRequest(t.Name(), map[string]any{}), nil
return BuildMCPCallToolRequest(t.Name(), map[string]any{}, action), nil
}
// ToolLaunchApp implements the launch_app tool call.
@@ -109,7 +110,7 @@ func (t *ToolLaunchApp) ConvertActionToCallToolRequest(action option.MobileActio
arguments := map[string]any{
"packageName": packageName,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid app launch params: %v", action.Params)
}
@@ -174,7 +175,7 @@ func (t *ToolTerminateApp) ConvertActionToCallToolRequest(action option.MobileAc
arguments := map[string]any{
"packageName": packageName,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid app terminate params: %v", action.Params)
}
@@ -228,7 +229,7 @@ func (t *ToolAppInstall) ConvertActionToCallToolRequest(action option.MobileActi
arguments := map[string]any{
"appUrl": appUrl,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid app install params: %v", action.Params)
}
@@ -282,7 +283,7 @@ func (t *ToolAppUninstall) ConvertActionToCallToolRequest(action option.MobileAc
arguments := map[string]any{
"packageName": packageName,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid app uninstall params: %v", action.Params)
}
@@ -336,7 +337,7 @@ func (t *ToolAppClear) ConvertActionToCallToolRequest(action option.MobileAction
arguments := map[string]any{
"packageName": packageName,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid app clear params: %v", action.Params)
}
@@ -385,5 +386,5 @@ func (t *ToolGetForegroundApp) Implement() server.ToolHandlerFunc {
}
func (t *ToolGetForegroundApp) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return BuildMCPCallToolRequest(t.Name(), map[string]any{}), nil
return BuildMCPCallToolRequest(t.Name(), map[string]any{}, action), nil
}

View File

@@ -4,10 +4,11 @@ import (
"context"
"fmt"
"github.com/httprunner/httprunner/v5/uixt/option"
"github.com/httprunner/httprunner/v5/uixt/types"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
"github.com/httprunner/httprunner/v5/uixt/option"
"github.com/httprunner/httprunner/v5/uixt/types"
)
// ToolPressButton implements the press_button tool call.
@@ -59,7 +60,7 @@ func (t *ToolPressButton) ConvertActionToCallToolRequest(action option.MobileAct
arguments := map[string]any{
"button": button,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid press button params: %v", action.Params)
}
@@ -102,7 +103,7 @@ func (t *ToolHome) Implement() server.ToolHandlerFunc {
}
func (t *ToolHome) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return BuildMCPCallToolRequest(t.Name(), map[string]any{}), nil
return BuildMCPCallToolRequest(t.Name(), map[string]any{}, action), nil
}
// ToolBack implements the back tool call.
@@ -143,5 +144,5 @@ func (t *ToolBack) Implement() server.ToolHandlerFunc {
}
func (t *ToolBack) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return BuildMCPCallToolRequest(t.Name(), map[string]any{}), nil
return BuildMCPCallToolRequest(t.Name(), map[string]any{}, action), nil
}

View File

@@ -5,11 +5,12 @@ import (
"fmt"
"github.com/danielpaulus/go-ios/ios"
"github.com/httprunner/httprunner/v5/pkg/gadb"
"github.com/httprunner/httprunner/v5/uixt/option"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
"github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/pkg/gadb"
"github.com/httprunner/httprunner/v5/uixt/option"
)
// ToolListAvailableDevices implements the list_available_devices tool call.
@@ -82,7 +83,7 @@ func (t *ToolListAvailableDevices) Implement() server.ToolHandlerFunc {
}
func (t *ToolListAvailableDevices) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return BuildMCPCallToolRequest(t.Name(), map[string]any{}), nil
return BuildMCPCallToolRequest(t.Name(), map[string]any{}, action), nil
}
// ToolSelectDevice implements the select_device tool call.
@@ -122,7 +123,7 @@ func (t *ToolSelectDevice) Implement() server.ToolHandlerFunc {
}
func (t *ToolSelectDevice) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return BuildMCPCallToolRequest(t.Name(), map[string]any{}), nil
return BuildMCPCallToolRequest(t.Name(), map[string]any{}, action), nil
}
// ToolScreenRecord implements the screenrecord tool call.
@@ -212,5 +213,5 @@ func (t *ToolScreenRecord) Implement() server.ToolHandlerFunc {
}
func (t *ToolScreenRecord) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return BuildMCPCallToolRequest(t.Name(), map[string]any{}), nil
return BuildMCPCallToolRequest(t.Name(), map[string]any{}, action), nil
}

View File

@@ -4,9 +4,10 @@ import (
"context"
"fmt"
"github.com/httprunner/httprunner/v5/uixt/option"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
"github.com/httprunner/httprunner/v5/uixt/option"
)
// ToolInput implements the input tool call.
@@ -44,8 +45,10 @@ func (t *ToolInput) Implement() server.ToolHandlerFunc {
return nil, fmt.Errorf("text is required")
}
opts := unifiedReq.Options()
// Input action logic
err = driverExt.Input(unifiedReq.Text)
err = driverExt.Input(unifiedReq.Text, opts...)
if err != nil {
return NewMCPErrorResponse(fmt.Sprintf("Input failed: %s", err.Error())), err
}
@@ -62,7 +65,7 @@ func (t *ToolInput) ConvertActionToCallToolRequest(action option.MobileAction) (
arguments := map[string]any{
"text": text,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
// ToolSetIme implements the set_ime tool call.
@@ -114,7 +117,7 @@ func (t *ToolSetIme) ConvertActionToCallToolRequest(action option.MobileAction)
arguments := map[string]any{
"ime": ime,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid set ime params: %v", action.Params)
}

View File

@@ -50,7 +50,7 @@ func (t *ToolScreenShot) Implement() server.ToolHandlerFunc {
}
func (t *ToolScreenShot) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return BuildMCPCallToolRequest(t.Name(), map[string]any{}), nil
return BuildMCPCallToolRequest(t.Name(), map[string]any{}, action), nil
}
// ToolGetScreenSize implements the get_screen_size tool call.
@@ -96,7 +96,7 @@ func (t *ToolGetScreenSize) Implement() server.ToolHandlerFunc {
}
func (t *ToolGetScreenSize) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return BuildMCPCallToolRequest(t.Name(), map[string]any{}), nil
return BuildMCPCallToolRequest(t.Name(), map[string]any{}, action), nil
}
// ToolGetSource implements the get_source tool call.
@@ -152,7 +152,7 @@ func (t *ToolGetSource) ConvertActionToCallToolRequest(action option.MobileActio
arguments := map[string]any{
"packageName": packageName,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid get source params: %v", action.Params)
}

View File

@@ -183,11 +183,7 @@ func (t *ToolSwipeDirection) ConvertActionToCallToolRequest(action option.Mobile
if pressDuration := action.ActionOptions.PressDuration; pressDuration > 0 {
arguments["pressDuration"] = pressDuration
}
// Extract all action options
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid swipe params: %v", action.Params)
}
@@ -276,11 +272,7 @@ func (t *ToolSwipeCoordinate) ConvertActionToCallToolRequest(action option.Mobil
if pressDuration := action.ActionOptions.PressDuration; pressDuration > 0 {
arguments["pressDuration"] = pressDuration
}
// Extract all action options
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid swipe advanced params: %v", action.Params)
}
@@ -337,11 +329,7 @@ func (t *ToolSwipeToTapApp) ConvertActionToCallToolRequest(action option.MobileA
arguments := map[string]any{
"appName": appName,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid swipe to tap app params: %v", action.Params)
}
@@ -398,11 +386,7 @@ func (t *ToolSwipeToTapText) ConvertActionToCallToolRequest(action option.Mobile
arguments := map[string]any{
"text": text,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid swipe to tap text params: %v", action.Params)
}
@@ -470,11 +454,7 @@ func (t *ToolSwipeToTapTexts) ConvertActionToCallToolRequest(action option.Mobil
arguments := map[string]any{
"texts": texts,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
// ToolDrag implements the drag tool call.
@@ -557,11 +537,7 @@ func (t *ToolDrag) ConvertActionToCallToolRequest(action option.MobileAction) (m
if duration := action.ActionOptions.Duration; duration > 0 {
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, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid drag parameters: %v", action.Params)
}

View File

@@ -78,11 +78,7 @@ func (t *ToolTapXY) ConvertActionToCallToolRequest(action option.MobileAction) (
if duration := action.ActionOptions.Duration; duration > 0 {
arguments["duration"] = duration
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid tap params: %v", action.Params)
}
@@ -154,11 +150,7 @@ func (t *ToolTapAbsXY) ConvertActionToCallToolRequest(action option.MobileAction
if duration := action.ActionOptions.Duration; duration > 0 {
arguments["duration"] = duration
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid tap abs params: %v", action.Params)
}
@@ -220,11 +212,7 @@ func (t *ToolTapByOCR) ConvertActionToCallToolRequest(action option.MobileAction
arguments := map[string]any{
"text": text,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid tap by OCR params: %v", action.Params)
}
@@ -281,11 +269,7 @@ func (t *ToolTapByCV) ConvertActionToCallToolRequest(action option.MobileAction)
arguments := map[string]any{
"imagePath": "", // Will be handled by the tool based on UI types
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
// ToolDoubleTapXY implements the double_tap_xy tool call.
@@ -348,7 +332,7 @@ func (t *ToolDoubleTapXY) ConvertActionToCallToolRequest(action option.MobileAct
"x": x,
"y": y,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid double tap params: %v", action.Params)
}

View File

@@ -94,7 +94,7 @@ func (t *ToolSleep) ConvertActionToCallToolRequest(action option.MobileAction) (
arguments := map[string]any{
"seconds": action.Params,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
// ToolSleepMS implements the sleep_ms tool call.
@@ -184,7 +184,7 @@ func (t *ToolSleepMS) ConvertActionToCallToolRequest(action option.MobileAction)
arguments := map[string]any{
"milliseconds": milliseconds,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
// ToolSleepRandom implements the sleep_random tool call.
@@ -228,7 +228,7 @@ func (t *ToolSleepRandom) ConvertActionToCallToolRequest(action option.MobileAct
arguments := map[string]any{
"params": params,
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid sleep random params: %v", action.Params)
}
@@ -271,5 +271,5 @@ func (t *ToolClosePopups) Implement() server.ToolHandlerFunc {
}
func (t *ToolClosePopups) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return BuildMCPCallToolRequest(t.Name(), map[string]any{}), nil
return BuildMCPCallToolRequest(t.Name(), map[string]any{}, action), nil
}

View File

@@ -71,8 +71,7 @@ func (t *ToolWebLoginNoneUI) ConvertActionToCallToolRequest(action option.Mobile
arguments["captcha"] = textsSlice[2].(string)
arguments["password"] = textsSlice[3].(string)
}
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
// ToolSecondaryClick implements the secondary_click tool call.
@@ -134,9 +133,7 @@ func (t *ToolSecondaryClick) ConvertActionToCallToolRequest(action option.Mobile
"x": params[0],
"y": params[1],
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid secondary click params: %v", action.Params)
}
@@ -192,9 +189,7 @@ func (t *ToolHoverBySelector) ConvertActionToCallToolRequest(action option.Mobil
arguments := map[string]any{
"selector": selector,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid hover by selector params: %v", action.Params)
}
@@ -250,9 +245,7 @@ func (t *ToolTapBySelector) ConvertActionToCallToolRequest(action option.MobileA
arguments := map[string]any{
"selector": selector,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid tap by selector params: %v", action.Params)
}
@@ -308,9 +301,7 @@ func (t *ToolSecondaryClickBySelector) ConvertActionToCallToolRequest(action opt
arguments := map[string]any{
"selector": selector,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}
return mcp.CallToolRequest{}, fmt.Errorf("invalid secondary click by selector params: %v", action.Params)
}
@@ -384,7 +375,5 @@ func (t *ToolWebCloseTab) ConvertActionToCallToolRequest(action option.MobileAct
arguments := map[string]any{
"tabIndex": tabIndex,
}
// Extract options to arguments
extractActionOptionsToArguments(action.GetOptions(), arguments)
return BuildMCPCallToolRequest(t.Name(), arguments), nil
return BuildMCPCallToolRequest(t.Name(), arguments, action), nil
}