diff --git a/components/tool/mcptool/callresulthandler/main.go b/components/tool/mcptool/callresulthandler/main.go new file mode 100644 index 0000000..575a982 --- /dev/null +++ b/components/tool/mcptool/callresulthandler/main.go @@ -0,0 +1,140 @@ +/* + * Copyright 2025 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "context" + "fmt" + + "github.com/bytedance/sonic" + "github.com/cloudwego/eino-ext/components/tool/mcp/officialmcp" + "github.com/cloudwego/eino/components/tool" + "github.com/cloudwego/eino/compose" + "github.com/cloudwego/eino/schema" + "github.com/modelcontextprotocol/go-sdk/mcp" +) + +// main function demonstrates how to use the tool call result handler. +func main() { + // 1. Initialize context and get tools. + // The GetTools function is configured to use our custom toolCallResultHandler. + ctx := context.Background() + tools, err := GetTools(ctx) + if err != nil { + fmt.Println(err) + return + } + + // 2. Create a new ToolNode. + // A ToolNode is a component that can execute tool calls. + tn, _ := compose.NewToolNode(ctx, &compose.ToolsNodeConfig{ + Tools: tools, + }) + + // 3. Simulate a tool call message from an assistant. + // This message represents a request to call the 'web_search' tool. + msg := schema.AssistantMessage("call web_search tool", []schema.ToolCall{ + { + ID: "1", + Function: schema.FunctionCall{ + Name: "web_search", + Arguments: `{"url":"web_url"}`, + }, + }, + }) + + // 4. Invoke the ToolNode. + // When tn.Invoke is called, it will execute the 'web_search' tool. + // After the tool returns a result, the toolCallResultHandler will be triggered + // to process the result before it is returned here. + result, err := tn.Invoke(ctx, msg) + if err != nil { + fmt.Println(err) + return + } + _ = result + +} + +type detailContent struct { + Summary string + Details string +} + +const webSearchTool = "web_search" + +// toolCallResultHandler is a callback function that gets executed after a tool call. +// It allows for the modification of the tool call's result before it's returned. +// This can be useful for tailoring the output, or in this case, +// condensing the result to save on token usage. +func toolCallResultHandler(ctx context.Context, name string, result *mcp.CallToolResult) (*mcp.CallToolResult, error) { + // First, check if the tool call resulted in an error. + if result.IsError { + marshaledResult, err := sonic.MarshalString(result) + if err != nil { + return nil, err + } + // If there was an error, return it to be handled upstream. + return nil, fmt.Errorf("failed to call official mcp tool, mcp server return error: %s", marshaledResult) + } + + // We're specifically interested in post-processing the 'web_search' tool's output. + if name == webSearchTool && len(result.Content) > 0 { + // The output format of the 'web_search' tool is known and consistent. + // It is expected to return a single content block, which is why we can safely access the first element. + content := result.Content[0] + // We also know that the content will be of type TextContent. + if textContent, ok := content.(*mcp.TextContent); ok { + detailCt := detailContent{} + // The Text field contains a JSON string with 'Summary' and 'Details'. We unmarshal it. + err := sonic.UnmarshalString(textContent.Text, &detailCt) + if err != nil { + return nil, err + } + + // To reduce token consumption for the language model, if the 'Details' are too long (over 1000 chars), + // we replace the content with the shorter 'Summary'. + if len(detailCt.Details) > 1000 { + textContent.Text = detailCt.Summary + } else { + textContent.Text = detailCt.Details + } + + // Update the result content with the potentially modified text. + result.Content[0] = textContent + } + } + + // Return the (possibly modified) result. + return result, nil +} + +// GetTools initializes and returns a list of tools. +// It hooks in the toolCallResultHandler to process the results of any tool calls. +func GetTools(ctx context.Context) ([]tool.BaseTool, error) { + // officialmcp.GetTools is used to get the official MCP tools. + // We provide a custom configuration to it. + tools, err := officialmcp.GetTools(ctx, &officialmcp.Config{ + // ToolCallResultHandler is a field in the config that takes a function. + // This function will be called with the result of every tool call. + ToolCallResultHandler: toolCallResultHandler, + }) + if err != nil { + return nil, err + } + return tools, nil +} diff --git a/components/tool/middlewares/errorremover/errorremover.go b/components/tool/middlewares/errorremover/errorremover.go new file mode 100644 index 0000000..896b938 --- /dev/null +++ b/components/tool/middlewares/errorremover/errorremover.go @@ -0,0 +1,86 @@ +/* + * Copyright 2025 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This example shows how to configure the errorremover middleware on a ToolsNode +// to catch errors during local tool invocation and return custom information. +// Run: go run ./components/tool/middlewares/errorremover/example + +package errorremover + +import ( + "context" + "fmt" + + "github.com/cloudwego/eino/compose" + "github.com/cloudwego/eino/schema" +) + +// removeErrorHandler is an error handler function that generates a string +// describing the error that occurred during a tool call. +func removeErrorHandler(ctx context.Context, in *compose.ToolInput, err error) string { + // Formats the error message to include the tool name and the specific error content. + return fmt.Sprintf("Failed to call tool '%s', error message: '%s'", in.Name, err.Error()) +} + +// Invokable creates a middleware endpoint for non-streaming (invokable) tools. +// It intercepts the tool's execution. If the tool returns an error, it calls the +// error handler and returns its result as a successful ToolOutput, +// effectively suppressing the original error. +func Invokable(next compose.InvokableToolEndpoint) compose.InvokableToolEndpoint { + return func(ctx context.Context, in *compose.ToolInput) (*compose.ToolOutput, error) { + // Proceed with the next middleware or the actual tool execution. + output, err := next(ctx, in) + // If an error occurs during execution. + if err != nil { + // Generate a custom error message using removeErrorHandler. + result := removeErrorHandler(ctx, in, err) + // Wrap the custom message in a successful ToolOutput and return it, + // with the error itself set to nil. + return &compose.ToolOutput{Result: result}, nil + } + // If there was no error, return the original output. + return output, nil + } +} + +// Streamable creates a middleware endpoint for streaming tools. +// It intercepts the tool's execution. If the tool returns an error, it calls the +// error handler and returns its result as a new stream containing a single successful item. +// This effectively replaces the error with a successful stream output. +func Streamable(next compose.StreamableToolEndpoint) compose.StreamableToolEndpoint { + return func(ctx context.Context, in *compose.ToolInput) (*compose.StreamToolOutput, error) { + // Proceed with the next middleware or the actual tool execution. + streamOutput, err := next(ctx, in) + // If an error occurs during execution. + if err != nil { + // Generate a custom error message using removeErrorHandler. + result := removeErrorHandler(ctx, in, err) + // Return the new stream as a successful output. + return &compose.StreamToolOutput{Result: schema.StreamReaderFromArray([]string{result})}, nil + + } + // If there was no error, return the original stream output. + return streamOutput, nil + + } +} + +// Middleware constructs and returns a compose.ToolMiddleware. +// This middleware is designed to catch errors from tool executions and replace them +// with a custom, successful output. +func Middleware() compose.ToolMiddleware { + return compose.ToolMiddleware{Invokable: Invokable, Streamable: Streamable} +} diff --git a/components/tool/middlewares/errorremover/example/main.go b/components/tool/middlewares/errorremover/example/main.go new file mode 100644 index 0000000..0642e5b --- /dev/null +++ b/components/tool/middlewares/errorremover/example/main.go @@ -0,0 +1,86 @@ +/* + * Copyright 2025 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This example shows how to configure the jsonfix middleware on a ToolsNode +// to repair invalid JSON arguments before invoking a local tool. +// Run: go run ./components/tool/middlewares/jsonfix/example + +package main + +import ( + "context" + "fmt" + + "github.com/cloudwego/eino/components/tool" + "github.com/cloudwego/eino/components/tool/utils" + "github.com/cloudwego/eino/compose" + "github.com/cloudwego/eino/schema" + + "github.com/cloudwego/eino-examples/components/tool/middlewares/errorremover" +) + +type WebSearch struct { + URL string `json:"url"` +} + +func main() { + ctx := context.Background() + // 1. Create a mock "web_search" tool. + // This tool is designed to always return an error to demonstrate the middleware's functionality. + searcher, _ := utils.InferTool("web_search", "search content for web url", func(ctx context.Context, in *WebSearch) (string, error) { + // The tool call always fails. + return "", fmt.Errorf("not found web url") + }) + + // 2. Create a compose.ToolNode and inject the remove_error middleware. + // This middleware will intercept the tool execution lifecycle. + // + // IMPORTANT: Middleware order is critical. To catch errors from any subsequent + // middleware or from the tool itself, `remove_error.Middleware()` must be placed + // at the beginning of the `ToolCallMiddlewares` slice. Any middleware placed + // before it will not have its errors handled by this mechanism due to the + // sequential nature of middleware execution. + tn, _ := compose.NewToolNode(ctx, &compose.ToolsNodeConfig{ + Tools: []tool.BaseTool{searcher}, + ToolCallMiddlewares: []compose.ToolMiddleware{errorremover.Middleware()}, // Inject the remove_error middleware. + }) + + msg := schema.AssistantMessage("", []schema.ToolCall{ + { + ID: "1", + Function: schema.FunctionCall{ + Name: "web_search", + Arguments: `{"url":"web_url"}`, + }, + }, + }) + + // 4. Simulate a tool call. + // Although the underlying 'web_search' tool fails, the 'Invoke' call will succeed. + // This is because the middleware catches the error and replaces the output with the result from the registered handler. + outs, err := tn.Invoke(ctx, msg) + if err != nil { + fmt.Println("error:", err) + return + } + + // 5. Print the result. + // The output content will be the string returned by the error handler, not the original error message. + for _, o := range outs { + fmt.Println("tool:", o.ToolName, "id:", o.ToolCallID, "content:", o.Content) + } + +} diff --git a/go.mod b/go.mod index 7a14ac6..75809a7 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.24.7 toolchain go1.24.9 require ( + github.com/alicebob/miniredis/v2 v2.35.0 github.com/bytedance/sonic v1.14.2 github.com/chromedp/chromedp v0.9.5 github.com/cloudwego/eino v0.7.0 @@ -18,6 +19,7 @@ require ( github.com/cloudwego/eino-ext/components/retriever/volc_vikingdb v0.0.0-20251120060928-25485ef519b5 github.com/cloudwego/eino-ext/components/tool/commandline v0.0.0-20251117090452-bd6375a0b3cf github.com/cloudwego/eino-ext/components/tool/duckduckgo/v2 v2.0.0-20251117090452-bd6375a0b3cf + github.com/cloudwego/eino-ext/components/tool/mcp/officialmcp v0.1.0 github.com/cloudwego/eino-ext/devops v0.1.8 github.com/coze-dev/cozeloop-go v0.1.11 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc @@ -25,7 +27,9 @@ require ( github.com/google/uuid v1.6.0 github.com/json-iterator/go v1.1.12 github.com/kaptinlin/jsonrepair v0.2.4 + github.com/mark3labs/mcp-go v0.43.2 github.com/pkoukk/tiktoken-go v0.1.8 + github.com/redis/go-redis/v9 v9.17.2 github.com/stretchr/testify v1.11.1 github.com/volcengine/volcengine-go-sdk v1.1.44 github.com/wk8/go-ordered-map/v2 v2.1.8 @@ -35,7 +39,6 @@ require ( require ( github.com/PuerkitoBio/goquery v1.10.3 // indirect - github.com/alicebob/miniredis/v2 v2.35.0 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect @@ -62,9 +65,11 @@ require ( github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/ws v1.3.2 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect + github.com/google/jsonschema-go v0.3.0 // indirect github.com/goph/emperror v0.17.2 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/mux v1.8.1 // indirect + github.com/invopop/jsonschema v0.13.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/joho/godotenv v1.5.1 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -74,6 +79,7 @@ require ( github.com/mattn/go-colorable v0.1.14 // indirect github.com/meguminnnnnnnnn/go-openai v0.1.0 // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect + github.com/modelcontextprotocol/go-sdk v1.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/nikolalohinski/gonja v1.5.3 // indirect @@ -83,11 +89,11 @@ require ( github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/redis/go-redis/v9 v9.17.2 // indirect github.com/richardlehane/mscfb v1.0.4 // indirect github.com/richardlehane/msoleps v1.0.4 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/slongfield/pyfmt v0.0.0-20220222012616-ea85ff4c361f // indirect + github.com/spf13/cast v1.7.1 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect @@ -100,6 +106,7 @@ require ( github.com/xuri/efp v0.0.1 // indirect github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect github.com/yargevad/filepathx v1.0.0 // indirect + github.com/yosida95/uritemplate/v3 v3.0.2 // indirect github.com/yuin/gopher-lua v1.1.1 // indirect golang.org/x/arch v0.19.0 // indirect golang.org/x/crypto v0.43.0 // indirect diff --git a/go.sum b/go.sum index 4f0e966..3c5ace0 100644 --- a/go.sum +++ b/go.sum @@ -84,6 +84,10 @@ github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngE github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bugsnag/bugsnag-go v1.4.0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= @@ -103,7 +107,6 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -146,6 +149,8 @@ github.com/cloudwego/eino-ext/components/tool/commandline v0.0.0-20251117090452- github.com/cloudwego/eino-ext/components/tool/commandline v0.0.0-20251117090452-bd6375a0b3cf/go.mod h1:cMZb1KM71kM+2hTJwxLwXT+HC66HimZirDDA5Oo64Hw= github.com/cloudwego/eino-ext/components/tool/duckduckgo/v2 v2.0.0-20251117090452-bd6375a0b3cf h1:54xcNETtXP1gYieDuNyOIvzE4Mk/jOxjlqCERr4cxTk= github.com/cloudwego/eino-ext/components/tool/duckduckgo/v2 v2.0.0-20251117090452-bd6375a0b3cf/go.mod h1:Np0BXy/9hPRu3wCgn+ij6L7YsjFcybVzg1k7uYOXh0M= +github.com/cloudwego/eino-ext/components/tool/mcp/officialmcp v0.1.0 h1:4haF2hnv7+t9JUc4E+6SHo7cRgpi+6hux+YeteT5CW8= +github.com/cloudwego/eino-ext/components/tool/mcp/officialmcp v0.1.0/go.mod h1:9kDYHgPkYf249MhpGxGxx21MRFdKzTRyK4wDxmowo7o= github.com/cloudwego/eino-ext/devops v0.1.8 h1:qBg5vjZSDnd9tHzCHG8YsjnGB5vKG2EoZuuQCI8qrGs= github.com/cloudwego/eino-ext/devops v0.1.8/go.mod h1:8yjvPNTaB5Ve4aJmJ0ysFgB10y3YbIuqMh0/Uwt5Fnw= github.com/cloudwego/eino-ext/libs/acl/openai v0.1.2 h1:r9Id2wzJ05PoHl+Km7jQgNMgciaZI93TVnUYso89esM= @@ -204,6 +209,8 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= @@ -293,6 +300,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/jsonschema-go v0.3.0 h1:6AH2TxVNtk3IlvkkhjrtbUc4S8AvO0Xii0DxIygDg+Q= +github.com/google/jsonschema-go v0.3.0/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -358,6 +367,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= +github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= @@ -414,6 +425,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/mark3labs/mcp-go v0.43.2 h1:21PUSlWWiSbUPQwXIJ5WKlETixpFpq+WBpbMGDSVy/I= +github.com/mark3labs/mcp-go v0.43.2/go.mod h1:YnJfOL382MIWDx1kMY+2zsRHU/q78dBg9aFb8W6Thdw= github.com/matoous/go-nanoid v1.5.1 h1:aCjdvTyO9LLnTIi0fgdXhOPPvOHjpXN6Ik9DaNjIct4= github.com/matoous/go-nanoid v1.5.1/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -448,6 +461,8 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modelcontextprotocol/go-sdk v1.0.0 h1:Z4MSjLi38bTgLrd/LjSmofqRqyBiVKRyQSJgw8q8V74= +github.com/modelcontextprotocol/go-sdk v1.0.0/go.mod h1:nYtYQroQ2KQiM0/SbyEPUWQ6xs4B95gJjEalc9AQyOs= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -568,6 +583,8 @@ github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sS github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -629,6 +646,8 @@ github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBL github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= github.com/yargevad/filepathx v1.0.0 h1:SYcT+N3tYGi+NvazubCNlvgIPbzAk7i7y2dwg3I5FYc= github.com/yargevad/filepathx v1.0.0/go.mod h1:BprfX/gpYNJHJfc35GjRRpVcwWXS89gGulUIU5tK3tA= +github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= +github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=