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
This commit is contained in:
lilong.129
2025-06-05 23:17:06 +08:00
parent 56831845ca
commit 6e1bd5bbe2
15 changed files with 990 additions and 797 deletions
+40 -38
View File
@@ -14,7 +14,11 @@ import (
)
// ToolSleep implements the sleep tool call.
type ToolSleep struct{}
type ToolSleep struct {
// Return data fields - these define the structure of data returned by this tool
Seconds float64 `json:"seconds" desc:"Duration in seconds that was slept"`
Duration string `json:"duration" desc:"Human-readable duration string"`
}
func (t *ToolSleep) Name() option.ActionName {
return option.ACTION_Sleep
@@ -42,18 +46,23 @@ func (t *ToolSleep) Implement() server.ToolHandlerFunc {
log.Info().Interface("seconds", seconds).Msg("sleeping")
var duration time.Duration
var actualSeconds float64
switch v := seconds.(type) {
case float64:
actualSeconds = v
duration = time.Duration(v*1000) * time.Millisecond
case int:
actualSeconds = float64(v)
duration = time.Duration(v) * time.Second
case int64:
actualSeconds = float64(v)
duration = time.Duration(v) * time.Second
case string:
s, err := builtin.ConvertToFloat64(v)
if err != nil {
return nil, fmt.Errorf("invalid sleep duration: %v", v)
}
actualSeconds = s
duration = time.Duration(s*1000) * time.Millisecond
default:
return nil, fmt.Errorf("unsupported sleep duration type: %T", v)
@@ -61,7 +70,13 @@ func (t *ToolSleep) Implement() server.ToolHandlerFunc {
time.Sleep(duration)
return mcp.NewToolResultText(fmt.Sprintf("Successfully slept for %v seconds", seconds)), nil
message := fmt.Sprintf("Successfully slept for %v seconds", actualSeconds)
returnData := ToolSleep{
Seconds: actualSeconds,
Duration: duration.String(),
}
return NewMCPSuccessResponse(message, &returnData), nil
}
}
@@ -72,15 +87,11 @@ func (t *ToolSleep) ConvertActionToCallToolRequest(action option.MobileAction) (
return buildMCPCallToolRequest(t.Name(), arguments), nil
}
func (t *ToolSleep) ReturnSchema() map[string]string {
return map[string]string{
"message": "string: Success message confirming sleep operation completed",
"seconds": "float64: Duration in seconds that was slept",
}
}
// ToolSleepMS implements the sleep_ms tool call.
type ToolSleepMS struct{}
type ToolSleepMS struct {
// Return data fields - these define the structure of data returned by this tool
Milliseconds int64 `json:"milliseconds" desc:"Duration in milliseconds that was slept"`
}
func (t *ToolSleepMS) Name() option.ActionName {
return option.ACTION_SleepMS
@@ -111,7 +122,10 @@ func (t *ToolSleepMS) Implement() server.ToolHandlerFunc {
log.Info().Int64("milliseconds", unifiedReq.Milliseconds).Msg("sleeping in milliseconds")
time.Sleep(time.Duration(unifiedReq.Milliseconds) * time.Millisecond)
return mcp.NewToolResultText(fmt.Sprintf("Successfully slept for %d milliseconds", unifiedReq.Milliseconds)), nil
message := fmt.Sprintf("Successfully slept for %d milliseconds", unifiedReq.Milliseconds)
returnData := ToolSleepMS{Milliseconds: unifiedReq.Milliseconds}
return NewMCPSuccessResponse(message, &returnData), nil
}
}
@@ -130,15 +144,11 @@ func (t *ToolSleepMS) ConvertActionToCallToolRequest(action option.MobileAction)
return buildMCPCallToolRequest(t.Name(), arguments), nil
}
func (t *ToolSleepMS) ReturnSchema() map[string]string {
return map[string]string{
"message": "string: Success message confirming sleep operation completed",
"milliseconds": "int64: Duration in milliseconds that was slept",
}
}
// ToolSleepRandom implements the sleep_random tool call.
type ToolSleepRandom struct{}
type ToolSleepRandom struct {
// Return data fields - these define the structure of data returned by this tool
Params []float64 `json:"params" desc:"Random sleep parameters used"`
}
func (t *ToolSleepRandom) Name() option.ActionName {
return option.ACTION_SleepRandom
@@ -163,7 +173,10 @@ func (t *ToolSleepRandom) Implement() server.ToolHandlerFunc {
// Sleep random action logic
sleepStrict(time.Now(), getSimulationDuration(unifiedReq.Params))
return mcp.NewToolResultText(fmt.Sprintf("Successfully slept for random duration with params: %v", unifiedReq.Params)), nil
message := fmt.Sprintf("Successfully slept for random duration with params: %v", unifiedReq.Params)
returnData := ToolSleepRandom{Params: unifiedReq.Params}
return NewMCPSuccessResponse(message, &returnData), nil
}
}
@@ -177,16 +190,9 @@ func (t *ToolSleepRandom) ConvertActionToCallToolRequest(action option.MobileAct
return mcp.CallToolRequest{}, fmt.Errorf("invalid sleep random params: %v", action.Params)
}
func (t *ToolSleepRandom) ReturnSchema() map[string]string {
return map[string]string{
"message": "string: Success message confirming random sleep operation completed",
"params": "[]float64: Parameters used for random duration calculation",
"actualDuration": "float64: Actual duration that was slept (in seconds)",
}
}
// ToolClosePopups implements the close_popups tool call.
type ToolClosePopups struct{}
type ToolClosePopups struct { // Return data fields - these define the structure of data returned by this tool
}
func (t *ToolClosePopups) Name() option.ActionName {
return option.ACTION_ClosePopups
@@ -211,20 +217,16 @@ func (t *ToolClosePopups) Implement() server.ToolHandlerFunc {
// Close popups action logic
err = driverExt.ClosePopupsHandler()
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Close popups failed: %s", err.Error())), nil
return NewMCPErrorResponse(fmt.Sprintf("Close popups failed: %s", err.Error())), nil
}
return mcp.NewToolResultText("Successfully closed popups"), nil
message := "Successfully closed popups"
returnData := ToolClosePopups{}
return NewMCPSuccessResponse(message, &returnData), nil
}
}
func (t *ToolClosePopups) ConvertActionToCallToolRequest(action option.MobileAction) (mcp.CallToolRequest, error) {
return buildMCPCallToolRequest(t.Name(), map[string]any{}), nil
}
func (t *ToolClosePopups) ReturnSchema() map[string]string {
return map[string]string{
"message": "string: Success message confirming popups were closed",
"popupsClosed": "int: Number of popup windows or dialogs that were closed",
}
}