mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-12 16:01:27 +08:00
refactor: move tool request types to option
This commit is contained in:
@@ -1 +1 @@
|
|||||||
v5.0.0-beta-2505242332
|
v5.0.0-beta-2505242351
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v5/uixt"
|
"github.com/httprunner/httprunner/v5/uixt"
|
||||||
"github.com/httprunner/httprunner/v5/uixt/types"
|
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *Router) foregroundAppHandler(c *gin.Context) {
|
func (r *Router) foregroundAppHandler(c *gin.Context) {
|
||||||
@@ -22,7 +22,7 @@ func (r *Router) foregroundAppHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) appInfoHandler(c *gin.Context) {
|
func (r *Router) appInfoHandler(c *gin.Context) {
|
||||||
var appInfoReq types.AppInfoRequest
|
var appInfoReq option.AppInfoRequest
|
||||||
if err := c.ShouldBindQuery(&appInfoReq); err != nil {
|
if err := c.ShouldBindQuery(&appInfoReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
@@ -51,7 +51,7 @@ func (r *Router) appInfoHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) clearAppHandler(c *gin.Context) {
|
func (r *Router) clearAppHandler(c *gin.Context) {
|
||||||
var appClearReq types.AppClearRequest
|
var appClearReq option.AppClearRequest
|
||||||
if err := c.ShouldBindJSON(&appClearReq); err != nil {
|
if err := c.ShouldBindJSON(&appClearReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
@@ -70,7 +70,7 @@ func (r *Router) clearAppHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) launchAppHandler(c *gin.Context) {
|
func (r *Router) launchAppHandler(c *gin.Context) {
|
||||||
var appLaunchReq types.AppLaunchRequest
|
var appLaunchReq option.AppLaunchRequest
|
||||||
if err := c.ShouldBindJSON(&appLaunchReq); err != nil {
|
if err := c.ShouldBindJSON(&appLaunchReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
@@ -88,7 +88,7 @@ func (r *Router) launchAppHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) terminalAppHandler(c *gin.Context) {
|
func (r *Router) terminalAppHandler(c *gin.Context) {
|
||||||
var appTerminateReq types.AppTerminateRequest
|
var appTerminateReq option.AppTerminateRequest
|
||||||
if err := c.ShouldBindJSON(&appTerminateReq); err != nil {
|
if err := c.ShouldBindJSON(&appTerminateReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
@@ -106,7 +106,7 @@ func (r *Router) terminalAppHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) uninstallAppHandler(c *gin.Context) {
|
func (r *Router) uninstallAppHandler(c *gin.Context) {
|
||||||
var appUninstallReq types.AppUninstallRequest
|
var appUninstallReq option.AppUninstallRequest
|
||||||
if err := c.ShouldBindJSON(&appUninstallReq); err != nil {
|
if err := c.ShouldBindJSON(&appUninstallReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v5/uixt"
|
"github.com/httprunner/httprunner/v5/uixt"
|
||||||
"github.com/httprunner/httprunner/v5/uixt/types"
|
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *Router) unlockHandler(c *gin.Context) {
|
func (r *Router) unlockHandler(c *gin.Context) {
|
||||||
@@ -34,7 +34,7 @@ func (r *Router) homeHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) backspaceHandler(c *gin.Context) {
|
func (r *Router) backspaceHandler(c *gin.Context) {
|
||||||
var deleteReq types.DeleteRequest
|
var deleteReq option.DeleteRequest
|
||||||
if err := c.ShouldBindJSON(&deleteReq); err != nil {
|
if err := c.ShouldBindJSON(&deleteReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
@@ -55,7 +55,7 @@ func (r *Router) backspaceHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) keycodeHandler(c *gin.Context) {
|
func (r *Router) keycodeHandler(c *gin.Context) {
|
||||||
var keycodeReq types.KeycodeRequest
|
var keycodeReq option.KeycodeRequest
|
||||||
if err := c.ShouldBindJSON(&keycodeReq); err != nil {
|
if err := c.ShouldBindJSON(&keycodeReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
|
|||||||
11
server/ui.go
11
server/ui.go
@@ -4,11 +4,10 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/httprunner/httprunner/v5/uixt"
|
"github.com/httprunner/httprunner/v5/uixt"
|
||||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||||
"github.com/httprunner/httprunner/v5/uixt/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *Router) tapHandler(c *gin.Context) {
|
func (r *Router) tapHandler(c *gin.Context) {
|
||||||
var tapReq types.TapRequest
|
var tapReq option.TapRequest
|
||||||
if err := c.ShouldBindJSON(&tapReq); err != nil {
|
if err := c.ShouldBindJSON(&tapReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
@@ -31,7 +30,7 @@ func (r *Router) tapHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) rightClickHandler(c *gin.Context) {
|
func (r *Router) rightClickHandler(c *gin.Context) {
|
||||||
var rightClickReq types.TapRequest
|
var rightClickReq option.TapRequest
|
||||||
if err := c.ShouldBindJSON(&rightClickReq); err != nil {
|
if err := c.ShouldBindJSON(&rightClickReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
@@ -118,7 +117,7 @@ func (r *Router) scrollHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) doubleTapHandler(c *gin.Context) {
|
func (r *Router) doubleTapHandler(c *gin.Context) {
|
||||||
var tapReq types.TapRequest
|
var tapReq option.TapRequest
|
||||||
if err := c.ShouldBindJSON(&tapReq); err != nil {
|
if err := c.ShouldBindJSON(&tapReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
@@ -138,7 +137,7 @@ func (r *Router) doubleTapHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) dragHandler(c *gin.Context) {
|
func (r *Router) dragHandler(c *gin.Context) {
|
||||||
var dragReq types.DragRequest
|
var dragReq option.DragRequest
|
||||||
if err := c.ShouldBindJSON(&dragReq); err != nil {
|
if err := c.ShouldBindJSON(&dragReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
@@ -162,7 +161,7 @@ func (r *Router) dragHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) inputHandler(c *gin.Context) {
|
func (r *Router) inputHandler(c *gin.Context) {
|
||||||
var inputReq types.InputRequest
|
var inputReq option.InputRequest
|
||||||
if err := c.ShouldBindJSON(&inputReq); err != nil {
|
if err := c.ShouldBindJSON(&inputReq); err != nil {
|
||||||
RenderErrorValidateRequest(c, err)
|
RenderErrorValidateRequest(c, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v5/uixt/types"
|
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,14 +18,14 @@ func TestTapHandler(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
path string
|
path string
|
||||||
tapReq types.TapRequest
|
tapReq option.TapRequest
|
||||||
wantStatus int
|
wantStatus int
|
||||||
wantResp HttpResponse
|
wantResp HttpResponse
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "tap abs xy",
|
name: "tap abs xy",
|
||||||
path: fmt.Sprintf("/api/v1/android/%s/ui/tap", "4622ca24"),
|
path: fmt.Sprintf("/api/v1/android/%s/ui/tap", "4622ca24"),
|
||||||
tapReq: types.TapRequest{
|
tapReq: option.TapRequest{
|
||||||
X: 500,
|
X: 500,
|
||||||
Y: 800,
|
Y: 800,
|
||||||
Duration: 0,
|
Duration: 0,
|
||||||
@@ -40,7 +40,7 @@ func TestTapHandler(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "tap relative xy",
|
name: "tap relative xy",
|
||||||
path: fmt.Sprintf("/api/v1/android/%s/ui/tap", "4622ca24"),
|
path: fmt.Sprintf("/api/v1/android/%s/ui/tap", "4622ca24"),
|
||||||
tapReq: types.TapRequest{
|
tapReq: option.TapRequest{
|
||||||
X: 0.5,
|
X: 0.5,
|
||||||
Y: 0.6,
|
Y: 0.6,
|
||||||
Duration: 0,
|
Duration: 0,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -16,7 +15,6 @@ import (
|
|||||||
"github.com/httprunner/httprunner/v5/internal/version"
|
"github.com/httprunner/httprunner/v5/internal/version"
|
||||||
"github.com/httprunner/httprunner/v5/pkg/gadb"
|
"github.com/httprunner/httprunner/v5/pkg/gadb"
|
||||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||||
"github.com/httprunner/httprunner/v5/uixt/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewMCPServer creates a new MCP server for XTDriver and registers all tools.
|
// NewMCPServer creates a new MCP server for XTDriver and registers all tools.
|
||||||
@@ -220,7 +218,7 @@ func (t *ToolListPackages) Description() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolListPackages) Options() []mcp.ToolOption {
|
func (t *ToolListPackages) Options() []mcp.ToolOption {
|
||||||
return generateMCPOptions(&types.TargetDeviceRequest{})
|
return option.NewMCPOptions(&option.TargetDeviceRequest{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolListPackages) Implement() toolCall {
|
func (t *ToolListPackages) Implement() toolCall {
|
||||||
@@ -250,7 +248,7 @@ func (t *ToolLaunchApp) Description() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolLaunchApp) Options() []mcp.ToolOption {
|
func (t *ToolLaunchApp) Options() []mcp.ToolOption {
|
||||||
return generateMCPOptions(&types.AppLaunchRequest{})
|
return option.NewMCPOptions(&option.AppLaunchRequest{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolLaunchApp) Implement() toolCall {
|
func (t *ToolLaunchApp) Implement() toolCall {
|
||||||
@@ -259,7 +257,7 @@ func (t *ToolLaunchApp) Implement() toolCall {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var appLaunchReq types.AppLaunchRequest
|
var appLaunchReq option.AppLaunchRequest
|
||||||
if err := mapToStruct(request.Params.Arguments, &appLaunchReq); err != nil {
|
if err := mapToStruct(request.Params.Arguments, &appLaunchReq); err != nil {
|
||||||
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
||||||
}
|
}
|
||||||
@@ -287,7 +285,7 @@ func (t *ToolTerminateApp) Description() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolTerminateApp) Options() []mcp.ToolOption {
|
func (t *ToolTerminateApp) Options() []mcp.ToolOption {
|
||||||
return generateMCPOptions(&types.AppTerminateRequest{})
|
return option.NewMCPOptions(&option.AppTerminateRequest{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolTerminateApp) Implement() toolCall {
|
func (t *ToolTerminateApp) Implement() toolCall {
|
||||||
@@ -296,7 +294,7 @@ func (t *ToolTerminateApp) Implement() toolCall {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var appTerminateReq types.AppTerminateRequest
|
var appTerminateReq option.AppTerminateRequest
|
||||||
if err := mapToStruct(request.Params.Arguments, &appTerminateReq); err != nil {
|
if err := mapToStruct(request.Params.Arguments, &appTerminateReq); err != nil {
|
||||||
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
||||||
}
|
}
|
||||||
@@ -324,7 +322,7 @@ func (t *ToolGetScreenSize) Description() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolGetScreenSize) Options() []mcp.ToolOption {
|
func (t *ToolGetScreenSize) Options() []mcp.ToolOption {
|
||||||
return generateMCPOptions(&types.TargetDeviceRequest{})
|
return option.NewMCPOptions(&option.TargetDeviceRequest{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolGetScreenSize) Implement() toolCall {
|
func (t *ToolGetScreenSize) Implement() toolCall {
|
||||||
@@ -356,7 +354,7 @@ func (t *ToolPressButton) Description() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolPressButton) Options() []mcp.ToolOption {
|
func (t *ToolPressButton) Options() []mcp.ToolOption {
|
||||||
return generateMCPOptions(&types.PressButtonRequest{})
|
return option.NewMCPOptions(&option.PressButtonRequest{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolPressButton) Implement() toolCall {
|
func (t *ToolPressButton) Implement() toolCall {
|
||||||
@@ -365,7 +363,7 @@ func (t *ToolPressButton) Implement() toolCall {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var pressButtonReq types.PressButtonRequest
|
var pressButtonReq option.PressButtonRequest
|
||||||
if err := mapToStruct(request.Params.Arguments, &pressButtonReq); err != nil {
|
if err := mapToStruct(request.Params.Arguments, &pressButtonReq); err != nil {
|
||||||
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
||||||
}
|
}
|
||||||
@@ -389,7 +387,7 @@ func (t *ToolTapXY) Description() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolTapXY) Options() []mcp.ToolOption {
|
func (t *ToolTapXY) Options() []mcp.ToolOption {
|
||||||
return generateMCPOptions(&types.TapRequest{})
|
return option.NewMCPOptions(&option.TapRequest{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolTapXY) Implement() toolCall {
|
func (t *ToolTapXY) Implement() toolCall {
|
||||||
@@ -398,7 +396,7 @@ func (t *ToolTapXY) Implement() toolCall {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return mcp.NewToolResultError("Tap failed: " + err.Error()), nil
|
return mcp.NewToolResultError("Tap failed: " + err.Error()), nil
|
||||||
}
|
}
|
||||||
var tapReq types.TapRequest
|
var tapReq option.TapRequest
|
||||||
if err := mapToStruct(request.Params.Arguments, &tapReq); err != nil {
|
if err := mapToStruct(request.Params.Arguments, &tapReq); err != nil {
|
||||||
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
||||||
}
|
}
|
||||||
@@ -426,7 +424,7 @@ func (t *ToolSwipe) Description() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolSwipe) Options() []mcp.ToolOption {
|
func (t *ToolSwipe) Options() []mcp.ToolOption {
|
||||||
return generateMCPOptions(&types.SwipeRequest{})
|
return option.NewMCPOptions(&option.SwipeRequest{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolSwipe) Implement() toolCall {
|
func (t *ToolSwipe) Implement() toolCall {
|
||||||
@@ -435,7 +433,7 @@ func (t *ToolSwipe) Implement() toolCall {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return mcp.NewToolResultError("Swipe failed: " + err.Error()), nil
|
return mcp.NewToolResultError("Swipe failed: " + err.Error()), nil
|
||||||
}
|
}
|
||||||
var swipeReq types.SwipeRequest
|
var swipeReq option.SwipeRequest
|
||||||
if err := mapToStruct(request.Params.Arguments, &swipeReq); err != nil {
|
if err := mapToStruct(request.Params.Arguments, &swipeReq); err != nil {
|
||||||
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
||||||
}
|
}
|
||||||
@@ -480,7 +478,7 @@ func (t *ToolDrag) Description() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolDrag) Options() []mcp.ToolOption {
|
func (t *ToolDrag) Options() []mcp.ToolOption {
|
||||||
return generateMCPOptions(&types.DragRequest{})
|
return option.NewMCPOptions(&option.DragRequest{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolDrag) Implement() toolCall {
|
func (t *ToolDrag) Implement() toolCall {
|
||||||
@@ -489,7 +487,7 @@ func (t *ToolDrag) Implement() toolCall {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var dragReq types.DragRequest
|
var dragReq option.DragRequest
|
||||||
if err := mapToStruct(request.Params.Arguments, &dragReq); err != nil {
|
if err := mapToStruct(request.Params.Arguments, &dragReq); err != nil {
|
||||||
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
||||||
}
|
}
|
||||||
@@ -521,7 +519,7 @@ func (t *ToolScreenShot) Description() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolScreenShot) Options() []mcp.ToolOption {
|
func (t *ToolScreenShot) Options() []mcp.ToolOption {
|
||||||
return generateMCPOptions(&types.TargetDeviceRequest{})
|
return option.NewMCPOptions(&option.TargetDeviceRequest{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolScreenShot) Implement() toolCall {
|
func (t *ToolScreenShot) Implement() toolCall {
|
||||||
@@ -630,46 +628,6 @@ func NewDevice(platform, serial string) (device IDevice, err error) {
|
|||||||
return device, nil
|
return device, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateMCPOptions generates mcp.NewTool parameters from a struct type.
|
|
||||||
// It automatically generates mcp.NewTool parameters based on the struct fields and their desc tags.
|
|
||||||
func generateMCPOptions(t interface{}) (options []mcp.ToolOption) {
|
|
||||||
tType := reflect.TypeOf(t)
|
|
||||||
for i := 0; i < tType.NumField(); i++ {
|
|
||||||
field := tType.Field(i)
|
|
||||||
jsonTag := field.Tag.Get("json")
|
|
||||||
if jsonTag == "" || jsonTag == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := strings.Split(jsonTag, ",")[0]
|
|
||||||
binding := field.Tag.Get("binding")
|
|
||||||
required := strings.Contains(binding, "required")
|
|
||||||
desc := field.Tag.Get("desc")
|
|
||||||
switch field.Type.Kind() {
|
|
||||||
case reflect.Float64, reflect.Float32, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
if required {
|
|
||||||
options = append(options, mcp.WithNumber(name, mcp.Required(), mcp.Description(desc)))
|
|
||||||
} else {
|
|
||||||
options = append(options, mcp.WithNumber(name, mcp.Description(desc)))
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
if required {
|
|
||||||
options = append(options, mcp.WithString(name, mcp.Required(), mcp.Description(desc)))
|
|
||||||
} else {
|
|
||||||
options = append(options, mcp.WithString(name, mcp.Description(desc)))
|
|
||||||
}
|
|
||||||
case reflect.Bool:
|
|
||||||
if required {
|
|
||||||
options = append(options, mcp.WithBoolean(name, mcp.Required(), mcp.Description(desc)))
|
|
||||||
} else {
|
|
||||||
options = append(options, mcp.WithBoolean(name, mcp.Description(desc)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
log.Warn().Str("field_type", field.Type.String()).Msg("Unsupported field type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return options
|
|
||||||
}
|
|
||||||
|
|
||||||
// mapToStruct convert map[string]interface{} to target struct
|
// mapToStruct convert map[string]interface{} to target struct
|
||||||
func mapToStruct(m map[string]interface{}, out interface{}) error {
|
func mapToStruct(m map[string]interface{}, out interface{}) error {
|
||||||
b, err := json.Marshal(m)
|
b, err := json.Marshal(m)
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
package types
|
package option
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v5/uixt/types"
|
||||||
|
"github.com/mark3labs/mcp-go/mcp"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
type TargetDeviceRequest struct {
|
type TargetDeviceRequest struct {
|
||||||
Platform string `json:"platform" binding:"required" desc:"Device platform: android/ios/browser"`
|
Platform string `json:"platform" binding:"required" desc:"Device platform: android/ios/browser"`
|
||||||
@@ -80,5 +89,45 @@ type AppTerminateRequest struct {
|
|||||||
|
|
||||||
type PressButtonRequest struct {
|
type PressButtonRequest struct {
|
||||||
TargetDeviceRequest
|
TargetDeviceRequest
|
||||||
Button DeviceButton `json:"button" binding:"required" desc:"The button to press. Supported buttons: BACK (android only), HOME, VOLUME_UP, VOLUME_DOWN, ENTER."`
|
Button types.DeviceButton `json:"button" binding:"required" desc:"The button to press. Supported buttons: BACK (android only), HOME, VOLUME_UP, VOLUME_DOWN, ENTER."`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMCPOptions generates mcp.NewTool parameters from a struct type.
|
||||||
|
// It automatically generates mcp.NewTool parameters based on the struct fields and their desc tags.
|
||||||
|
func NewMCPOptions(t interface{}) (options []mcp.ToolOption) {
|
||||||
|
tType := reflect.TypeOf(t)
|
||||||
|
for i := 0; i < tType.NumField(); i++ {
|
||||||
|
field := tType.Field(i)
|
||||||
|
jsonTag := field.Tag.Get("json")
|
||||||
|
if jsonTag == "" || jsonTag == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name := strings.Split(jsonTag, ",")[0]
|
||||||
|
binding := field.Tag.Get("binding")
|
||||||
|
required := strings.Contains(binding, "required")
|
||||||
|
desc := field.Tag.Get("desc")
|
||||||
|
switch field.Type.Kind() {
|
||||||
|
case reflect.Float64, reflect.Float32, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
if required {
|
||||||
|
options = append(options, mcp.WithNumber(name, mcp.Required(), mcp.Description(desc)))
|
||||||
|
} else {
|
||||||
|
options = append(options, mcp.WithNumber(name, mcp.Description(desc)))
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
if required {
|
||||||
|
options = append(options, mcp.WithString(name, mcp.Required(), mcp.Description(desc)))
|
||||||
|
} else {
|
||||||
|
options = append(options, mcp.WithString(name, mcp.Description(desc)))
|
||||||
|
}
|
||||||
|
case reflect.Bool:
|
||||||
|
if required {
|
||||||
|
options = append(options, mcp.WithBoolean(name, mcp.Required(), mcp.Description(desc)))
|
||||||
|
} else {
|
||||||
|
options = append(options, mcp.WithBoolean(name, mcp.Description(desc)))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Warn().Str("field_type", field.Type.String()).Msg("Unsupported field type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return options
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user