mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-25 17:44:02 +08:00
refactor: move server models to uixt/types
This commit is contained in:
@@ -1 +1 @@
|
||||
v5.0.0-beta-2505201326
|
||||
v5.0.0-beta-2505201421
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package mcphost
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/internal/version"
|
||||
"github.com/httprunner/httprunner/v5/uixt"
|
||||
"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/rs/zerolog/log"
|
||||
@@ -20,7 +21,8 @@ import (
|
||||
// MCPServer4XTDriver wraps a MCPServer to expose XTDriver functionality via MCP protocol.
|
||||
type MCPServer4XTDriver struct {
|
||||
mcpServer *server.MCPServer
|
||||
driverCache sync.Map // key is serial, value is *XTDriver
|
||||
driverCache sync.Map // key is serial, value is *XTDriver
|
||||
tools []mcp.Tool // 本地维护的工具列表
|
||||
}
|
||||
|
||||
// NewMCPServer creates a new MCP server for XTDriver and registers all tools.
|
||||
@@ -50,9 +52,10 @@ func (ums *MCPServer4XTDriver) addTools() {
|
||||
[]mcp.ToolOption{mcp.WithDescription("Taps on the device screen at the given coordinates.")},
|
||||
commonToolOptions...,
|
||||
)
|
||||
tapParams = append(tapParams, generateMCPOptions(TapRequest{})...)
|
||||
tapParams = append(tapParams, generateMCPOptions(types.TapRequest{})...)
|
||||
tapXYTool := mcp.NewTool("tap_xy", tapParams...)
|
||||
ums.mcpServer.AddTool(tapXYTool, ums.handleTapXY)
|
||||
ums.tools = append(ums.tools, tapXYTool)
|
||||
log.Info().Str("name", tapXYTool.Name).Msg("Register tool")
|
||||
|
||||
// Swipe Tool
|
||||
@@ -60,9 +63,10 @@ func (ums *MCPServer4XTDriver) addTools() {
|
||||
[]mcp.ToolOption{mcp.WithDescription("Swipes on the device screen from one point to another.")},
|
||||
commonToolOptions...,
|
||||
)
|
||||
swipeParams = append(swipeParams, generateMCPOptions(DragRequest{})...)
|
||||
swipeParams = append(swipeParams, generateMCPOptions(types.DragRequest{})...)
|
||||
swipeTool := mcp.NewTool("swipe", swipeParams...)
|
||||
ums.mcpServer.AddTool(swipeTool, ums.handleSwipe)
|
||||
ums.tools = append(ums.tools, swipeTool)
|
||||
log.Info().Str("name", swipeTool.Name).Msg("Register tool")
|
||||
|
||||
// ScreenShot Tool
|
||||
@@ -70,6 +74,7 @@ func (ums *MCPServer4XTDriver) addTools() {
|
||||
mcp.WithDescription("Takes a screenshot of the device screen and returns it as a base64 encoded string."),
|
||||
)
|
||||
ums.mcpServer.AddTool(screenShotTool, ums.handleScreenShot)
|
||||
ums.tools = append(ums.tools, screenShotTool)
|
||||
log.Info().Str("name", screenShotTool.Name).Msg("Register tool")
|
||||
}
|
||||
|
||||
@@ -79,7 +84,7 @@ func (ums *MCPServer4XTDriver) handleTapXY(ctx context.Context, request mcp.Call
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var tapReq TapRequest
|
||||
var tapReq types.TapRequest
|
||||
if err := mapToStruct(request.Params.Arguments, &tapReq); err != nil {
|
||||
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
||||
}
|
||||
@@ -103,7 +108,7 @@ func (ums *MCPServer4XTDriver) handleSwipe(ctx context.Context, request mcp.Call
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var swipeReq DragRequest
|
||||
var swipeReq types.DragRequest
|
||||
if err := mapToStruct(request.Params.Arguments, &swipeReq); err != nil {
|
||||
return mcp.NewToolResultError("parse parameters error: " + err.Error()), nil
|
||||
}
|
||||
@@ -253,3 +258,18 @@ var commonToolOptions = []mcp.ToolOption{
|
||||
mcp.WithString("platform", mcp.Required(), mcp.Description("Device platform: android/ios/browser")),
|
||||
mcp.WithString("serial", mcp.Required(), mcp.Description("Device serial/udid/browser id")),
|
||||
}
|
||||
|
||||
// ListTools 返回所有注册的 mcp.Tool
|
||||
func (s *MCPServer4XTDriver) ListTools() []mcp.Tool {
|
||||
return s.tools
|
||||
}
|
||||
|
||||
// GetTool 根据名称返回 mcp.Tool 指针
|
||||
func (s *MCPServer4XTDriver) GetTool(name string) *mcp.Tool {
|
||||
for i := range s.tools {
|
||||
if s.tools[i].Name == name {
|
||||
return &s.tools[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -4,12 +4,6 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||
)
|
||||
|
||||
type TapRequest struct {
|
||||
X float64 `json:"x" binding:"required" desc:"X coordinate (0.0~1.0 for percent, or absolute pixel value)"`
|
||||
Y float64 `json:"y" binding:"required" desc:"Y coordinate (0.0~1.0 for percent, or absolute pixel value)"`
|
||||
Duration float64 `json:"duration" desc:"Tap duration in seconds (optional)"`
|
||||
}
|
||||
|
||||
type uploadRequest struct {
|
||||
X float64 `json:"x"`
|
||||
Y float64 `json:"y"`
|
||||
@@ -17,15 +11,6 @@ type uploadRequest struct {
|
||||
FileFormat string `json:"file_format"`
|
||||
}
|
||||
|
||||
type DragRequest struct {
|
||||
FromX float64 `json:"from_x" binding:"required" desc:"Starting X-coordinate (percentage, 0.0 to 1.0)"`
|
||||
FromY float64 `json:"from_y" binding:"required" desc:"Starting Y-coordinate (percentage, 0.0 to 1.0)"`
|
||||
ToX float64 `json:"to_x" binding:"required" desc:"Ending X-coordinate (percentage, 0.0 to 1.0)"`
|
||||
ToY float64 `json:"to_y" binding:"required" desc:"Ending Y-coordinate (percentage, 0.0 to 1.0)"`
|
||||
Duration float64 `json:"duration" desc:"Swipe duration in milliseconds (optional)"`
|
||||
PressDuration float64 `json:"press_duration" desc:"Press duration in milliseconds (optional)"`
|
||||
}
|
||||
|
||||
type InputRequest struct {
|
||||
Text string `json:"text" binding:"required"`
|
||||
Frequency int `json:"frequency"` // only iOS
|
||||
|
||||
@@ -4,10 +4,11 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/httprunner/httprunner/v5/uixt"
|
||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||
"github.com/httprunner/httprunner/v5/uixt/types"
|
||||
)
|
||||
|
||||
func (r *Router) tapHandler(c *gin.Context) {
|
||||
var tapReq TapRequest
|
||||
var tapReq types.TapRequest
|
||||
if err := c.ShouldBindJSON(&tapReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
@@ -30,7 +31,7 @@ func (r *Router) tapHandler(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (r *Router) rightClickHandler(c *gin.Context) {
|
||||
var rightClickReq TapRequest
|
||||
var rightClickReq types.TapRequest
|
||||
if err := c.ShouldBindJSON(&rightClickReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
@@ -117,7 +118,7 @@ func (r *Router) scrollHandler(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (r *Router) doubleTapHandler(c *gin.Context) {
|
||||
var tapReq TapRequest
|
||||
var tapReq types.TapRequest
|
||||
if err := c.ShouldBindJSON(&tapReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
@@ -137,7 +138,7 @@ func (r *Router) doubleTapHandler(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (r *Router) dragHandler(c *gin.Context) {
|
||||
var dragReq DragRequest
|
||||
var dragReq types.DragRequest
|
||||
if err := c.ShouldBindJSON(&dragReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/httprunner/httprunner/v5/uixt/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -17,14 +18,14 @@ func TestTapHandler(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
path string
|
||||
tapReq TapRequest
|
||||
tapReq types.TapRequest
|
||||
wantStatus int
|
||||
wantResp HttpResponse
|
||||
}{
|
||||
{
|
||||
name: "tap abs xy",
|
||||
path: fmt.Sprintf("/api/v1/android/%s/ui/tap", "4622ca24"),
|
||||
tapReq: TapRequest{
|
||||
tapReq: types.TapRequest{
|
||||
X: 500,
|
||||
Y: 800,
|
||||
Duration: 0,
|
||||
@@ -39,7 +40,7 @@ func TestTapHandler(t *testing.T) {
|
||||
{
|
||||
name: "tap relative xy",
|
||||
path: fmt.Sprintf("/api/v1/android/%s/ui/tap", "4622ca24"),
|
||||
tapReq: TapRequest{
|
||||
tapReq: types.TapRequest{
|
||||
X: 0.5,
|
||||
Y: 0.6,
|
||||
Duration: 0,
|
||||
|
||||
16
uixt/types/request.go
Normal file
16
uixt/types/request.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package types
|
||||
|
||||
type TapRequest struct {
|
||||
X float64 `json:"x" binding:"required" desc:"X coordinate (0.0~1.0 for percent, or absolute pixel value)"`
|
||||
Y float64 `json:"y" binding:"required" desc:"Y coordinate (0.0~1.0 for percent, or absolute pixel value)"`
|
||||
Duration float64 `json:"duration" desc:"Tap duration in seconds (optional)"`
|
||||
}
|
||||
|
||||
type DragRequest struct {
|
||||
FromX float64 `json:"from_x" binding:"required" desc:"Starting X-coordinate (percentage, 0.0 to 1.0)"`
|
||||
FromY float64 `json:"from_y" binding:"required" desc:"Starting Y-coordinate (percentage, 0.0 to 1.0)"`
|
||||
ToX float64 `json:"to_x" binding:"required" desc:"Ending X-coordinate (percentage, 0.0 to 1.0)"`
|
||||
ToY float64 `json:"to_y" binding:"required" desc:"Ending Y-coordinate (percentage, 0.0 to 1.0)"`
|
||||
Duration float64 `json:"duration" desc:"Swipe duration in milliseconds (optional)"`
|
||||
PressDuration float64 `json:"press_duration" desc:"Press duration in milliseconds (optional)"`
|
||||
}
|
||||
Reference in New Issue
Block a user