From 29d8725215dc46b244dade2eed969157f98c6c1c Mon Sep 17 00:00:00 2001 From: lianghui Date: Mon, 14 Apr 2025 18:05:17 +0800 Subject: [PATCH 1/2] feat:Added the parameter parsing mode to parse any to the specified type --- go.mod | 1 + go.sum | 12 +++++++ mcp/tools_test.go | 68 ++++++++++++++++++++++++++++++++++++++ mcp/utils.go | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+) diff --git a/go.mod b/go.mod index 940f05dec..9b9fe2d48 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.23 require ( github.com/google/uuid v1.6.0 + github.com/spf13/cast v1.7.1 github.com/stretchr/testify v1.9.0 github.com/yosida95/uritemplate/v3 v3.0.2 ) diff --git a/go.sum b/go.sum index 14437f708..31ed86d18 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,21 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= diff --git a/mcp/tools_test.go b/mcp/tools_test.go index 31a5b93ed..872749e19 100644 --- a/mcp/tools_test.go +++ b/mcp/tools_test.go @@ -2,6 +2,7 @@ package mcp import ( "encoding/json" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -240,3 +241,70 @@ func TestToolWithObjectAndArray(t *testing.T) { assert.True(t, ok) assert.Contains(t, required, "books") } + +func TestParseToolCallToolRequest(t *testing.T) { + request := CallToolRequest{} + request.Params.Name = "test-tool" + request.Params.Arguments = map[string]interface{}{ + "bool_value": "true", + "int64_value": "123456789", + "int32_value": "123456789", + "int16_value": "123456789", + "int8_value": "123456789", + "int_value": "123456789", + "uint_value": "123456789", + "uint64_value": "123456789", + "uint32_value": "123456789", + "uint16_value": "123456789", + "uint8_value": "123456789", + "float32_value": "3.14", + "float64_value": "3.1415926", + "string_value": "hello", + } + param1 := ParseBoolean(request, "bool_value", false) + assert.Equal(t, fmt.Sprintf("%T", param1), "bool") + + param2 := ParseInt64(request, "int64_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param2), "int64") + + param3 := ParseInt32(request, "int32_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param3), "int32") + + param4 := ParseInt16(request, "int16_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param4), "int16") + + param5 := ParseInt8(request, "int8_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param5), "int8") + + param6 := ParseInt(request, "int_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param6), "int") + + param7 := ParseUInt(request, "uint_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param7), "uint") + + param8 := ParseUInt64(request, "uint64_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param8), "uint64") + + param9 := ParseUInt32(request, "uint32_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param9), "uint32") + + param10 := ParseUInt16(request, "uint16_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param10), "uint16") + + param11 := ParseUInt8(request, "uint8_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param11), "uint8") + + param12 := ParseFloat32(request, "float32_value", 1.0) + assert.Equal(t, fmt.Sprintf("%T", param12), "float32") + + param13 := ParseFloat64(request, "float64_value", 1.0) + assert.Equal(t, fmt.Sprintf("%T", param13), "float64") + + param14 := ParseString(request, "string_value", "") + assert.Equal(t, fmt.Sprintf("%T", param14), "string") + + param15 := ParseInt64(request, "string_value", 1) + assert.Equal(t, fmt.Sprintf("%T", param15), "int64") + t.Logf("param15 type: %T,value:%v", param15, param15) + +} diff --git a/mcp/utils.go b/mcp/utils.go index 236164cbd..7d1921c43 100644 --- a/mcp/utils.go +++ b/mcp/utils.go @@ -3,6 +3,7 @@ package mcp import ( "encoding/json" "fmt" + "github.com/spf13/cast" ) // ClientRequest types @@ -594,3 +595,86 @@ func ParseReadResourceResult(rawMessage *json.RawMessage) (*ReadResourceResult, return &result, nil } + +func ParseArgument(request CallToolRequest, key string, defaultVal any) any { + if _, ok := request.Params.Arguments[key]; !ok { + return defaultVal + } else { + return request.Params.Arguments[key] + } +} + +func ParseBoolean(request CallToolRequest, key string, defaultValue bool) bool { + v := ParseArgument(request, key, defaultValue) + return cast.ToBool(v) +} + +func ParseInt64(request CallToolRequest, key string, defaultValue int64) int64 { + v := ParseArgument(request, key, defaultValue) + return cast.ToInt64(v) +} + +func ParseInt32(request CallToolRequest, key string, defaultValue int32) int32 { + v := ParseArgument(request, key, defaultValue) + return cast.ToInt32(v) +} + +func ParseInt16(request CallToolRequest, key string, defaultValue int16) int16 { + v := ParseArgument(request, key, defaultValue) + return cast.ToInt16(v) +} + +func ParseInt8(request CallToolRequest, key string, defaultValue int8) int8 { + v := ParseArgument(request, key, defaultValue) + return cast.ToInt8(v) +} + +func ParseInt(request CallToolRequest, key string, defaultValue int) int { + v := ParseArgument(request, key, defaultValue) + return cast.ToInt(v) +} + +func ParseUInt(request CallToolRequest, key string, defaultValue uint) uint { + v := ParseArgument(request, key, defaultValue) + return cast.ToUint(v) +} + +func ParseUInt64(request CallToolRequest, key string, defaultValue uint64) uint64 { + v := ParseArgument(request, key, defaultValue) + return cast.ToUint64(v) +} + +func ParseUInt32(request CallToolRequest, key string, defaultValue uint32) uint32 { + v := ParseArgument(request, key, defaultValue) + return cast.ToUint32(v) +} + +func ParseUInt16(request CallToolRequest, key string, defaultValue uint16) uint16 { + v := ParseArgument(request, key, defaultValue) + return cast.ToUint16(v) +} + +func ParseUInt8(request CallToolRequest, key string, defaultValue uint8) uint8 { + v := ParseArgument(request, key, defaultValue) + return cast.ToUint8(v) +} + +func ParseFloat32(request CallToolRequest, key string, defaultValue float32) float32 { + v := ParseArgument(request, key, defaultValue) + return cast.ToFloat32(v) +} + +func ParseFloat64(request CallToolRequest, key string, defaultValue float64) float64 { + v := ParseArgument(request, key, defaultValue) + return cast.ToFloat64(v) +} + +func ParseString(request CallToolRequest, key string, defaultValue string) string { + v := ParseArgument(request, key, defaultValue) + return cast.ToString(v) +} + +func ParseStringMap(request CallToolRequest, key string, defaultValue map[string]any) map[string]any { + v := ParseArgument(request, key, defaultValue) + return cast.ToStringMap(v) +} From 0fe6dbd4e9fb10097fc7ab83f0d632a06774e1c6 Mon Sep 17 00:00:00 2001 From: lianghui Date: Mon, 14 Apr 2025 18:18:22 +0800 Subject: [PATCH 2/2] docs:AAdd GoDoc comments to exported functions. --- mcp/utils.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/mcp/utils.go b/mcp/utils.go index 7d1921c43..131b50da6 100644 --- a/mcp/utils.go +++ b/mcp/utils.go @@ -604,76 +604,95 @@ func ParseArgument(request CallToolRequest, key string, defaultVal any) any { } } +// ParseBoolean extracts and converts a boolean parameter from a CallToolRequest. +// If the key is not found in the Arguments map, the defaultValue is returned. +// The function uses cast.ToBool for conversion which handles various string representations +// such as "true", "yes", "1", etc. func ParseBoolean(request CallToolRequest, key string, defaultValue bool) bool { v := ParseArgument(request, key, defaultValue) return cast.ToBool(v) } +// ParseInt64 extracts and converts an int64 parameter from a CallToolRequest. +// If the key is not found in the Arguments map, the defaultValue is returned. func ParseInt64(request CallToolRequest, key string, defaultValue int64) int64 { v := ParseArgument(request, key, defaultValue) return cast.ToInt64(v) } +// ParseInt32 extracts and converts an int32 parameter from a CallToolRequest. func ParseInt32(request CallToolRequest, key string, defaultValue int32) int32 { v := ParseArgument(request, key, defaultValue) return cast.ToInt32(v) } +// ParseInt16 extracts and converts an int16 parameter from a CallToolRequest. func ParseInt16(request CallToolRequest, key string, defaultValue int16) int16 { v := ParseArgument(request, key, defaultValue) return cast.ToInt16(v) } +// ParseInt8 extracts and converts an int8 parameter from a CallToolRequest. func ParseInt8(request CallToolRequest, key string, defaultValue int8) int8 { v := ParseArgument(request, key, defaultValue) return cast.ToInt8(v) } +// ParseInt extracts and converts an int parameter from a CallToolRequest. func ParseInt(request CallToolRequest, key string, defaultValue int) int { v := ParseArgument(request, key, defaultValue) return cast.ToInt(v) } +// ParseUInt extracts and converts an uint parameter from a CallToolRequest. func ParseUInt(request CallToolRequest, key string, defaultValue uint) uint { v := ParseArgument(request, key, defaultValue) return cast.ToUint(v) } +// ParseUInt64 extracts and converts an uint64 parameter from a CallToolRequest. func ParseUInt64(request CallToolRequest, key string, defaultValue uint64) uint64 { v := ParseArgument(request, key, defaultValue) return cast.ToUint64(v) } +// ParseUInt32 extracts and converts an uint32 parameter from a CallToolRequest. func ParseUInt32(request CallToolRequest, key string, defaultValue uint32) uint32 { v := ParseArgument(request, key, defaultValue) return cast.ToUint32(v) } +// ParseUInt16 extracts and converts an uint16 parameter from a CallToolRequest. func ParseUInt16(request CallToolRequest, key string, defaultValue uint16) uint16 { v := ParseArgument(request, key, defaultValue) return cast.ToUint16(v) } +// ParseUInt8 extracts and converts an uint8 parameter from a CallToolRequest. func ParseUInt8(request CallToolRequest, key string, defaultValue uint8) uint8 { v := ParseArgument(request, key, defaultValue) return cast.ToUint8(v) } +// ParseFloat32 extracts and converts a float32 parameter from a CallToolRequest. func ParseFloat32(request CallToolRequest, key string, defaultValue float32) float32 { v := ParseArgument(request, key, defaultValue) return cast.ToFloat32(v) } +// ParseFloat64 extracts and converts a float64 parameter from a CallToolRequest. func ParseFloat64(request CallToolRequest, key string, defaultValue float64) float64 { v := ParseArgument(request, key, defaultValue) return cast.ToFloat64(v) } +// ParseString extracts and converts a string parameter from a CallToolRequest. func ParseString(request CallToolRequest, key string, defaultValue string) string { v := ParseArgument(request, key, defaultValue) return cast.ToString(v) } +// ParseStringMap extracts and converts a string map parameter from a CallToolRequest. func ParseStringMap(request CallToolRequest, key string, defaultValue map[string]any) map[string]any { v := ParseArgument(request, key, defaultValue) return cast.ToStringMap(v)