mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-01-11 08:28:11 -05:00
Compare commits
13 Commits
binary-npx
...
mongodb-in
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c6f290481 | ||
|
|
768cbdc07c | ||
|
|
6a7edab6e6 | ||
|
|
71b751c400 | ||
|
|
7815dce6a0 | ||
|
|
6b4dd50a20 | ||
|
|
7e814804aa | ||
|
|
296a7a7aa8 | ||
|
|
b37aedd880 | ||
|
|
3a19e46d63 | ||
|
|
2c6eb4f47f | ||
|
|
8a8649b789 | ||
|
|
9159550089 |
@@ -73,6 +73,8 @@ import (
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbdeleteone"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbfind"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbfindone"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbinsertmany"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbinsertone"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbupdatemany"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbupdateone"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mssql/mssqlexecutesql"
|
||||
|
||||
52
docs/en/resources/tools/mongodb/mongodb-insert-many.md
Normal file
52
docs/en/resources/tools/mongodb/mongodb-insert-many.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "mongodb-insert-many"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "mongodb-insert-many" tool inserts multiple new documents into a MongoDB collection.
|
||||
aliases:
|
||||
- /resources/tools/mongodb-insert-many
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
The `mongodb-insert-many` tool inserts **multiple new documents** into a specified MongoDB collection in a single bulk operation. This is highly efficient for adding large amounts of data at once.
|
||||
|
||||
This tool takes one required parameter named `data`. This `data` parameter must be a string containing a **JSON array of document objects**. Upon successful insertion, the tool returns a JSON array containing the unique `_id` of **each** new document that was created.
|
||||
|
||||
This tool is compatible with the following source kind:
|
||||
|
||||
* [`mongodb`](../../sources/mongodb.md)
|
||||
|
||||
---
|
||||
|
||||
## Example
|
||||
|
||||
Here is an example configuration for a tool that logs multiple events at once.
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
log_batch_events:
|
||||
kind: mongodb-insert-many
|
||||
source: my-mongo-source
|
||||
description: Inserts a batch of event logs into the database.
|
||||
database: logging
|
||||
collection: events
|
||||
canonical: true
|
||||
```
|
||||
|
||||
An LLM would call this tool by providing an array of documents as a JSON string in the `data` parameter, like this:
|
||||
`tool_code: log_batch_events(data='[{"event": "login", "user": "user1"}, {"event": "click", "user": "user2"}, {"event": "logout", "user": "user1"}]')`
|
||||
|
||||
---
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|:------------|:---------|:-------------|:---------------------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be `mongodb-insert-many`. |
|
||||
| source | string | true | The name of the `mongodb` source to use. |
|
||||
| description | string | true | A description of the tool that is passed to the LLM. |
|
||||
| database | string | true | The name of the MongoDB database containing the collection. |
|
||||
| collection | string | true | The name of the MongoDB collection into which the documents will be inserted. |
|
||||
| canonical | bool | true | Determines if the data string is parsed using MongoDB's Canonical or Relaxed Extended JSON format. |
|
||||
48
docs/en/resources/tools/mongodb/mongodb-insert-one.md
Normal file
48
docs/en/resources/tools/mongodb/mongodb-insert-one.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "mongodb-insert-one"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "mongodb-insert-one" tool inserts a single new document into a MongoDB collection.
|
||||
aliases:
|
||||
- /resources/tools/mongodb-insert-one
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
The `mongodb-insert-one` tool inserts a **single new document** into a specified MongoDB collection.
|
||||
|
||||
This tool takes one required parameter named `data`, which must be a string containing the JSON object you want to insert. Upon successful insertion, the tool returns the unique `_id` of the newly created document.
|
||||
|
||||
This tool is compatible with the following source kind:
|
||||
|
||||
* [`mongodb`](../../sources/mongodb.md)
|
||||
|
||||
## Example
|
||||
|
||||
Here is an example configuration for a tool that adds a new user to a `users` collection.
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
create_new_user:
|
||||
kind: mongodb-insert-one
|
||||
source: my-mongo-source
|
||||
description: Creates a new user record in the database.
|
||||
database: user_data
|
||||
collection: users
|
||||
canonical: false
|
||||
```
|
||||
|
||||
An LLM would call this tool by providing the document as a JSON string in the `data` parameter, like this:
|
||||
`tool_code: create_new_user(data='{"email": "new.user@example.com", "name": "Jane Doe", "status": "active"}')`
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|:------------|:---------|:-------------|:---------------------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be `mongodb-insert-one`. |
|
||||
| source | string | true | The name of the `mongodb` source to use. |
|
||||
| description | string | true | A description of the tool that is passed to the LLM. |
|
||||
| database | string | true | The name of the MongoDB database containing the collection. |
|
||||
| collection | string | true | The name of the MongoDB collection into which the document will be inserted. |
|
||||
| canonical | bool | true | Determines if the data string is parsed using MongoDB's Canonical or Relaxed Extended JSON format. |
|
||||
@@ -104,7 +104,7 @@ func PopulateTemplateWithJSON(templateName, templateString string, data map[stri
|
||||
return result.String(), nil
|
||||
}
|
||||
|
||||
// Verify there are no duplicate parameter names
|
||||
// CheckDuplicateParameters verify there are no duplicate parameter names
|
||||
func CheckDuplicateParameters(ps Parameters) error {
|
||||
seenNames := make(map[string]bool)
|
||||
for _, p := range ps {
|
||||
|
||||
167
internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany.go
Normal file
167
internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany.go
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// 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 mongodbinsertmany
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/goccy/go-yaml"
|
||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||
mongosrc "github.com/googleapis/genai-toolbox/internal/sources/mongodb"
|
||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
const kind string = "mongodb-insert-many"
|
||||
|
||||
const paramDataKey = "data"
|
||||
|
||||
func init() {
|
||||
if !tools.Register(kind, newConfig) {
|
||||
panic(fmt.Sprintf("tool kind %q already registered", kind))
|
||||
}
|
||||
}
|
||||
|
||||
func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.ToolConfig, error) {
|
||||
actual := Config{Name: name}
|
||||
if err := decoder.DecodeContext(ctx, &actual); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return actual, nil
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Name string `yaml:"name" validate:"required"`
|
||||
Kind string `yaml:"kind" validate:"required"`
|
||||
Source string `yaml:"source" validate:"required"`
|
||||
AuthRequired []string `yaml:"authRequired" validate:"required"`
|
||||
Description string `yaml:"description" validate:"required"`
|
||||
Database string `yaml:"database" validate:"required"`
|
||||
Collection string `yaml:"collection" validate:"required"`
|
||||
Canonical bool `yaml:"canonical" validate:"required"` //i want to force the user to choose
|
||||
}
|
||||
|
||||
// validate interface
|
||||
var _ tools.ToolConfig = Config{}
|
||||
|
||||
func (cfg Config) ToolConfigKind() string {
|
||||
return kind
|
||||
}
|
||||
|
||||
func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) {
|
||||
// verify source exists
|
||||
rawS, ok := srcs[cfg.Source]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no source named %q configured", cfg.Source)
|
||||
}
|
||||
|
||||
// verify the source is compatible
|
||||
s, ok := rawS.(*mongosrc.Source)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid source for %q tool: source kind must be `mongodb`", kind)
|
||||
}
|
||||
|
||||
dataParam := tools.NewStringParameterWithRequired(paramDataKey, "the JSON payload to insert, should be a JSON array of documents", true)
|
||||
|
||||
allParameters := tools.Parameters{dataParam}
|
||||
|
||||
// Create Toolbox manifest
|
||||
paramManifest := allParameters.Manifest()
|
||||
|
||||
if paramManifest == nil {
|
||||
paramManifest = make([]tools.ParameterManifest, 0)
|
||||
}
|
||||
|
||||
// Create MCP manifest
|
||||
mcpManifest := tools.McpManifest{
|
||||
Name: cfg.Name,
|
||||
Description: cfg.Description,
|
||||
InputSchema: allParameters.McpManifest(),
|
||||
}
|
||||
// finish tool setup
|
||||
return Tool{
|
||||
Name: cfg.Name,
|
||||
Kind: kind,
|
||||
AuthRequired: cfg.AuthRequired,
|
||||
Collection: cfg.Collection,
|
||||
Canonical: cfg.Canonical,
|
||||
PayloadParams: allParameters,
|
||||
database: s.Client.Database(cfg.Database),
|
||||
manifest: tools.Manifest{Description: cfg.Description, Parameters: paramManifest, AuthRequired: cfg.AuthRequired},
|
||||
mcpManifest: mcpManifest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// validate interface
|
||||
var _ tools.Tool = Tool{}
|
||||
|
||||
type Tool struct {
|
||||
Name string `yaml:"name"`
|
||||
Kind string `yaml:"kind"`
|
||||
AuthRequired []string `yaml:"authRequired"`
|
||||
Description string `yaml:"description"`
|
||||
Collection string `yaml:"collection"`
|
||||
Canonical bool `yaml:"canonical" validation:"required"` //i want to force the user to choose
|
||||
PayloadParams tools.Parameters
|
||||
|
||||
database *mongo.Database
|
||||
manifest tools.Manifest
|
||||
mcpManifest tools.McpManifest
|
||||
}
|
||||
|
||||
func (t Tool) Invoke(ctx context.Context, params tools.ParamValues) (any, error) {
|
||||
if len(params) == 0 {
|
||||
return nil, errors.New("no input found")
|
||||
}
|
||||
|
||||
paramsMap := params.AsMap()
|
||||
|
||||
var jsonData, ok = paramsMap[paramDataKey].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("no input found")
|
||||
}
|
||||
|
||||
var data = []any{}
|
||||
err := bson.UnmarshalExtJSON([]byte(jsonData), t.Canonical, &data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := t.database.Collection(t.Collection).InsertMany(ctx, data, options.InsertMany())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res.InsertedIDs, nil
|
||||
}
|
||||
|
||||
func (t Tool) ParseParams(data map[string]any, claims map[string]map[string]any) (tools.ParamValues, error) {
|
||||
return tools.ParseParams(t.PayloadParams, data, claims)
|
||||
}
|
||||
|
||||
func (t Tool) Manifest() tools.Manifest {
|
||||
return t.manifest
|
||||
}
|
||||
|
||||
func (t Tool) McpManifest() tools.McpManifest {
|
||||
return t.mcpManifest
|
||||
}
|
||||
|
||||
func (t Tool) Authorized(verifiedAuthServices []string) bool {
|
||||
return tools.IsAuthorized(t.AuthRequired, verifiedAuthServices)
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// 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 mongodbinsertmany_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbinsertmany"
|
||||
|
||||
yaml "github.com/goccy/go-yaml"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/googleapis/genai-toolbox/internal/server"
|
||||
"github.com/googleapis/genai-toolbox/internal/testutils"
|
||||
)
|
||||
|
||||
func TestParseFromYamlMongoQuery(t *testing.T) {
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
tcs := []struct {
|
||||
desc string
|
||||
in string
|
||||
want server.ToolConfigs
|
||||
}{
|
||||
{
|
||||
desc: "basic example",
|
||||
in: `
|
||||
tools:
|
||||
example_tool:
|
||||
kind: mongodb-insert-many
|
||||
source: my-instance
|
||||
description: some description
|
||||
database: test_db
|
||||
collection: test_coll
|
||||
canonical: true
|
||||
`,
|
||||
want: server.ToolConfigs{
|
||||
"example_tool": mongodbinsertmany.Config{
|
||||
Name: "example_tool",
|
||||
Kind: "mongodb-insert-many",
|
||||
Source: "my-instance",
|
||||
AuthRequired: []string{},
|
||||
Database: "test_db",
|
||||
Collection: "test_coll",
|
||||
Description: "some description",
|
||||
Canonical: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
got := struct {
|
||||
Tools server.ToolConfigs `yaml:"tools"`
|
||||
}{}
|
||||
// Parse contents
|
||||
err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to unmarshal: %s", err)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
|
||||
t.Fatalf("incorrect parse: diff %v", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestFailParseFromYamlMongoQuery(t *testing.T) {
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
tcs := []struct {
|
||||
desc string
|
||||
in string
|
||||
err string
|
||||
}{
|
||||
{
|
||||
desc: "Invalid method",
|
||||
in: `
|
||||
tools:
|
||||
example_tool:
|
||||
kind: mongodb-insert-many
|
||||
source: my-instance
|
||||
description: some description
|
||||
collection: test_coll
|
||||
`,
|
||||
err: `unable to parse tool "example_tool" as kind "mongodb-insert-many"`,
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
got := struct {
|
||||
Tools server.ToolConfigs `yaml:"tools"`
|
||||
}{}
|
||||
// Parse contents
|
||||
err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
|
||||
if err == nil {
|
||||
t.Fatalf("expect parsing to fail")
|
||||
}
|
||||
errStr := err.Error()
|
||||
if !strings.Contains(errStr, tc.err) {
|
||||
t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
166
internal/tools/mongodb/mongodbinsertone/mongodbinsertone.go
Normal file
166
internal/tools/mongodb/mongodbinsertone/mongodbinsertone.go
Normal file
@@ -0,0 +1,166 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// 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 mongodbinsertone
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/goccy/go-yaml"
|
||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||
mongosrc "github.com/googleapis/genai-toolbox/internal/sources/mongodb"
|
||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
const kind string = "mongodb-insert-one"
|
||||
|
||||
const dataParamsKey = "data"
|
||||
|
||||
func init() {
|
||||
if !tools.Register(kind, newConfig) {
|
||||
panic(fmt.Sprintf("tool kind %q already registered", kind))
|
||||
}
|
||||
}
|
||||
|
||||
func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.ToolConfig, error) {
|
||||
actual := Config{Name: name}
|
||||
if err := decoder.DecodeContext(ctx, &actual); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return actual, nil
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Name string `yaml:"name" validate:"required"`
|
||||
Kind string `yaml:"kind" validate:"required"`
|
||||
Source string `yaml:"source" validate:"required"`
|
||||
AuthRequired []string `yaml:"authRequired" validate:"required"`
|
||||
Description string `yaml:"description" validate:"required"`
|
||||
Database string `yaml:"database" validate:"required"`
|
||||
Collection string `yaml:"collection" validate:"required"`
|
||||
Canonical bool `yaml:"canonical" validate:"required"` //i want to force the user to choose
|
||||
}
|
||||
|
||||
// validate interface
|
||||
var _ tools.ToolConfig = Config{}
|
||||
|
||||
func (cfg Config) ToolConfigKind() string {
|
||||
return kind
|
||||
}
|
||||
|
||||
func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) {
|
||||
// verify source exists
|
||||
rawS, ok := srcs[cfg.Source]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no source named %q configured", cfg.Source)
|
||||
}
|
||||
|
||||
// verify the source is compatible
|
||||
s, ok := rawS.(*mongosrc.Source)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid source for %q tool: source kind must be `mongodb`", kind)
|
||||
}
|
||||
|
||||
payloadParams := tools.NewStringParameterWithRequired(dataParamsKey, "the JSON payload to insert, should be a JSON object", true)
|
||||
|
||||
allParameters := tools.Parameters{payloadParams}
|
||||
|
||||
// Create Toolbox manifest
|
||||
paramManifest := allParameters.Manifest()
|
||||
|
||||
if paramManifest == nil {
|
||||
paramManifest = make([]tools.ParameterManifest, 0)
|
||||
}
|
||||
|
||||
// Create MCP manifest
|
||||
mcpManifest := tools.McpManifest{
|
||||
Name: cfg.Name,
|
||||
Description: cfg.Description,
|
||||
InputSchema: allParameters.McpManifest(),
|
||||
}
|
||||
|
||||
// finish tool setup
|
||||
return Tool{
|
||||
Name: cfg.Name,
|
||||
Kind: kind,
|
||||
AuthRequired: cfg.AuthRequired,
|
||||
Collection: cfg.Collection,
|
||||
Canonical: cfg.Canonical,
|
||||
PayloadParams: allParameters,
|
||||
database: s.Client.Database(cfg.Database),
|
||||
manifest: tools.Manifest{Description: cfg.Description, Parameters: paramManifest, AuthRequired: cfg.AuthRequired},
|
||||
mcpManifest: mcpManifest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// validate interface
|
||||
var _ tools.Tool = Tool{}
|
||||
|
||||
type Tool struct {
|
||||
Name string `yaml:"name"`
|
||||
Kind string `yaml:"kind"`
|
||||
AuthRequired []string `yaml:"authRequired"`
|
||||
Description string `yaml:"description"`
|
||||
Collection string `yaml:"collection"`
|
||||
Canonical bool `yaml:"canonical" validation:"required"`
|
||||
PayloadParams tools.Parameters `yaml:"payloadParams" validate:"required"`
|
||||
|
||||
database *mongo.Database
|
||||
manifest tools.Manifest
|
||||
mcpManifest tools.McpManifest
|
||||
}
|
||||
|
||||
func (t Tool) Invoke(ctx context.Context, params tools.ParamValues) (any, error) {
|
||||
if len(params) == 0 {
|
||||
return nil, errors.New("no input found")
|
||||
}
|
||||
// use the first, assume it's a string
|
||||
var jsonData, ok = params[0].Value.(string)
|
||||
if !ok {
|
||||
return nil, errors.New("no input found")
|
||||
}
|
||||
|
||||
var data any
|
||||
err := bson.UnmarshalExtJSON([]byte(jsonData), t.Canonical, &data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := t.database.Collection(t.Collection).InsertOne(ctx, data, options.InsertOne())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res.InsertedID, nil
|
||||
}
|
||||
|
||||
func (t Tool) ParseParams(data map[string]any, claims map[string]map[string]any) (tools.ParamValues, error) {
|
||||
return tools.ParseParams(t.PayloadParams, data, claims)
|
||||
}
|
||||
|
||||
func (t Tool) Manifest() tools.Manifest {
|
||||
return t.manifest
|
||||
}
|
||||
|
||||
func (t Tool) McpManifest() tools.McpManifest {
|
||||
return t.mcpManifest
|
||||
}
|
||||
|
||||
func (t Tool) Authorized(verifiedAuthServices []string) bool {
|
||||
return tools.IsAuthorized(t.AuthRequired, verifiedAuthServices)
|
||||
}
|
||||
124
internal/tools/mongodb/mongodbinsertone/mongodbinsertone_test.go
Normal file
124
internal/tools/mongodb/mongodbinsertone/mongodbinsertone_test.go
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// 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 mongodbinsertone_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbinsertone"
|
||||
|
||||
yaml "github.com/goccy/go-yaml"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/googleapis/genai-toolbox/internal/server"
|
||||
"github.com/googleapis/genai-toolbox/internal/testutils"
|
||||
)
|
||||
|
||||
func TestParseFromYamlMongoQuery(t *testing.T) {
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
tcs := []struct {
|
||||
desc string
|
||||
in string
|
||||
want server.ToolConfigs
|
||||
}{
|
||||
{
|
||||
desc: "basic example",
|
||||
in: `
|
||||
tools:
|
||||
example_tool:
|
||||
kind: mongodb-insert-one
|
||||
source: my-instance
|
||||
description: some description
|
||||
database: test_db
|
||||
collection: test_coll
|
||||
canonical: true
|
||||
`,
|
||||
want: server.ToolConfigs{
|
||||
"example_tool": mongodbinsertone.Config{
|
||||
Name: "example_tool",
|
||||
Kind: "mongodb-insert-one",
|
||||
Source: "my-instance",
|
||||
AuthRequired: []string{},
|
||||
Database: "test_db",
|
||||
Collection: "test_coll",
|
||||
Canonical: true,
|
||||
Description: "some description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
got := struct {
|
||||
Tools server.ToolConfigs `yaml:"tools"`
|
||||
}{}
|
||||
// Parse contents
|
||||
err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to unmarshal: %s", err)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
|
||||
t.Fatalf("incorrect parse: diff %v", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestFailParseFromYamlMongoQuery(t *testing.T) {
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
tcs := []struct {
|
||||
desc string
|
||||
in string
|
||||
err string
|
||||
}{
|
||||
{
|
||||
desc: "Invalid method",
|
||||
in: `
|
||||
tools:
|
||||
example_tool:
|
||||
kind: mongodb-insert-one
|
||||
source: my-instance
|
||||
description: some description
|
||||
collection: test_coll
|
||||
canonical: true
|
||||
`,
|
||||
err: `unable to parse tool "example_tool" as kind "mongodb-insert-one"`,
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
got := struct {
|
||||
Tools server.ToolConfigs `yaml:"tools"`
|
||||
}{}
|
||||
// Parse contents
|
||||
err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
|
||||
if err == nil {
|
||||
t.Fatalf("expect parsing to fail")
|
||||
}
|
||||
errStr := err.Error()
|
||||
if !strings.Contains(errStr, tc.err) {
|
||||
t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -55,7 +55,7 @@ type Config struct {
|
||||
FilterParams tools.Parameters `yaml:"filterParams" validate:"required"`
|
||||
UpdatePayload string `yaml:"updatePayload" validate:"required"`
|
||||
UpdateParams tools.Parameters `yaml:"updateParams" validate:"required"`
|
||||
Canonical bool `yaml:"canonical" validate:"required"` //i want to force the user to choose
|
||||
Canonical bool `yaml:"canonical" validate:"required"`
|
||||
Upsert bool `yaml:"upsert"`
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ type Tool struct {
|
||||
UpdatePayload string `yaml:"updatePayload" validate:"required"`
|
||||
UpdateParams tools.Parameters `yaml:"updateParams" validate:"required"`
|
||||
AllParams tools.Parameters `yaml:"allParams"`
|
||||
Canonical bool `yaml:"canonical" validation:"required"` //i want to force the user to choose
|
||||
Canonical bool `yaml:"canonical" validation:"required"`
|
||||
Upsert bool `yaml:"upsert"`
|
||||
|
||||
database *mongo.Database
|
||||
|
||||
@@ -56,7 +56,7 @@ type Config struct {
|
||||
UpdatePayload string `yaml:"updatePayload" validate:"required"`
|
||||
UpdateParams tools.Parameters `yaml:"updateParams" validate:"required"`
|
||||
|
||||
Canonical bool `yaml:"canonical" validate:"required"` //i want to force the user to choose
|
||||
Canonical bool `yaml:"canonical" validate:"required"`
|
||||
Upsert bool `yaml:"upsert"`
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user