#
tokens: 49880/50000 32/786 files (page 6/45)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 6 of 45. Use http://codebase.md/googleapis/genai-toolbox?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .ci
│   ├── continuous.release.cloudbuild.yaml
│   ├── generate_release_table.sh
│   ├── integration.cloudbuild.yaml
│   ├── quickstart_test
│   │   ├── go.integration.cloudbuild.yaml
│   │   ├── js.integration.cloudbuild.yaml
│   │   ├── py.integration.cloudbuild.yaml
│   │   ├── run_go_tests.sh
│   │   ├── run_js_tests.sh
│   │   ├── run_py_tests.sh
│   │   └── setup_hotels_sample.sql
│   ├── test_with_coverage.sh
│   └── versioned.release.cloudbuild.yaml
├── .github
│   ├── auto-label.yaml
│   ├── blunderbuss.yml
│   ├── CODEOWNERS
│   ├── header-checker-lint.yml
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   ├── feature_request.yml
│   │   └── question.yml
│   ├── label-sync.yml
│   ├── labels.yaml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── release-please.yml
│   ├── renovate.json5
│   ├── sync-repo-settings.yaml
│   └── workflows
│       ├── cloud_build_failure_reporter.yml
│       ├── deploy_dev_docs.yaml
│       ├── deploy_previous_version_docs.yaml
│       ├── deploy_versioned_docs.yaml
│       ├── docs_deploy.yaml
│       ├── docs_preview_clean.yaml
│       ├── docs_preview_deploy.yaml
│       ├── lint.yaml
│       ├── schedule_reporter.yml
│       ├── sync-labels.yaml
│       └── tests.yaml
├── .gitignore
├── .gitmodules
├── .golangci.yaml
├── .hugo
│   ├── archetypes
│   │   └── default.md
│   ├── assets
│   │   ├── icons
│   │   │   └── logo.svg
│   │   └── scss
│   │       ├── _styles_project.scss
│   │       └── _variables_project.scss
│   ├── go.mod
│   ├── go.sum
│   ├── hugo.toml
│   ├── layouts
│   │   ├── _default
│   │   │   └── home.releases.releases
│   │   ├── index.llms-full.txt
│   │   ├── index.llms.txt
│   │   ├── partials
│   │   │   ├── hooks
│   │   │   │   └── head-end.html
│   │   │   ├── navbar-version-selector.html
│   │   │   ├── page-meta-links.html
│   │   │   └── td
│   │   │       └── render-heading.html
│   │   ├── robot.txt
│   │   └── shortcodes
│   │       ├── include.html
│   │       ├── ipynb.html
│   │       └── regionInclude.html
│   ├── package-lock.json
│   ├── package.json
│   └── static
│       ├── favicons
│       │   ├── android-chrome-192x192.png
│       │   ├── android-chrome-512x512.png
│       │   ├── apple-touch-icon.png
│       │   ├── favicon-16x16.png
│       │   ├── favicon-32x32.png
│       │   └── favicon.ico
│       └── js
│           └── w3.js
├── CHANGELOG.md
├── cmd
│   ├── options_test.go
│   ├── options.go
│   ├── root_test.go
│   ├── root.go
│   └── version.txt
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── DEVELOPER.md
├── Dockerfile
├── docs
│   └── en
│       ├── _index.md
│       ├── about
│       │   ├── _index.md
│       │   └── faq.md
│       ├── concepts
│       │   ├── _index.md
│       │   └── telemetry
│       │       ├── index.md
│       │       ├── telemetry_flow.png
│       │       └── telemetry_traces.png
│       ├── getting-started
│       │   ├── _index.md
│       │   ├── colab_quickstart.ipynb
│       │   ├── configure.md
│       │   ├── introduction
│       │   │   ├── _index.md
│       │   │   └── architecture.png
│       │   ├── local_quickstart_go.md
│       │   ├── local_quickstart_js.md
│       │   ├── local_quickstart.md
│       │   ├── mcp_quickstart
│       │   │   ├── _index.md
│       │   │   ├── inspector_tools.png
│       │   │   └── inspector.png
│       │   └── quickstart
│       │       ├── go
│       │       │   ├── genAI
│       │       │   │   ├── go.mod
│       │       │   │   ├── go.sum
│       │       │   │   └── quickstart.go
│       │       │   ├── genkit
│       │       │   │   ├── go.mod
│       │       │   │   ├── go.sum
│       │       │   │   └── quickstart.go
│       │       │   ├── langchain
│       │       │   │   ├── go.mod
│       │       │   │   ├── go.sum
│       │       │   │   └── quickstart.go
│       │       │   ├── openAI
│       │       │   │   ├── go.mod
│       │       │   │   ├── go.sum
│       │       │   │   └── quickstart.go
│       │       │   └── quickstart_test.go
│       │       ├── golden.txt
│       │       ├── js
│       │       │   ├── genAI
│       │       │   │   ├── package-lock.json
│       │       │   │   ├── package.json
│       │       │   │   └── quickstart.js
│       │       │   ├── genkit
│       │       │   │   ├── package-lock.json
│       │       │   │   ├── package.json
│       │       │   │   └── quickstart.js
│       │       │   ├── langchain
│       │       │   │   ├── package-lock.json
│       │       │   │   ├── package.json
│       │       │   │   └── quickstart.js
│       │       │   ├── llamaindex
│       │       │   │   ├── package-lock.json
│       │       │   │   ├── package.json
│       │       │   │   └── quickstart.js
│       │       │   └── quickstart.test.js
│       │       ├── python
│       │       │   ├── __init__.py
│       │       │   ├── adk
│       │       │   │   ├── quickstart.py
│       │       │   │   └── requirements.txt
│       │       │   ├── core
│       │       │   │   ├── quickstart.py
│       │       │   │   └── requirements.txt
│       │       │   ├── langchain
│       │       │   │   ├── quickstart.py
│       │       │   │   └── requirements.txt
│       │       │   ├── llamaindex
│       │       │   │   ├── quickstart.py
│       │       │   │   └── requirements.txt
│       │       │   └── quickstart_test.py
│       │       └── shared
│       │           ├── cloud_setup.md
│       │           ├── configure_toolbox.md
│       │           └── database_setup.md
│       ├── how-to
│       │   ├── _index.md
│       │   ├── connect_via_geminicli.md
│       │   ├── connect_via_mcp.md
│       │   ├── connect-ide
│       │   │   ├── _index.md
│       │   │   ├── alloydb_pg_admin_mcp.md
│       │   │   ├── alloydb_pg_mcp.md
│       │   │   ├── bigquery_mcp.md
│       │   │   ├── cloud_sql_mssql_admin_mcp.md
│       │   │   ├── cloud_sql_mssql_mcp.md
│       │   │   ├── cloud_sql_mysql_admin_mcp.md
│       │   │   ├── cloud_sql_mysql_mcp.md
│       │   │   ├── cloud_sql_pg_admin_mcp.md
│       │   │   ├── cloud_sql_pg_mcp.md
│       │   │   ├── firestore_mcp.md
│       │   │   ├── looker_mcp.md
│       │   │   ├── mssql_mcp.md
│       │   │   ├── mysql_mcp.md
│       │   │   ├── neo4j_mcp.md
│       │   │   ├── postgres_mcp.md
│       │   │   ├── spanner_mcp.md
│       │   │   └── sqlite_mcp.md
│       │   ├── deploy_docker.md
│       │   ├── deploy_gke.md
│       │   ├── deploy_toolbox.md
│       │   ├── export_telemetry.md
│       │   └── toolbox-ui
│       │       ├── edit-headers.gif
│       │       ├── edit-headers.png
│       │       ├── index.md
│       │       ├── optional-param-checked.png
│       │       ├── optional-param-unchecked.png
│       │       ├── run-tool.gif
│       │       ├── tools.png
│       │       └── toolsets.png
│       ├── reference
│       │   ├── _index.md
│       │   ├── cli.md
│       │   └── prebuilt-tools.md
│       ├── resources
│       │   ├── _index.md
│       │   ├── authServices
│       │   │   ├── _index.md
│       │   │   └── google.md
│       │   ├── sources
│       │   │   ├── _index.md
│       │   │   ├── alloydb-admin.md
│       │   │   ├── alloydb-pg.md
│       │   │   ├── bigquery.md
│       │   │   ├── bigtable.md
│       │   │   ├── cassandra.md
│       │   │   ├── clickhouse.md
│       │   │   ├── cloud-monitoring.md
│       │   │   ├── cloud-sql-admin.md
│       │   │   ├── cloud-sql-mssql.md
│       │   │   ├── cloud-sql-mysql.md
│       │   │   ├── cloud-sql-pg.md
│       │   │   ├── couchbase.md
│       │   │   ├── dataplex.md
│       │   │   ├── dgraph.md
│       │   │   ├── firebird.md
│       │   │   ├── firestore.md
│       │   │   ├── http.md
│       │   │   ├── looker.md
│       │   │   ├── mongodb.md
│       │   │   ├── mssql.md
│       │   │   ├── mysql.md
│       │   │   ├── neo4j.md
│       │   │   ├── oceanbase.md
│       │   │   ├── oracle.md
│       │   │   ├── postgres.md
│       │   │   ├── redis.md
│       │   │   ├── spanner.md
│       │   │   ├── sqlite.md
│       │   │   ├── tidb.md
│       │   │   ├── trino.md
│       │   │   ├── valkey.md
│       │   │   └── yugabytedb.md
│       │   └── tools
│       │       ├── _index.md
│       │       ├── alloydb
│       │       │   ├── _index.md
│       │       │   ├── alloydb-create-cluster.md
│       │       │   ├── alloydb-create-instance.md
│       │       │   ├── alloydb-create-user.md
│       │       │   ├── alloydb-get-cluster.md
│       │       │   ├── alloydb-get-instance.md
│       │       │   ├── alloydb-get-user.md
│       │       │   ├── alloydb-list-clusters.md
│       │       │   ├── alloydb-list-instances.md
│       │       │   ├── alloydb-list-users.md
│       │       │   └── alloydb-wait-for-operation.md
│       │       ├── alloydbainl
│       │       │   ├── _index.md
│       │       │   └── alloydb-ai-nl.md
│       │       ├── bigquery
│       │       │   ├── _index.md
│       │       │   ├── bigquery-analyze-contribution.md
│       │       │   ├── bigquery-conversational-analytics.md
│       │       │   ├── bigquery-execute-sql.md
│       │       │   ├── bigquery-forecast.md
│       │       │   ├── bigquery-get-dataset-info.md
│       │       │   ├── bigquery-get-table-info.md
│       │       │   ├── bigquery-list-dataset-ids.md
│       │       │   ├── bigquery-list-table-ids.md
│       │       │   ├── bigquery-search-catalog.md
│       │       │   └── bigquery-sql.md
│       │       ├── bigtable
│       │       │   ├── _index.md
│       │       │   └── bigtable-sql.md
│       │       ├── cassandra
│       │       │   ├── _index.md
│       │       │   └── cassandra-cql.md
│       │       ├── clickhouse
│       │       │   ├── _index.md
│       │       │   ├── clickhouse-execute-sql.md
│       │       │   ├── clickhouse-list-databases.md
│       │       │   ├── clickhouse-list-tables.md
│       │       │   └── clickhouse-sql.md
│       │       ├── cloudmonitoring
│       │       │   ├── _index.md
│       │       │   └── cloud-monitoring-query-prometheus.md
│       │       ├── cloudsql
│       │       │   ├── _index.md
│       │       │   ├── cloudsqlcreatedatabase.md
│       │       │   ├── cloudsqlcreateusers.md
│       │       │   ├── cloudsqlgetinstances.md
│       │       │   ├── cloudsqllistdatabases.md
│       │       │   ├── cloudsqllistinstances.md
│       │       │   ├── cloudsqlmssqlcreateinstance.md
│       │       │   ├── cloudsqlmysqlcreateinstance.md
│       │       │   ├── cloudsqlpgcreateinstances.md
│       │       │   └── cloudsqlwaitforoperation.md
│       │       ├── couchbase
│       │       │   ├── _index.md
│       │       │   └── couchbase-sql.md
│       │       ├── dataform
│       │       │   ├── _index.md
│       │       │   └── dataform-compile-local.md
│       │       ├── dataplex
│       │       │   ├── _index.md
│       │       │   ├── dataplex-lookup-entry.md
│       │       │   ├── dataplex-search-aspect-types.md
│       │       │   └── dataplex-search-entries.md
│       │       ├── dgraph
│       │       │   ├── _index.md
│       │       │   └── dgraph-dql.md
│       │       ├── firebird
│       │       │   ├── _index.md
│       │       │   ├── firebird-execute-sql.md
│       │       │   └── firebird-sql.md
│       │       ├── firestore
│       │       │   ├── _index.md
│       │       │   ├── firestore-add-documents.md
│       │       │   ├── firestore-delete-documents.md
│       │       │   ├── firestore-get-documents.md
│       │       │   ├── firestore-get-rules.md
│       │       │   ├── firestore-list-collections.md
│       │       │   ├── firestore-query-collection.md
│       │       │   ├── firestore-query.md
│       │       │   ├── firestore-update-document.md
│       │       │   └── firestore-validate-rules.md
│       │       ├── http
│       │       │   ├── _index.md
│       │       │   └── http.md
│       │       ├── looker
│       │       │   ├── _index.md
│       │       │   ├── looker-add-dashboard-element.md
│       │       │   ├── looker-conversational-analytics.md
│       │       │   ├── looker-get-dashboards.md
│       │       │   ├── looker-get-dimensions.md
│       │       │   ├── looker-get-explores.md
│       │       │   ├── looker-get-filters.md
│       │       │   ├── looker-get-looks.md
│       │       │   ├── looker-get-measures.md
│       │       │   ├── looker-get-models.md
│       │       │   ├── looker-get-parameters.md
│       │       │   ├── looker-health-analyze.md
│       │       │   ├── looker-health-pulse.md
│       │       │   ├── looker-health-vacuum.md
│       │       │   ├── looker-make-dashboard.md
│       │       │   ├── looker-make-look.md
│       │       │   ├── looker-query-sql.md
│       │       │   ├── looker-query-url.md
│       │       │   ├── looker-query.md
│       │       │   └── looker-run-look.md
│       │       ├── mongodb
│       │       │   ├── _index.md
│       │       │   ├── mongodb-aggregate.md
│       │       │   ├── mongodb-delete-many.md
│       │       │   ├── mongodb-delete-one.md
│       │       │   ├── mongodb-find-one.md
│       │       │   ├── mongodb-find.md
│       │       │   ├── mongodb-insert-many.md
│       │       │   ├── mongodb-insert-one.md
│       │       │   ├── mongodb-update-many.md
│       │       │   └── mongodb-update-one.md
│       │       ├── mssql
│       │       │   ├── _index.md
│       │       │   ├── mssql-execute-sql.md
│       │       │   ├── mssql-list-tables.md
│       │       │   └── mssql-sql.md
│       │       ├── mysql
│       │       │   ├── _index.md
│       │       │   ├── mysql-execute-sql.md
│       │       │   ├── mysql-list-active-queries.md
│       │       │   ├── mysql-list-table-fragmentation.md
│       │       │   ├── mysql-list-tables-missing-unique-indexes.md
│       │       │   ├── mysql-list-tables.md
│       │       │   └── mysql-sql.md
│       │       ├── neo4j
│       │       │   ├── _index.md
│       │       │   ├── neo4j-cypher.md
│       │       │   ├── neo4j-execute-cypher.md
│       │       │   └── neo4j-schema.md
│       │       ├── oceanbase
│       │       │   ├── _index.md
│       │       │   ├── oceanbase-execute-sql.md
│       │       │   └── oceanbase-sql.md
│       │       ├── oracle
│       │       │   ├── _index.md
│       │       │   ├── oracle-execute-sql.md
│       │       │   └── oracle-sql.md
│       │       ├── postgres
│       │       │   ├── _index.md
│       │       │   ├── postgres-execute-sql.md
│       │       │   ├── postgres-list-active-queries.md
│       │       │   ├── postgres-list-available-extensions.md
│       │       │   ├── postgres-list-installed-extensions.md
│       │       │   ├── postgres-list-tables.md
│       │       │   └── postgres-sql.md
│       │       ├── redis
│       │       │   ├── _index.md
│       │       │   └── redis.md
│       │       ├── spanner
│       │       │   ├── _index.md
│       │       │   ├── spanner-execute-sql.md
│       │       │   ├── spanner-list-tables.md
│       │       │   └── spanner-sql.md
│       │       ├── sqlite
│       │       │   ├── _index.md
│       │       │   ├── sqlite-execute-sql.md
│       │       │   └── sqlite-sql.md
│       │       ├── tidb
│       │       │   ├── _index.md
│       │       │   ├── tidb-execute-sql.md
│       │       │   └── tidb-sql.md
│       │       ├── trino
│       │       │   ├── _index.md
│       │       │   ├── trino-execute-sql.md
│       │       │   └── trino-sql.md
│       │       ├── utility
│       │       │   ├── _index.md
│       │       │   └── wait.md
│       │       ├── valkey
│       │       │   ├── _index.md
│       │       │   └── valkey.md
│       │       └── yuagbytedb
│       │           ├── _index.md
│       │           └── yugabytedb-sql.md
│       ├── samples
│       │   ├── _index.md
│       │   ├── alloydb
│       │   │   ├── _index.md
│       │   │   ├── ai-nl
│       │   │   │   ├── alloydb_ai_nl.ipynb
│       │   │   │   └── index.md
│       │   │   └── mcp_quickstart.md
│       │   ├── bigquery
│       │   │   ├── _index.md
│       │   │   ├── colab_quickstart_bigquery.ipynb
│       │   │   ├── local_quickstart.md
│       │   │   └── mcp_quickstart
│       │   │       ├── _index.md
│       │   │       ├── inspector_tools.png
│       │   │       └── inspector.png
│       │   └── looker
│       │       ├── _index.md
│       │       ├── looker_gemini_oauth
│       │       │   ├── _index.md
│       │       │   ├── authenticated.png
│       │       │   ├── authorize.png
│       │       │   └── registration.png
│       │       ├── looker_gemini.md
│       │       └── looker_mcp_inspector
│       │           ├── _index.md
│       │           ├── inspector_tools.png
│       │           └── inspector.png
│       └── sdks
│           ├── _index.md
│           ├── go-sdk.md
│           ├── js-sdk.md
│           └── python-sdk.md
├── gemini-extension.json
├── go.mod
├── go.sum
├── internal
│   ├── auth
│   │   ├── auth.go
│   │   └── google
│   │       └── google.go
│   ├── log
│   │   ├── handler.go
│   │   ├── log_test.go
│   │   ├── log.go
│   │   └── logger.go
│   ├── prebuiltconfigs
│   │   ├── prebuiltconfigs_test.go
│   │   ├── prebuiltconfigs.go
│   │   └── tools
│   │       ├── alloydb-postgres-admin.yaml
│   │       ├── alloydb-postgres-observability.yaml
│   │       ├── alloydb-postgres.yaml
│   │       ├── bigquery.yaml
│   │       ├── clickhouse.yaml
│   │       ├── cloud-sql-mssql-admin.yaml
│   │       ├── cloud-sql-mssql-observability.yaml
│   │       ├── cloud-sql-mssql.yaml
│   │       ├── cloud-sql-mysql-admin.yaml
│   │       ├── cloud-sql-mysql-observability.yaml
│   │       ├── cloud-sql-mysql.yaml
│   │       ├── cloud-sql-postgres-admin.yaml
│   │       ├── cloud-sql-postgres-observability.yaml
│   │       ├── cloud-sql-postgres.yaml
│   │       ├── dataplex.yaml
│   │       ├── firestore.yaml
│   │       ├── looker-conversational-analytics.yaml
│   │       ├── looker.yaml
│   │       ├── mssql.yaml
│   │       ├── mysql.yaml
│   │       ├── neo4j.yaml
│   │       ├── oceanbase.yaml
│   │       ├── postgres.yaml
│   │       ├── spanner-postgres.yaml
│   │       ├── spanner.yaml
│   │       └── sqlite.yaml
│   ├── server
│   │   ├── api_test.go
│   │   ├── api.go
│   │   ├── common_test.go
│   │   ├── config.go
│   │   ├── mcp
│   │   │   ├── jsonrpc
│   │   │   │   ├── jsonrpc_test.go
│   │   │   │   └── jsonrpc.go
│   │   │   ├── mcp.go
│   │   │   ├── util
│   │   │   │   └── lifecycle.go
│   │   │   ├── v20241105
│   │   │   │   ├── method.go
│   │   │   │   └── types.go
│   │   │   ├── v20250326
│   │   │   │   ├── method.go
│   │   │   │   └── types.go
│   │   │   └── v20250618
│   │   │       ├── method.go
│   │   │       └── types.go
│   │   ├── mcp_test.go
│   │   ├── mcp.go
│   │   ├── server_test.go
│   │   ├── server.go
│   │   ├── static
│   │   │   ├── assets
│   │   │   │   └── mcptoolboxlogo.png
│   │   │   ├── css
│   │   │   │   └── style.css
│   │   │   ├── index.html
│   │   │   ├── js
│   │   │   │   ├── auth.js
│   │   │   │   ├── loadTools.js
│   │   │   │   ├── mainContent.js
│   │   │   │   ├── navbar.js
│   │   │   │   ├── runTool.js
│   │   │   │   ├── toolDisplay.js
│   │   │   │   ├── tools.js
│   │   │   │   └── toolsets.js
│   │   │   ├── tools.html
│   │   │   └── toolsets.html
│   │   ├── web_test.go
│   │   └── web.go
│   ├── sources
│   │   ├── alloydbadmin
│   │   │   ├── alloydbadmin_test.go
│   │   │   └── alloydbadmin.go
│   │   ├── alloydbpg
│   │   │   ├── alloydb_pg_test.go
│   │   │   └── alloydb_pg.go
│   │   ├── bigquery
│   │   │   ├── bigquery_test.go
│   │   │   └── bigquery.go
│   │   ├── bigtable
│   │   │   ├── bigtable_test.go
│   │   │   └── bigtable.go
│   │   ├── cassandra
│   │   │   ├── cassandra_test.go
│   │   │   └── cassandra.go
│   │   ├── clickhouse
│   │   │   ├── clickhouse_test.go
│   │   │   └── clickhouse.go
│   │   ├── cloudmonitoring
│   │   │   ├── cloud_monitoring_test.go
│   │   │   └── cloud_monitoring.go
│   │   ├── cloudsqladmin
│   │   │   ├── cloud_sql_admin_test.go
│   │   │   └── cloud_sql_admin.go
│   │   ├── cloudsqlmssql
│   │   │   ├── cloud_sql_mssql_test.go
│   │   │   └── cloud_sql_mssql.go
│   │   ├── cloudsqlmysql
│   │   │   ├── cloud_sql_mysql_test.go
│   │   │   └── cloud_sql_mysql.go
│   │   ├── cloudsqlpg
│   │   │   ├── cloud_sql_pg_test.go
│   │   │   └── cloud_sql_pg.go
│   │   ├── couchbase
│   │   │   ├── couchbase_test.go
│   │   │   └── couchbase.go
│   │   ├── dataplex
│   │   │   ├── dataplex_test.go
│   │   │   └── dataplex.go
│   │   ├── dgraph
│   │   │   ├── dgraph_test.go
│   │   │   └── dgraph.go
│   │   ├── dialect.go
│   │   ├── firebird
│   │   │   ├── firebird_test.go
│   │   │   └── firebird.go
│   │   ├── firestore
│   │   │   ├── firestore_test.go
│   │   │   └── firestore.go
│   │   ├── http
│   │   │   ├── http_test.go
│   │   │   └── http.go
│   │   ├── ip_type.go
│   │   ├── looker
│   │   │   ├── looker_test.go
│   │   │   └── looker.go
│   │   ├── mongodb
│   │   │   ├── mongodb_test.go
│   │   │   └── mongodb.go
│   │   ├── mssql
│   │   │   ├── mssql_test.go
│   │   │   └── mssql.go
│   │   ├── mysql
│   │   │   ├── mysql_test.go
│   │   │   └── mysql.go
│   │   ├── neo4j
│   │   │   ├── neo4j_test.go
│   │   │   └── neo4j.go
│   │   ├── oceanbase
│   │   │   ├── oceanbase_test.go
│   │   │   └── oceanbase.go
│   │   ├── oracle
│   │   │   └── oracle.go
│   │   ├── postgres
│   │   │   ├── postgres_test.go
│   │   │   └── postgres.go
│   │   ├── redis
│   │   │   ├── redis_test.go
│   │   │   └── redis.go
│   │   ├── sources.go
│   │   ├── spanner
│   │   │   ├── spanner_test.go
│   │   │   └── spanner.go
│   │   ├── sqlite
│   │   │   ├── sqlite_test.go
│   │   │   └── sqlite.go
│   │   ├── tidb
│   │   │   ├── tidb_test.go
│   │   │   └── tidb.go
│   │   ├── trino
│   │   │   ├── trino_test.go
│   │   │   └── trino.go
│   │   ├── util.go
│   │   ├── valkey
│   │   │   ├── valkey_test.go
│   │   │   └── valkey.go
│   │   └── yugabytedb
│   │       ├── yugabytedb_test.go
│   │       └── yugabytedb.go
│   ├── telemetry
│   │   ├── instrumentation.go
│   │   └── telemetry.go
│   ├── testutils
│   │   └── testutils.go
│   ├── tools
│   │   ├── alloydb
│   │   │   ├── alloydbcreatecluster
│   │   │   │   ├── alloydbcreatecluster_test.go
│   │   │   │   └── alloydbcreatecluster.go
│   │   │   ├── alloydbcreateinstance
│   │   │   │   ├── alloydbcreateinstance_test.go
│   │   │   │   └── alloydbcreateinstance.go
│   │   │   ├── alloydbcreateuser
│   │   │   │   ├── alloydbcreateuser_test.go
│   │   │   │   └── alloydbcreateuser.go
│   │   │   ├── alloydbgetcluster
│   │   │   │   ├── alloydbgetcluster_test.go
│   │   │   │   └── alloydbgetcluster.go
│   │   │   ├── alloydbgetinstance
│   │   │   │   ├── alloydbgetinstance_test.go
│   │   │   │   └── alloydbgetinstance.go
│   │   │   ├── alloydbgetuser
│   │   │   │   ├── alloydbgetuser_test.go
│   │   │   │   └── alloydbgetuser.go
│   │   │   ├── alloydblistclusters
│   │   │   │   ├── alloydblistclusters_test.go
│   │   │   │   └── alloydblistclusters.go
│   │   │   ├── alloydblistinstances
│   │   │   │   ├── alloydblistinstances_test.go
│   │   │   │   └── alloydblistinstances.go
│   │   │   ├── alloydblistusers
│   │   │   │   ├── alloydblistusers_test.go
│   │   │   │   └── alloydblistusers.go
│   │   │   └── alloydbwaitforoperation
│   │   │       ├── alloydbwaitforoperation_test.go
│   │   │       └── alloydbwaitforoperation.go
│   │   ├── alloydbainl
│   │   │   ├── alloydbainl_test.go
│   │   │   └── alloydbainl.go
│   │   ├── bigquery
│   │   │   ├── bigqueryanalyzecontribution
│   │   │   │   ├── bigqueryanalyzecontribution_test.go
│   │   │   │   └── bigqueryanalyzecontribution.go
│   │   │   ├── bigquerycommon
│   │   │   │   ├── table_name_parser_test.go
│   │   │   │   ├── table_name_parser.go
│   │   │   │   └── util.go
│   │   │   ├── bigqueryconversationalanalytics
│   │   │   │   ├── bigqueryconversationalanalytics_test.go
│   │   │   │   └── bigqueryconversationalanalytics.go
│   │   │   ├── bigqueryexecutesql
│   │   │   │   ├── bigqueryexecutesql_test.go
│   │   │   │   └── bigqueryexecutesql.go
│   │   │   ├── bigqueryforecast
│   │   │   │   ├── bigqueryforecast_test.go
│   │   │   │   └── bigqueryforecast.go
│   │   │   ├── bigquerygetdatasetinfo
│   │   │   │   ├── bigquerygetdatasetinfo_test.go
│   │   │   │   └── bigquerygetdatasetinfo.go
│   │   │   ├── bigquerygettableinfo
│   │   │   │   ├── bigquerygettableinfo_test.go
│   │   │   │   └── bigquerygettableinfo.go
│   │   │   ├── bigquerylistdatasetids
│   │   │   │   ├── bigquerylistdatasetids_test.go
│   │   │   │   └── bigquerylistdatasetids.go
│   │   │   ├── bigquerylisttableids
│   │   │   │   ├── bigquerylisttableids_test.go
│   │   │   │   └── bigquerylisttableids.go
│   │   │   ├── bigquerysearchcatalog
│   │   │   │   ├── bigquerysearchcatalog_test.go
│   │   │   │   └── bigquerysearchcatalog.go
│   │   │   └── bigquerysql
│   │   │       ├── bigquerysql_test.go
│   │   │       └── bigquerysql.go
│   │   ├── bigtable
│   │   │   ├── bigtable_test.go
│   │   │   └── bigtable.go
│   │   ├── cassandra
│   │   │   └── cassandracql
│   │   │       ├── cassandracql_test.go
│   │   │       └── cassandracql.go
│   │   ├── clickhouse
│   │   │   ├── clickhouseexecutesql
│   │   │   │   ├── clickhouseexecutesql_test.go
│   │   │   │   └── clickhouseexecutesql.go
│   │   │   ├── clickhouselistdatabases
│   │   │   │   ├── clickhouselistdatabases_test.go
│   │   │   │   └── clickhouselistdatabases.go
│   │   │   ├── clickhouselisttables
│   │   │   │   ├── clickhouselisttables_test.go
│   │   │   │   └── clickhouselisttables.go
│   │   │   └── clickhousesql
│   │   │       ├── clickhousesql_test.go
│   │   │       └── clickhousesql.go
│   │   ├── cloudmonitoring
│   │   │   ├── cloudmonitoring_test.go
│   │   │   └── cloudmonitoring.go
│   │   ├── cloudsql
│   │   │   ├── cloudsqlcreatedatabase
│   │   │   │   ├── cloudsqlcreatedatabase_test.go
│   │   │   │   └── cloudsqlcreatedatabase.go
│   │   │   ├── cloudsqlcreateusers
│   │   │   │   ├── cloudsqlcreateusers_test.go
│   │   │   │   └── cloudsqlcreateusers.go
│   │   │   ├── cloudsqlgetinstances
│   │   │   │   ├── cloudsqlgetinstances_test.go
│   │   │   │   └── cloudsqlgetinstances.go
│   │   │   ├── cloudsqllistdatabases
│   │   │   │   ├── cloudsqllistdatabases_test.go
│   │   │   │   └── cloudsqllistdatabases.go
│   │   │   ├── cloudsqllistinstances
│   │   │   │   ├── cloudsqllistinstances_test.go
│   │   │   │   └── cloudsqllistinstances.go
│   │   │   └── cloudsqlwaitforoperation
│   │   │       ├── cloudsqlwaitforoperation_test.go
│   │   │       └── cloudsqlwaitforoperation.go
│   │   ├── cloudsqlmssql
│   │   │   └── cloudsqlmssqlcreateinstance
│   │   │       ├── cloudsqlmssqlcreateinstance_test.go
│   │   │       └── cloudsqlmssqlcreateinstance.go
│   │   ├── cloudsqlmysql
│   │   │   └── cloudsqlmysqlcreateinstance
│   │   │       ├── cloudsqlmysqlcreateinstance_test.go
│   │   │       └── cloudsqlmysqlcreateinstance.go
│   │   ├── cloudsqlpg
│   │   │   └── cloudsqlpgcreateinstances
│   │   │       ├── cloudsqlpgcreateinstances_test.go
│   │   │       └── cloudsqlpgcreateinstances.go
│   │   ├── common_test.go
│   │   ├── common.go
│   │   ├── couchbase
│   │   │   ├── couchbase_test.go
│   │   │   └── couchbase.go
│   │   ├── dataform
│   │   │   └── dataformcompilelocal
│   │   │       ├── dataformcompilelocal_test.go
│   │   │       └── dataformcompilelocal.go
│   │   ├── dataplex
│   │   │   ├── dataplexlookupentry
│   │   │   │   ├── dataplexlookupentry_test.go
│   │   │   │   └── dataplexlookupentry.go
│   │   │   ├── dataplexsearchaspecttypes
│   │   │   │   ├── dataplexsearchaspecttypes_test.go
│   │   │   │   └── dataplexsearchaspecttypes.go
│   │   │   └── dataplexsearchentries
│   │   │       ├── dataplexsearchentries_test.go
│   │   │       └── dataplexsearchentries.go
│   │   ├── dgraph
│   │   │   ├── dgraph_test.go
│   │   │   └── dgraph.go
│   │   ├── firebird
│   │   │   ├── firebirdexecutesql
│   │   │   │   ├── firebirdexecutesql_test.go
│   │   │   │   └── firebirdexecutesql.go
│   │   │   └── firebirdsql
│   │   │       ├── firebirdsql_test.go
│   │   │       └── firebirdsql.go
│   │   ├── firestore
│   │   │   ├── firestoreadddocuments
│   │   │   │   ├── firestoreadddocuments_test.go
│   │   │   │   └── firestoreadddocuments.go
│   │   │   ├── firestoredeletedocuments
│   │   │   │   ├── firestoredeletedocuments_test.go
│   │   │   │   └── firestoredeletedocuments.go
│   │   │   ├── firestoregetdocuments
│   │   │   │   ├── firestoregetdocuments_test.go
│   │   │   │   └── firestoregetdocuments.go
│   │   │   ├── firestoregetrules
│   │   │   │   ├── firestoregetrules_test.go
│   │   │   │   └── firestoregetrules.go
│   │   │   ├── firestorelistcollections
│   │   │   │   ├── firestorelistcollections_test.go
│   │   │   │   └── firestorelistcollections.go
│   │   │   ├── firestorequery
│   │   │   │   ├── firestorequery_test.go
│   │   │   │   └── firestorequery.go
│   │   │   ├── firestorequerycollection
│   │   │   │   ├── firestorequerycollection_test.go
│   │   │   │   └── firestorequerycollection.go
│   │   │   ├── firestoreupdatedocument
│   │   │   │   ├── firestoreupdatedocument_test.go
│   │   │   │   └── firestoreupdatedocument.go
│   │   │   ├── firestorevalidaterules
│   │   │   │   ├── firestorevalidaterules_test.go
│   │   │   │   └── firestorevalidaterules.go
│   │   │   └── util
│   │   │       ├── converter_test.go
│   │   │       ├── converter.go
│   │   │       ├── validator_test.go
│   │   │       └── validator.go
│   │   ├── http
│   │   │   ├── http_test.go
│   │   │   └── http.go
│   │   ├── http_method.go
│   │   ├── looker
│   │   │   ├── lookeradddashboardelement
│   │   │   │   ├── lookeradddashboardelement_test.go
│   │   │   │   └── lookeradddashboardelement.go
│   │   │   ├── lookercommon
│   │   │   │   ├── lookercommon_test.go
│   │   │   │   └── lookercommon.go
│   │   │   ├── lookerconversationalanalytics
│   │   │   │   ├── lookerconversationalanalytics_test.go
│   │   │   │   └── lookerconversationalanalytics.go
│   │   │   ├── lookergetdashboards
│   │   │   │   ├── lookergetdashboards_test.go
│   │   │   │   └── lookergetdashboards.go
│   │   │   ├── lookergetdimensions
│   │   │   │   ├── lookergetdimensions_test.go
│   │   │   │   └── lookergetdimensions.go
│   │   │   ├── lookergetexplores
│   │   │   │   ├── lookergetexplores_test.go
│   │   │   │   └── lookergetexplores.go
│   │   │   ├── lookergetfilters
│   │   │   │   ├── lookergetfilters_test.go
│   │   │   │   └── lookergetfilters.go
│   │   │   ├── lookergetlooks
│   │   │   │   ├── lookergetlooks_test.go
│   │   │   │   └── lookergetlooks.go
│   │   │   ├── lookergetmeasures
│   │   │   │   ├── lookergetmeasures_test.go
│   │   │   │   └── lookergetmeasures.go
│   │   │   ├── lookergetmodels
│   │   │   │   ├── lookergetmodels_test.go
│   │   │   │   └── lookergetmodels.go
│   │   │   ├── lookergetparameters
│   │   │   │   ├── lookergetparameters_test.go
│   │   │   │   └── lookergetparameters.go
│   │   │   ├── lookerhealthanalyze
│   │   │   │   ├── lookerhealthanalyze_test.go
│   │   │   │   └── lookerhealthanalyze.go
│   │   │   ├── lookerhealthpulse
│   │   │   │   ├── lookerhealthpulse_test.go
│   │   │   │   └── lookerhealthpulse.go
│   │   │   ├── lookerhealthvacuum
│   │   │   │   ├── lookerhealthvacuum_test.go
│   │   │   │   └── lookerhealthvacuum.go
│   │   │   ├── lookermakedashboard
│   │   │   │   ├── lookermakedashboard_test.go
│   │   │   │   └── lookermakedashboard.go
│   │   │   ├── lookermakelook
│   │   │   │   ├── lookermakelook_test.go
│   │   │   │   └── lookermakelook.go
│   │   │   ├── lookerquery
│   │   │   │   ├── lookerquery_test.go
│   │   │   │   └── lookerquery.go
│   │   │   ├── lookerquerysql
│   │   │   │   ├── lookerquerysql_test.go
│   │   │   │   └── lookerquerysql.go
│   │   │   ├── lookerqueryurl
│   │   │   │   ├── lookerqueryurl_test.go
│   │   │   │   └── lookerqueryurl.go
│   │   │   └── lookerrunlook
│   │   │       ├── lookerrunlook_test.go
│   │   │       └── lookerrunlook.go
│   │   ├── mongodb
│   │   │   ├── mongodbaggregate
│   │   │   │   ├── mongodbaggregate_test.go
│   │   │   │   └── mongodbaggregate.go
│   │   │   ├── mongodbdeletemany
│   │   │   │   ├── mongodbdeletemany_test.go
│   │   │   │   └── mongodbdeletemany.go
│   │   │   ├── mongodbdeleteone
│   │   │   │   ├── mongodbdeleteone_test.go
│   │   │   │   └── mongodbdeleteone.go
│   │   │   ├── mongodbfind
│   │   │   │   ├── mongodbfind_test.go
│   │   │   │   └── mongodbfind.go
│   │   │   ├── mongodbfindone
│   │   │   │   ├── mongodbfindone_test.go
│   │   │   │   └── mongodbfindone.go
│   │   │   ├── mongodbinsertmany
│   │   │   │   ├── mongodbinsertmany_test.go
│   │   │   │   └── mongodbinsertmany.go
│   │   │   ├── mongodbinsertone
│   │   │   │   ├── mongodbinsertone_test.go
│   │   │   │   └── mongodbinsertone.go
│   │   │   ├── mongodbupdatemany
│   │   │   │   ├── mongodbupdatemany_test.go
│   │   │   │   └── mongodbupdatemany.go
│   │   │   └── mongodbupdateone
│   │   │       ├── mongodbupdateone_test.go
│   │   │       └── mongodbupdateone.go
│   │   ├── mssql
│   │   │   ├── mssqlexecutesql
│   │   │   │   ├── mssqlexecutesql_test.go
│   │   │   │   └── mssqlexecutesql.go
│   │   │   ├── mssqllisttables
│   │   │   │   ├── mssqllisttables_test.go
│   │   │   │   └── mssqllisttables.go
│   │   │   └── mssqlsql
│   │   │       ├── mssqlsql_test.go
│   │   │       └── mssqlsql.go
│   │   ├── mysql
│   │   │   ├── mysqlcommon
│   │   │   │   └── mysqlcommon.go
│   │   │   ├── mysqlexecutesql
│   │   │   │   ├── mysqlexecutesql_test.go
│   │   │   │   └── mysqlexecutesql.go
│   │   │   ├── mysqllistactivequeries
│   │   │   │   ├── mysqllistactivequeries_test.go
│   │   │   │   └── mysqllistactivequeries.go
│   │   │   ├── mysqllisttablefragmentation
│   │   │   │   ├── mysqllisttablefragmentation_test.go
│   │   │   │   └── mysqllisttablefragmentation.go
│   │   │   ├── mysqllisttables
│   │   │   │   ├── mysqllisttables_test.go
│   │   │   │   └── mysqllisttables.go
│   │   │   ├── mysqllisttablesmissinguniqueindexes
│   │   │   │   ├── mysqllisttablesmissinguniqueindexes_test.go
│   │   │   │   └── mysqllisttablesmissinguniqueindexes.go
│   │   │   └── mysqlsql
│   │   │       ├── mysqlsql_test.go
│   │   │       └── mysqlsql.go
│   │   ├── neo4j
│   │   │   ├── neo4jcypher
│   │   │   │   ├── neo4jcypher_test.go
│   │   │   │   └── neo4jcypher.go
│   │   │   ├── neo4jexecutecypher
│   │   │   │   ├── classifier
│   │   │   │   │   ├── classifier_test.go
│   │   │   │   │   └── classifier.go
│   │   │   │   ├── neo4jexecutecypher_test.go
│   │   │   │   └── neo4jexecutecypher.go
│   │   │   └── neo4jschema
│   │   │       ├── cache
│   │   │       │   ├── cache_test.go
│   │   │       │   └── cache.go
│   │   │       ├── helpers
│   │   │       │   ├── helpers_test.go
│   │   │       │   └── helpers.go
│   │   │       ├── neo4jschema_test.go
│   │   │       ├── neo4jschema.go
│   │   │       └── types
│   │   │           └── types.go
│   │   ├── oceanbase
│   │   │   ├── oceanbaseexecutesql
│   │   │   │   ├── oceanbaseexecutesql_test.go
│   │   │   │   └── oceanbaseexecutesql.go
│   │   │   └── oceanbasesql
│   │   │       ├── oceanbasesql_test.go
│   │   │       └── oceanbasesql.go
│   │   ├── oracle
│   │   │   ├── oracleexecutesql
│   │   │   │   └── oracleexecutesql.go
│   │   │   └── oraclesql
│   │   │       └── oraclesql.go
│   │   ├── parameters_test.go
│   │   ├── parameters.go
│   │   ├── postgres
│   │   │   ├── postgresexecutesql
│   │   │   │   ├── postgresexecutesql_test.go
│   │   │   │   └── postgresexecutesql.go
│   │   │   ├── postgreslistactivequeries
│   │   │   │   ├── postgreslistactivequeries_test.go
│   │   │   │   └── postgreslistactivequeries.go
│   │   │   ├── postgreslistavailableextensions
│   │   │   │   ├── postgreslistavailableextensions_test.go
│   │   │   │   └── postgreslistavailableextensions.go
│   │   │   ├── postgreslistinstalledextensions
│   │   │   │   ├── postgreslistinstalledextensions_test.go
│   │   │   │   └── postgreslistinstalledextensions.go
│   │   │   ├── postgreslisttables
│   │   │   │   ├── postgreslisttables_test.go
│   │   │   │   └── postgreslisttables.go
│   │   │   └── postgressql
│   │   │       ├── postgressql_test.go
│   │   │       └── postgressql.go
│   │   ├── redis
│   │   │   ├── redis_test.go
│   │   │   └── redis.go
│   │   ├── spanner
│   │   │   ├── spannerexecutesql
│   │   │   │   ├── spannerexecutesql_test.go
│   │   │   │   └── spannerexecutesql.go
│   │   │   ├── spannerlisttables
│   │   │   │   ├── spannerlisttables_test.go
│   │   │   │   └── spannerlisttables.go
│   │   │   └── spannersql
│   │   │       ├── spanner_test.go
│   │   │       └── spannersql.go
│   │   ├── sqlite
│   │   │   ├── sqliteexecutesql
│   │   │   │   ├── sqliteexecutesql_test.go
│   │   │   │   └── sqliteexecutesql.go
│   │   │   └── sqlitesql
│   │   │       ├── sqlitesql_test.go
│   │   │       └── sqlitesql.go
│   │   ├── tidb
│   │   │   ├── tidbexecutesql
│   │   │   │   ├── tidbexecutesql_test.go
│   │   │   │   └── tidbexecutesql.go
│   │   │   └── tidbsql
│   │   │       ├── tidbsql_test.go
│   │   │       └── tidbsql.go
│   │   ├── tools_test.go
│   │   ├── tools.go
│   │   ├── toolsets.go
│   │   ├── trino
│   │   │   ├── trinoexecutesql
│   │   │   │   ├── trinoexecutesql_test.go
│   │   │   │   └── trinoexecutesql.go
│   │   │   └── trinosql
│   │   │       ├── trinosql_test.go
│   │   │       └── trinosql.go
│   │   ├── utility
│   │   │   └── wait
│   │   │       ├── wait_test.go
│   │   │       └── wait.go
│   │   ├── valkey
│   │   │   ├── valkey_test.go
│   │   │   └── valkey.go
│   │   └── yugabytedbsql
│   │       ├── yugabytedbsql_test.go
│   │       └── yugabytedbsql.go
│   └── util
│       └── util.go
├── LICENSE
├── logo.png
├── main.go
├── MCP-TOOLBOX-EXTENSION.md
├── README.md
└── tests
    ├── alloydb
    │   ├── alloydb_integration_test.go
    │   └── alloydb_wait_for_operation_test.go
    ├── alloydbainl
    │   └── alloydb_ai_nl_integration_test.go
    ├── alloydbpg
    │   └── alloydb_pg_integration_test.go
    ├── auth.go
    ├── bigquery
    │   └── bigquery_integration_test.go
    ├── bigtable
    │   └── bigtable_integration_test.go
    ├── cassandra
    │   └── cassandra_integration_test.go
    ├── clickhouse
    │   └── clickhouse_integration_test.go
    ├── cloudmonitoring
    │   └── cloud_monitoring_integration_test.go
    ├── cloudsql
    │   ├── cloud_sql_create_database_test.go
    │   ├── cloud_sql_create_users_test.go
    │   ├── cloud_sql_get_instances_test.go
    │   ├── cloud_sql_list_databases_test.go
    │   ├── cloudsql_list_instances_test.go
    │   └── cloudsql_wait_for_operation_test.go
    ├── cloudsqlmssql
    │   ├── cloud_sql_mssql_create_instance_integration_test.go
    │   └── cloud_sql_mssql_integration_test.go
    ├── cloudsqlmysql
    │   ├── cloud_sql_mysql_create_instance_integration_test.go
    │   └── cloud_sql_mysql_integration_test.go
    ├── cloudsqlpg
    │   ├── cloud_sql_pg_create_instances_test.go
    │   └── cloud_sql_pg_integration_test.go
    ├── common.go
    ├── couchbase
    │   └── couchbase_integration_test.go
    ├── dataform
    │   └── dataform_integration_test.go
    ├── dataplex
    │   └── dataplex_integration_test.go
    ├── dgraph
    │   └── dgraph_integration_test.go
    ├── firebird
    │   └── firebird_integration_test.go
    ├── firestore
    │   └── firestore_integration_test.go
    ├── http
    │   └── http_integration_test.go
    ├── looker
    │   └── looker_integration_test.go
    ├── mongodb
    │   └── mongodb_integration_test.go
    ├── mssql
    │   └── mssql_integration_test.go
    ├── mysql
    │   └── mysql_integration_test.go
    ├── neo4j
    │   └── neo4j_integration_test.go
    ├── oceanbase
    │   └── oceanbase_integration_test.go
    ├── option.go
    ├── oracle
    │   └── oracle_integration_test.go
    ├── postgres
    │   └── postgres_integration_test.go
    ├── redis
    │   └── redis_test.go
    ├── server.go
    ├── source.go
    ├── spanner
    │   └── spanner_integration_test.go
    ├── sqlite
    │   └── sqlite_integration_test.go
    ├── tidb
    │   └── tidb_integration_test.go
    ├── tool.go
    ├── trino
    │   └── trino_integration_test.go
    ├── utility
    │   └── wait_integration_test.go
    ├── valkey
    │   └── valkey_test.go
    └── yugabytedb
        └── yugabytedb_integration_test.go
```

# Files

--------------------------------------------------------------------------------
/docs/en/resources/tools/alloydb/alloydb-wait-for-operation.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: alloydb-wait-for-operation
 3 | type: docs
 4 | weight: 10
 5 | description: "Wait for a long-running AlloyDB operation to complete.\n"
 6 | ---
 7 | 
 8 | The `alloydb-wait-for-operation` tool is a utility tool that waits for a
 9 | long-running AlloyDB operation to complete. It does this by polling the AlloyDB
10 | Admin API operation status endpoint until the operation is finished, using
11 | exponential backoff. It is compatible with
12 | [alloydb-admin](../../sources/alloydb-admin.md) source.
13 | 
14 | | Parameter   | Type   | Description                                          | Required |
15 | | :---------- | :----- | :--------------------------------------------------- | :------- |
16 | | `project`   | string | The GCP project ID.                                  | Yes      |
17 | | `location`  | string | The location of the operation (e.g., 'us-central1'). | Yes      |
18 | | `operation` | string | The ID of the operation to wait for.                 | Yes      |
19 | 
20 | {{< notice info >}}
21 | This tool is intended for developer assistant workflows with human-in-the-loop
22 | and shouldn't be used for production agents.
23 | {{< /notice >}}
24 | 
25 | ## Example
26 | 
27 | ```yaml
28 | tools:
29 |   wait_for_operation:
30 |     kind: alloydb-wait-for-operation
31 |     source: my-alloydb-admin-source
32 |     description: "This will poll on operations API until the operation is done. For checking operation status we need projectId, locationID and operationId. Once instance is created give follow up steps on how to use the variables to bring data plane MCP server up in local and remote setup."
33 |     delay: 1s
34 |     maxDelay: 4m
35 |     multiplier: 2
36 |     maxRetries: 10
37 | ```
38 | 
39 | ## Reference
40 | 
41 | | **field**   | **type** | **required** | **description**                                                                                                  |
42 | | ----------- | :------: | :----------: | ---------------------------------------------------------------------------------------------------------------- |
43 | | kind        |  string  |     true     | Must be "alloydb-wait-for-operation".                                                                            |
44 | | source      |  string  |     true     | The name of a `alloydb-admin` source to use for authentication.                                                  |
45 | | description |  string  |     false    | A description of the tool.                                                                                       |
46 | | delay       | duration |     false    | The initial delay between polling requests (e.g., `3s`). Defaults to 3 seconds.                                  |
47 | | maxDelay    | duration |     false    | The maximum delay between polling requests (e.g., `4m`). Defaults to 4 minutes.                                  |
48 | | multiplier  |   float  |     false    | The multiplier for the polling delay. The delay is multiplied by this value after each request. Defaults to 2.0. |
49 | | maxRetries  |    int   |     false    | The maximum number of polling attempts before giving up. Defaults to 10.                                         |
50 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/bigquery/bigquery-search-catalog.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "bigquery-search-catalog"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   A "bigquery-search-catalog" tool allows to search for entries based on the provided query.
 7 | ---
 8 | 
 9 | ## About
10 | 
11 | A `bigquery-search-catalog` tool returns all entries in Dataplex Catalog (e.g.
12 | tables, views, models) with system=bigquery that matches given user query.
13 | It's compatible with the following sources:
14 | 
15 | - [bigquery](../../sources/bigquery.md)
16 | 
17 | `bigquery-search-catalog` takes a required `query` parameter based on which
18 | entries are filtered and returned to the user. It also optionally accepts
19 | following parameters:
20 | 
21 | - `datasetIds` - The IDs of the bigquery dataset.
22 | - `projectIds` - The IDs of the bigquery project.
23 | - `types` - The type of the data. Accepted values are: CONNECTION, POLICY,
24 |   DATASET, MODEL, ROUTINE, TABLE, VIEW.
25 | - `pageSize` - Number of results in the search page. Defaults to `5`.
26 | 
27 | ## Requirements
28 | 
29 | ### IAM Permissions
30 | 
31 | Bigquery uses [Identity and Access Management (IAM)][iam-overview] to control
32 | user and group access to Dataplex resources. Toolbox will use your
33 | [Application Default Credentials (ADC)][adc] to authorize and authenticate when
34 | interacting with [Dataplex][dataplex-docs].
35 | 
36 | In addition to [setting the ADC for your server][set-adc], you need to ensure
37 | the IAM identity has been given the correct IAM permissions for the tasks you
38 | intend to perform. See [Dataplex Universal Catalog IAM permissions][iam-permissions]
39 | and [Dataplex Universal Catalog IAM roles][iam-roles] for more information on
40 | applying IAM permissions and roles to an identity.
41 | 
42 | [iam-overview]: https://cloud.google.com/dataplex/docs/iam-and-access-control
43 | [adc]: https://cloud.google.com/docs/authentication#adc
44 | [set-adc]: https://cloud.google.com/docs/authentication/provide-credentials-adc
45 | [iam-permissions]: https://cloud.google.com/dataplex/docs/iam-permissions
46 | [iam-roles]: https://cloud.google.com/dataplex/docs/iam-roles
47 | 
48 | ## Example
49 | 
50 | ```yaml
51 | tools:
52 |   search_catalog:
53 |     kind: bigquery-search-catalog
54 |     source: bigquery-source
55 |     description: Use this tool to find tables, views, models, routines or connections.
56 | ```
57 | 
58 | ## Reference
59 | 
60 | | **field**   |                  **type**                  | **required** | **description**                                                                                  |
61 | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------|
62 | | kind        |                   string                   |     true     | Must be "bigquery-search-catalog".                                                               |
63 | | source      |                   string                   |     true     | Name of the source the tool should execute on.                                                   |
64 | | description |                   string                   |     true     | Description of the tool that is passed to the LLM.                                               |
65 | 
```

--------------------------------------------------------------------------------
/.ci/quickstart_test/run_go_tests.sh:
--------------------------------------------------------------------------------

```bash
  1 | # Copyright 2025 Google LLC
  2 | # 
  3 | # Licensed under the Apache License, Version 2.0 (the "License");
  4 | # you may not use this file except in compliance with the License.
  5 | # You may obtain a copy of the License at
  6 | # 
  7 | #      http://www.apache.org/licenses/LICENSE-2.0
  8 | # 
  9 | # Unless required by applicable law or agreed to in writing, software
 10 | # distributed under the License is distributed on an "AS IS" BASIS,
 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | # See the License for the specific language governing permissions and
 13 | # limitations under the License.
 14 | 
 15 | #!/bin/bash
 16 | 
 17 | set -e
 18 | 
 19 | TABLE_NAME="hotels_go"
 20 | QUICKSTART_GO_DIR="docs/en/getting-started/quickstart/go"
 21 | SQL_FILE=".ci/quickstart_test/setup_hotels_sample.sql"
 22 | 
 23 | PROXY_PID=""
 24 | TOOLBOX_PID=""
 25 | 
 26 | install_system_packages() {
 27 |   apt-get update && apt-get install -y \
 28 |     postgresql-client \
 29 |     wget \
 30 |     gettext-base  \
 31 |     netcat-openbsd
 32 | }
 33 | 
 34 | start_cloud_sql_proxy() {
 35 |   wget "https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.10.0/cloud-sql-proxy.linux.amd64" -O /usr/local/bin/cloud-sql-proxy
 36 |   chmod +x /usr/local/bin/cloud-sql-proxy
 37 |   cloud-sql-proxy "${CLOUD_SQL_INSTANCE}" &
 38 |   PROXY_PID=$!
 39 | 
 40 |   for i in {1..30}; do
 41 |     if nc -z 127.0.0.1 5432; then
 42 |       echo "Cloud SQL Proxy is up and running."
 43 |       return
 44 |     fi
 45 |     sleep 1
 46 |   done
 47 | 
 48 |   echo "Cloud SQL Proxy failed to start within the timeout period."
 49 |   exit 1
 50 | }
 51 | 
 52 | setup_toolbox() {
 53 |   TOOLBOX_YAML="/tools.yaml"
 54 |   echo "${TOOLS_YAML_CONTENT}" > "$TOOLBOX_YAML"
 55 |   if [ ! -f "$TOOLBOX_YAML" ]; then echo "Failed to create tools.yaml"; exit 1; fi
 56 |   wget "https://storage.googleapis.com/genai-toolbox/v${VERSION}/linux/amd64/toolbox" -O "/toolbox"
 57 |   chmod +x "/toolbox"
 58 |   /toolbox --tools-file "$TOOLBOX_YAML" &
 59 |   TOOLBOX_PID=$!
 60 |   sleep 2
 61 | }
 62 | 
 63 | setup_orch_table() {
 64 |   export TABLE_NAME
 65 |   envsubst < "$SQL_FILE" | psql -h "$PGHOST" -p "$PGPORT" -U "$DB_USER" -d "$DATABASE_NAME"
 66 | }
 67 | 
 68 | run_orch_test() {
 69 |   local orch_dir="$1"
 70 |   local orch_name
 71 |   orch_name=$(basename "$orch_dir")
 72 |   
 73 |   if [ "$orch_name" == "openAI" ]; then
 74 |       echo -e "\nSkipping framework '${orch_name}': Temporarily excluded."
 75 |       return
 76 |   fi
 77 |   
 78 |   (
 79 |     set -e
 80 |     setup_orch_table
 81 | 
 82 |     echo "--- Preparing module for $orch_name ---"
 83 |     cd "$orch_dir"
 84 | 
 85 |     if [ -f "go.mod" ]; then
 86 |       go mod tidy
 87 |     fi
 88 | 
 89 |     cd ..
 90 | 
 91 |     export ORCH_NAME="$orch_name"
 92 | 
 93 |     echo "--- Running tests for $orch_name ---"
 94 |     go test -v ./...
 95 |   )
 96 | }
 97 | 
 98 | cleanup_all() {
 99 |   echo "--- Final cleanup: Shutting down processes and dropping table ---"
100 |   if [ -n "$TOOLBOX_PID" ]; then
101 |     kill $TOOLBOX_PID || true
102 |   fi
103 |   if [ -n "$PROXY_PID" ]; then
104 |     kill $PROXY_PID || true
105 |   fi
106 | }
107 | trap cleanup_all EXIT
108 | 
109 | # Main script execution
110 | install_system_packages
111 | start_cloud_sql_proxy
112 | 
113 | export PGHOST=127.0.0.1
114 | export PGPORT=5432
115 | export PGPASSWORD="$DB_PASSWORD"
116 | export GOOGLE_API_KEY="$GOOGLE_API_KEY"
117 | 
118 | setup_toolbox
119 | 
120 | for ORCH_DIR in "$QUICKSTART_GO_DIR"/*/; do
121 |   if [ ! -d "$ORCH_DIR" ]; then
122 |     continue
123 |   fi
124 |   run_orch_test "$ORCH_DIR"
125 | done
126 | 
```

--------------------------------------------------------------------------------
/docs/en/how-to/export_telemetry.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | title: "Export Telemetry"
  3 | type: docs
  4 | weight: 5
  5 | description: >
  6 |   How to set up and configure Toolbox to use the Otel Collector.
  7 | ---
  8 | 
  9 | 
 10 | ## About
 11 | 
 12 | The [OpenTelemetry Collector][about-collector] offers a vendor-agnostic
 13 | implementation of how to receive, process and export telemetry data. It removes
 14 | the need to run, operate, and maintain multiple agents/collectors.
 15 | 
 16 | [about-collector]: https://opentelemetry.io/docs/collector/
 17 | 
 18 | ## Configure the Collector
 19 | 
 20 | To configure the collector, you will have to provide a configuration file. The
 21 | configuration file consists of four classes of pipeline component that access
 22 | telemetry data.
 23 | 
 24 | - `Receivers`
 25 | - `Processors`
 26 | - `Exporters`
 27 | - `Connectors`
 28 | 
 29 | Example of setting up the classes of pipeline components (in this example, we
 30 | don't use connectors):
 31 | 
 32 | ```yaml
 33 | receivers:
 34 |   otlp:
 35 |     protocols:
 36 |       http:
 37 |         endpoint: "127.0.0.1:4553"
 38 | 
 39 | exporters:
 40 |   googlecloud:
 41 |     project: <YOUR_GOOGLE_CLOUD_PROJECT>
 42 | 
 43 | processors:
 44 |   batch:
 45 |     send_batch_size: 200
 46 | ```
 47 | 
 48 | After each pipeline component is configured, you will enable it within the
 49 | `service` section of the configuration file.
 50 | 
 51 | ```yaml
 52 | service:
 53 |   pipelines:
 54 |     traces:
 55 |       receivers: ["otlp"]
 56 |       processors: ["batch"]
 57 |       exporters: ["googlecloud"]
 58 | ```
 59 | 
 60 | ## Running the Collector
 61 | 
 62 | There are a couple of steps to run and use a Collector.
 63 | 
 64 | 1. [Install the
 65 |    Collector](https://opentelemetry.io/docs/collector/installation/) binary.
 66 |    Pull a binary or Docker image for the OpenTelemetry contrib collector.
 67 | 
 68 | 1. Set up credentials for telemetry backend.
 69 | 
 70 | 1. Set up the Collector config. Below are some examples for setting up the
 71 |    Collector config:
 72 |     - [Google Cloud Exporter][google-cloud-exporter]
 73 |     - [Google Managed Service for Prometheus Exporter][google-prometheus-exporter]
 74 | 
 75 | 1. Run the Collector with the configuration file.
 76 | 
 77 |     ```bash
 78 |     ./otelcol-contrib --config=collector-config.yaml
 79 |     ```
 80 | 
 81 | 1. Run toolbox with the `--telemetry-otlp` flag. Configure it to send them to
 82 |    `http://127.0.0.1:4553` (for HTTP) or the Collector's URL.
 83 | 
 84 |     ```bash
 85 |     ./toolbox --telemetry-otlp=http://127.0.0.1:4553
 86 |     ```
 87 | 
 88 | 1. Once telemetry datas are collected, you can view them in your telemetry
 89 |    backend. If you are using GCP exporters, telemetry will be visible in GCP
 90 |    dashboard at [Metrics Explorer][metrics-explorer] and [Trace
 91 |    Explorer][trace-explorer].
 92 | 
 93 |   {{< notice note >}}
 94 |   If you are exporting to Google Cloud monitoring, we recommend that you use
 95 |   the Google Cloud Exporter for traces and the Google Managed Service for
 96 |   Prometheus Exporter for metrics.
 97 |   {{< /notice >}}
 98 | 
 99 | [google-cloud-exporter]:
100 |     https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/googlecloudexporter
101 | [google-prometheus-exporter]:
102 |     https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/googlemanagedprometheusexporter#example-configuration
103 | [metrics-explorer]: https://console.cloud.google.com/monitoring/metrics-explorer
104 | [trace-explorer]: https://console.cloud.google.com/traces
105 | 
```

--------------------------------------------------------------------------------
/docs/en/getting-started/quickstart/js/genkit/quickstart.js:
--------------------------------------------------------------------------------

```javascript
 1 | import { ToolboxClient } from "@toolbox-sdk/core";
 2 | import { genkit } from "genkit";
 3 | import { googleAI } from '@genkit-ai/googleai';
 4 | 
 5 | const GOOGLE_API_KEY = process.env.GOOGLE_API_KEY || 'your-api-key'; // Replace it with your API key
 6 | 
 7 | const systemPrompt = `
 8 | You're a helpful hotel assistant. You handle hotel searching, booking, and
 9 | cancellations. When the user searches for a hotel, mention its name, id,
10 | location and price tier. Always mention hotel ids while performing any
11 | searches. This is very important for any operations. For any bookings or
12 | cancellations, please provide the appropriate confirmation. Be sure to
13 | update checkin or checkout dates if mentioned by the user.
14 | Don't ask for confirmations from the user.
15 | `;
16 | 
17 | const queries = [
18 |   "Find hotels in Basel with Basel in its name.",
19 |   "Can you book the Hilton Basel for me?",
20 |   "Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
21 |   "My check in dates would be from April 10, 2024 to April 19, 2024.",
22 | ];
23 | 
24 | export async function main() {
25 |   const toolboxClient = new ToolboxClient("http://127.0.0.1:5000");
26 | 
27 |   const ai = genkit({
28 |     plugins: [
29 |       googleAI({
30 |         apiKey: process.env.GEMINI_API_KEY || GOOGLE_API_KEY
31 |       })
32 |     ],
33 |     model: googleAI.model('gemini-2.0-flash'),
34 |   });
35 | 
36 |   const toolboxTools = await toolboxClient.loadToolset("my-toolset");
37 |   const toolMap = Object.fromEntries(
38 |     toolboxTools.map((tool) => {
39 |       const definedTool = ai.defineTool(
40 |         {
41 |           name: tool.getName(),
42 |           description: tool.getDescription(),
43 |           inputSchema: tool.getParamSchema(),
44 |         },
45 |         tool
46 |       );
47 |       return [tool.getName(), definedTool];
48 |     })
49 |   );
50 |   const tools = Object.values(toolMap);
51 | 
52 |   let conversationHistory = [{ role: "system", content: [{ text: systemPrompt }] }];
53 | 
54 |   for (const query of queries) {
55 |     conversationHistory.push({ role: "user", content: [{ text: query }] });
56 |     const response = await ai.generate({
57 |       messages: conversationHistory,
58 |       tools: tools,
59 |     });
60 |     conversationHistory.push(response.message);
61 | 
62 |     const toolRequests = response.toolRequests;
63 |     if (toolRequests?.length > 0) {
64 |       // Execute tools concurrently and collect their responses.
65 |       const toolResponses = await Promise.all(
66 |         toolRequests.map(async (call) => {
67 |           try {
68 |             const toolOutput = await toolMap[call.name].invoke(call.input);
69 |             return { role: "tool", content: [{ toolResponse: { name: call.name, output: toolOutput } }] };
70 |           } catch (e) {
71 |             console.error(`Error executing tool ${call.name}:`, e);
72 |             return { role: "tool", content: [{ toolResponse: { name: call.name, output: { error: e.message } } }] };
73 |           }
74 |         })
75 |       );
76 | 
77 |       conversationHistory.push(...toolResponses);
78 | 
79 |       // Call the AI again with the tool results.
80 |       response = await ai.generate({ messages: conversationHistory, tools });
81 |       conversationHistory.push(response.message);
82 |     }
83 | 
84 |     console.log(response.text);
85 |   }
86 | }
87 | 
88 | main();
89 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/alloydb/alloydb-create-cluster.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: alloydb-create-cluster
 3 | type: docs
 4 | weight: 1
 5 | description: "The \"alloydb-create-cluster\" tool creates a new AlloyDB for PostgreSQL cluster in a specified project and location.\n"
 6 | aliases: [/resources/tools/alloydb-create-cluster]
 7 | ---
 8 | 
 9 | ## About
10 | 
11 | The `alloydb-create-cluster` tool creates a new AlloyDB for PostgreSQL cluster in a specified project and location. It is compatible with [alloydb-admin](../../sources/alloydb-admin.md) source.
12 | This tool provisions a cluster with a **private IP address** within the specified VPC network.
13 | 
14 |   **Permissions & APIs Required:**
15 |   Before using, ensure the following on your GCP project:
16 | 
17 | 1. The [AlloyDB API](https://console.cloud.google.com/apis/library/alloydb.googleapis.com) is enabled.
18 | 2. The user or service account executing the tool has one of the following IAM roles:
19 | 
20 |     - `roles/alloydb.admin` (the AlloyDB Admin predefined IAM role)
21 |     - `roles/owner` (the Owner basic IAM role)
22 |     - `roles/editor` (the Editor basic IAM role)
23 | 
24 | The tool takes the following input parameters:
25 | 
26 | | Parameter  | Type   | Description                                                                                                               | Required |
27 | | :--------- | :----- | :------------------------------------------------------------------------------------------------------------------------ | :------- |
28 | | `project`  | string | The GCP project ID where the cluster will be created.                                                                     | Yes      |
29 | | `cluster`  | string | A unique identifier for the new AlloyDB cluster.                                                                          | Yes      |
30 | | `password` | string | A secure password for the initial user.                                                                                   | Yes      |
31 | | `location` | string | The GCP location where the cluster will be created. Default: `us-central1`. If quota is exhausted then use other regions. | No       |
32 | | `network`  | string | The name of the VPC network to connect the cluster to. Default: `default`.                                                | No       |
33 | | `user`     | string | The name for the initial superuser. Default: `postgres`.                                                                  | No       |
34 | 
35 | ## Example
36 | 
37 | ```yaml
38 | tools:
39 |   create_cluster:
40 |     kind: alloydb-create-cluster
41 |     source: alloydb-admin-source
42 |     description: Use this tool to create a new AlloyDB cluster in a given project and location.
43 | ```
44 | 
45 | ## Reference
46 | 
47 | | **field**   | **type** | **required** | **description**                                      |   |
48 | | ----------- | :------: | :----------: | ---------------------------------------------------- | - |
49 | | kind        |  string  |     true     | Must be alloydb-create-cluster.                      |   |
50 | | source      |  string  |     true     | The name of an `alloydb-admin` source.               |   |
51 | | description |  string  |     false    | Description of the tool that is passed to the agent. |   |
52 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/dataplex/dataplex-lookup-entry.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "dataplex-lookup-entry"
 3 | type: docs
 4 | weight: 1
 5 | description: > 
 6 |   A "dataplex-lookup-entry" tool returns details of a particular entry in Dataplex Catalog.
 7 | aliases:
 8 | - /resources/tools/dataplex-lookup-entry
 9 | ---
10 | 
11 | ## About
12 | 
13 | A `dataplex-lookup-entry` tool returns details of a particular entry in Dataplex
14 | Catalog. It's compatible with the following sources:
15 | 
16 | - [dataplex](../sources/dataplex.md)
17 | 
18 | `dataplex-lookup-entry` takes a required `name` parameter which contains the
19 | project and location to which the request should be attributed in the following
20 | form: projects/{project}/locations/{location} and also a required `entry`
21 | parameter which is the resource name of the entry in the following form:
22 | projects/{project}/locations/{location}/entryGroups/{entryGroup}/entries/{entry}.
23 | It also optionally accepts following parameters:
24 | 
25 | - `view` - View to control which parts of an entry the service should return.
26 |     It takes integer values from 1-4 corresponding to type of view - BASIC,
27 |     FULL, CUSTOM, ALL
28 | - `aspectTypes` - Limits the aspects returned to the provided aspect types in
29 |     the format
30 |     `projects/{project}/locations/{location}/aspectTypes/{aspectType}`. It only
31 |     works for CUSTOM view.
32 | - `paths` - Limits the aspects returned to those associated with the provided
33 |     paths within the Entry. It only works for CUSTOM view.
34 | 
35 | ## Requirements
36 | 
37 | ### IAM Permissions
38 | 
39 | Dataplex uses [Identity and Access Management (IAM)][iam-overview] to control
40 | user and group access to Dataplex resources. Toolbox will use your
41 | [Application Default Credentials (ADC)][adc] to authorize and authenticate when
42 | interacting with [Dataplex][dataplex-docs].
43 | 
44 | In addition to [setting the ADC for your server][set-adc], you need to ensure
45 | the IAM identity has been given the correct IAM permissions for the tasks you
46 | intend to perform. See [Dataplex Universal Catalog IAM permissions][iam-permissions]
47 | and [Dataplex Universal Catalog IAM roles][iam-roles] for more information on
48 | applying IAM permissions and roles to an identity.
49 | 
50 | [iam-overview]: https://cloud.google.com/dataplex/docs/iam-and-access-control
51 | [adc]: https://cloud.google.com/docs/authentication#adc
52 | [set-adc]: https://cloud.google.com/docs/authentication/provide-credentials-adc
53 | [iam-permissions]: https://cloud.google.com/dataplex/docs/iam-permissions
54 | [iam-roles]: https://cloud.google.com/dataplex/docs/iam-roles
55 | 
56 | ## Example
57 | 
58 | ```yaml
59 | tools:
60 |   lookup_entry:
61 |     kind: dataplex-lookup-entry
62 |     source: my-dataplex-source
63 |     description: Use this tool to retrieve a specific entry in Dataplex Catalog.
64 | ```
65 | 
66 | ## Reference
67 | 
68 | | **field**   | **type** | **required** | **description**                                    |
69 | |-------------|:--------:|:------------:|----------------------------------------------------|
70 | | kind        |  string  |     true     | Must be "dataplex-lookup-entry".                   |
71 | | source      |  string  |     true     | Name of the source the tool should execute on.     |
72 | | description |  string  |     true     | Description of the tool that is passed to the LLM. |
73 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/alloydb/alloydb-create-user.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: alloydb-create-user
 3 | type: docs
 4 | weight: 2
 5 | description: "The \"alloydb-create-user\" tool creates a new database user within a specified AlloyDB cluster.\n"
 6 | aliases: [/resources/tools/alloydb-create-user]
 7 | ---
 8 | 
 9 | ## About
10 | 
11 | The `alloydb-create-user` tool creates a new database user (`ALLOYDB_BUILT_IN`
12 | or `ALLOYDB_IAM_USER`) within a specified cluster. It is compatible with
13 | [alloydb-admin](../../sources/alloydb-admin.md) source.
14 | 
15 | **Permissions & APIs Required:**
16 | Before using, ensure the following on your GCP project:
17 | 
18 | 1. The [AlloyDB
19 |     API](https://console.cloud.google.com/apis/library/alloydb.googleapis.com)
20 |     is enabled.
21 | 2. The user or service account executing the tool has one of the following IAM
22 |     roles:
23 |     - `roles/alloydb.admin` (the AlloyDB Admin predefined IAM role)
24 |     - `roles/owner` (the Owner basic IAM role)
25 |     - `roles/editor` (the Editor basic IAM role)
26 | 
27 | The tool takes the following input parameters:
28 | 
29 | | Parameter       | Type          | Description                                                                                                   | Required |
30 | | :-------------- | :------------ | :------------------------------------------------------------------------------------------------------------ | :------- |
31 | | `project`       | string        | The GCP project ID where the cluster exists.                                                                  | Yes      |
32 | | `cluster`       | string        | The ID of the existing cluster where the user will be created.                                                | Yes      |
33 | | `location`      | string        | The GCP location where the cluster exists (e.g., `us-central1`).                                              | Yes      |
34 | | `user`          | string        | The name for the new user. Must be unique within the cluster.                                                 | Yes      |
35 | | `userType`      | string        | The type of user. Valid values: `ALLOYDB_BUILT_IN` and `ALLOYDB_IAM_USER`. `ALLOYDB_IAM_USER` is recommended. | Yes      |
36 | | `password`      | string        | A secure password for the user. Required only if `userType` is `ALLOYDB_BUILT_IN`.                            | No       |
37 | | `databaseRoles` | array(string) | Optional. A list of database roles to grant to the new user (e.g., `pg_read_all_data`).                       | No       |
38 | 
39 | ## Example
40 | 
41 | ```yaml
42 | tools:
43 |   create_user:
44 |     kind: alloydb-create-user
45 |     source: alloydb-admin-source
46 |     description: Use this tool to create a new database user for an AlloyDB cluster.
47 | ```
48 | 
49 | ## Reference
50 | 
51 | | **field**   | **type** | **required** | **description**                                      |
52 | | ----------- | :------: | :----------: | ---------------------------------------------------- |
53 | | kind        |  string  |     true     | Must be alloydb-create-user.                         |
54 | | source      |  string  |     true     | The name of an `alloydb-admin` source.               |
55 | | description |  string  |     false    | Description of the tool that is passed to the agent. |
56 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookerquery/lookerquery_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookerquery_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerquery"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerQuery(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-query
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-query",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerQuery(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-query
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-query\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-query\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookerrunlook/lookerrunlook_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookerrunlook_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerrunlook"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerRunLook(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-run-look
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-run-look",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerRunLook(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-run-look
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-run-look\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-run-look\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/.ci/quickstart_test/run_js_tests.sh:
--------------------------------------------------------------------------------

```bash
  1 | # Copyright 2025 Google LLC
  2 | # 
  3 | # Licensed under the Apache License, Version 2.0 (the "License");
  4 | # you may not use this file except in compliance with the License.
  5 | # You may obtain a copy of the License at
  6 | # 
  7 | #      http://www.apache.org/licenses/LICENSE-2.0
  8 | # 
  9 | # Unless required by applicable law or agreed to in writing, software
 10 | # distributed under the License is distributed on an "AS IS" BASIS,
 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | # See the License for the specific language governing permissions and
 13 | # limitations under the License.
 14 | 
 15 | #!/bin/bash
 16 | 
 17 | set -e
 18 | 
 19 | TABLE_NAME="hotels_js"
 20 | QUICKSTART_JS_DIR="docs/en/getting-started/quickstart/js"
 21 | SQL_FILE=".ci/quickstart_test/setup_hotels_sample.sql"
 22 | 
 23 | # Initialize process IDs to empty at the top of the script
 24 | PROXY_PID=""
 25 | TOOLBOX_PID=""
 26 | 
 27 | install_system_packages() {
 28 |   apt-get update && apt-get install -y \
 29 |     postgresql-client \
 30 |     wget \
 31 |     gettext-base  \
 32 |     netcat-openbsd
 33 | }
 34 | 
 35 | start_cloud_sql_proxy() {
 36 |   wget "https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.10.0/cloud-sql-proxy.linux.amd64" -O /usr/local/bin/cloud-sql-proxy
 37 |   chmod +x /usr/local/bin/cloud-sql-proxy
 38 |   cloud-sql-proxy "${CLOUD_SQL_INSTANCE}" &
 39 |   PROXY_PID=$!
 40 | 
 41 |   for i in {1..30}; do
 42 |     if nc -z 127.0.0.1 5432; then
 43 |       echo "Cloud SQL Proxy is up and running."
 44 |       return
 45 |     fi
 46 |     sleep 1
 47 |   done
 48 | 
 49 |   echo "Cloud SQL Proxy failed to start within the timeout period."
 50 |   exit 1
 51 | }
 52 | 
 53 | setup_toolbox() {
 54 |   TOOLBOX_YAML="/tools.yaml"
 55 |   echo "${TOOLS_YAML_CONTENT}" > "$TOOLBOX_YAML"
 56 |   if [ ! -f "$TOOLBOX_YAML" ]; then echo "Failed to create tools.yaml"; exit 1; fi
 57 |   wget "https://storage.googleapis.com/genai-toolbox/v${VERSION}/linux/amd64/toolbox" -O "/toolbox"
 58 |   chmod +x "/toolbox"
 59 |   /toolbox --tools-file "$TOOLBOX_YAML" &
 60 |   TOOLBOX_PID=$!
 61 |   sleep 2
 62 | }
 63 | 
 64 | setup_orch_table() {
 65 |   export TABLE_NAME
 66 |   envsubst < "$SQL_FILE" | psql -h "$PGHOST" -p "$PGPORT" -U "$DB_USER" -d "$DATABASE_NAME"
 67 | }
 68 | 
 69 | run_orch_test() {
 70 |   local orch_dir="$1"
 71 |   local orch_name
 72 |   orch_name=$(basename "$orch_dir")
 73 | 
 74 |   (
 75 |     set -e
 76 |     echo "--- Preparing environment for $orch_name ---"
 77 |     setup_orch_table
 78 | 
 79 |     cd "$orch_dir"
 80 |     if [ -f "package.json" ]; then
 81 |       echo "Installing dependencies for $orch_name..."
 82 |       npm install
 83 |     fi
 84 | 
 85 |     cd ..
 86 | 
 87 |     echo "--- Running tests for $orch_name ---"
 88 |     export ORCH_NAME="$orch_name"
 89 |     node --test quickstart.test.js
 90 | 
 91 |     echo "--- Cleaning environment for $orch_name ---"
 92 |     rm -rf "${orch_name}/node_modules"
 93 |   )
 94 | }
 95 | 
 96 | cleanup_all() {
 97 |   echo "--- Final cleanup: Shutting down processes and dropping table ---"
 98 |   if [ -n "$TOOLBOX_PID" ]; then
 99 |     kill $TOOLBOX_PID || true
100 |   fi
101 |   if [ -n "$PROXY_PID" ]; then
102 |     kill $PROXY_PID || true
103 |   fi
104 | }
105 | trap cleanup_all EXIT
106 | 
107 | # Main script execution
108 | install_system_packages
109 | start_cloud_sql_proxy
110 | 
111 | export PGHOST=127.0.0.1
112 | export PGPORT=5432
113 | export PGPASSWORD="$DB_PASSWORD"
114 | export GOOGLE_API_KEY="$GOOGLE_API_KEY"
115 | 
116 | setup_toolbox
117 | 
118 | for ORCH_DIR in "$QUICKSTART_JS_DIR"/*/; do
119 |   if [ ! -d "$ORCH_DIR" ]; then
120 |     continue
121 |   fi
122 |   run_orch_test "$ORCH_DIR"
123 | done
```

--------------------------------------------------------------------------------
/internal/sources/firebird/firebird.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package firebird
 16 | 
 17 | import (
 18 | 	"context"
 19 | 	"database/sql"
 20 | 	"fmt"
 21 | 	"time"
 22 | 
 23 | 	"github.com/goccy/go-yaml"
 24 | 	"github.com/googleapis/genai-toolbox/internal/sources"
 25 | 	"go.opentelemetry.io/otel/trace"
 26 | )
 27 | 
 28 | const SourceKind string = "firebird"
 29 | 
 30 | var _ sources.SourceConfig = Config{}
 31 | 
 32 | func init() {
 33 | 	if !sources.Register(SourceKind, newConfig) {
 34 | 		panic(fmt.Sprintf("source kind %q already registered", SourceKind))
 35 | 	}
 36 | }
 37 | 
 38 | func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources.SourceConfig, error) {
 39 | 	actual := Config{Name: name}
 40 | 	if err := decoder.DecodeContext(ctx, &actual); err != nil {
 41 | 		return nil, err
 42 | 	}
 43 | 	return actual, nil
 44 | }
 45 | 
 46 | type Config struct {
 47 | 	Name     string `yaml:"name" validate:"required"`
 48 | 	Kind     string `yaml:"kind" validate:"required"`
 49 | 	Host     string `yaml:"host" validate:"required"`
 50 | 	Port     string `yaml:"port" validate:"required"`
 51 | 	User     string `yaml:"user" validate:"required"`
 52 | 	Password string `yaml:"password" validate:"required"`
 53 | 	Database string `yaml:"database" validate:"required"`
 54 | }
 55 | 
 56 | func (r Config) SourceConfigKind() string {
 57 | 	return SourceKind
 58 | }
 59 | 
 60 | func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) {
 61 | 	pool, err := initFirebirdConnectionPool(ctx, tracer, r.Name, r.Host, r.Port, r.User, r.Password, r.Database)
 62 | 	if err != nil {
 63 | 		return nil, fmt.Errorf("unable to create pool: %w", err)
 64 | 	}
 65 | 
 66 | 	err = pool.PingContext(ctx)
 67 | 	if err != nil {
 68 | 		return nil, fmt.Errorf("unable to connect successfully: %w", err)
 69 | 	}
 70 | 
 71 | 	s := &Source{
 72 | 		Name: r.Name,
 73 | 		Kind: SourceKind,
 74 | 		Db:   pool,
 75 | 	}
 76 | 	return s, nil
 77 | }
 78 | 
 79 | var _ sources.Source = &Source{}
 80 | 
 81 | type Source struct {
 82 | 	Name string `yaml:"name"`
 83 | 	Kind string `yaml:"kind"`
 84 | 	Db   *sql.DB
 85 | }
 86 | 
 87 | func (s *Source) SourceKind() string {
 88 | 	return SourceKind
 89 | }
 90 | 
 91 | func (s *Source) FirebirdDB() *sql.DB {
 92 | 	return s.Db
 93 | }
 94 | 
 95 | func initFirebirdConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname string) (*sql.DB, error) {
 96 | 	_, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name)
 97 | 	defer span.End()
 98 | 
 99 | 	// urlExample := "user:password@host:port/path/to/database.fdb"
100 | 	dsn := fmt.Sprintf("%s:%s@%s:%s/%s", user, pass, host, port, dbname)
101 | 
102 | 	db, err := sql.Open("firebirdsql", dsn)
103 | 	if err != nil {
104 | 		return nil, fmt.Errorf("unable to create connection pool: %w", err)
105 | 	}
106 | 
107 | 	// Configure connection pool to prevent deadlocks
108 | 	db.SetMaxOpenConns(5)
109 | 	db.SetMaxIdleConns(2)
110 | 	db.SetConnMaxLifetime(5 * time.Minute)
111 | 	db.SetConnMaxIdleTime(1 * time.Minute)
112 | 
113 | 	return db, nil
114 | }
115 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/alloydb/alloydb-create-instance.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: alloydb-create-instance
 3 | type: docs
 4 | weight: 1
 5 | description: "The \"alloydb-create-instance\" tool creates a new AlloyDB instance within a specified cluster.\n"
 6 | aliases: [/resources/tools/alloydb-create-instance]
 7 | ---
 8 | 
 9 | ## About
10 | 
11 | The `alloydb-create-instance` tool creates a new AlloyDB instance (PRIMARY or
12 | READ_POOL) within a specified cluster. It is compatible with
13 | [alloydb-admin](../../sources/alloydb-admin.md) source.
14 | This tool provisions a new instance with a **public IP address**.
15 | 
16 |   **Permissions & APIs Required:**
17 |   Before using, ensure the following on your GCP project:
18 | 
19 | 1.  The [AlloyDB
20 |     API](https://console.cloud.google.com/apis/library/alloydb.googleapis.com)
21 |     is enabled.
22 | 2.  The user or service account executing the tool has one of the following IAM
23 |     roles:
24 | 
25 | 
26 |     - `roles/alloydb.admin` (the AlloyDB Admin predefined IAM role)
27 |     - `roles/owner` (the Owner basic IAM role)
28 |     - `roles/editor` (the Editor basic IAM role)
29 | 
30 | The tool takes the following input parameters:
31 | 
32 | | Parameter      | Type   | Description                                                                                       | Required |
33 | | :------------- | :----- | :------------------------------------------------------------------------------------------------ | :------- |
34 | | `project`      | string | The GCP project ID where the cluster exists.                                                      | Yes      |
35 | | `location`     | string | The GCP location where the cluster exists (e.g., `us-central1`).                                  | Yes      |
36 | | `cluster`      | string | The ID of the existing cluster to add this instance to.                                           | Yes      |
37 | | `instance`     | string | A unique identifier for the new AlloyDB instance.                                                 | Yes      |
38 | | `instanceType` | string | The type of instance. Valid values are: `PRIMARY` and `READ_POOL`. Default: `PRIMARY`             | No       |
39 | | `displayName`  | string | An optional, user-friendly name for the instance.                                                 | No       |
40 | | `nodeCount`    | int    | The number of nodes for a read pool. Required only if `instanceType` is `READ_POOL`. Default: `1` | No       |
41 | 
42 | > Note
43 | > The tool sets the `password.enforce_complexity` database flag to `on`,
44 | > requiring new database passwords to meet complexity rules.
45 | 
46 | ## Example
47 | 
48 | ```yaml
49 | tools:
50 |   create_instance:
51 |     kind: alloydb-create-instance
52 |     source: alloydb-admin-source
53 |     description: Use this tool to create a new AlloyDB instance within a specified cluster.
54 | ```
55 | 
56 | ## Reference
57 | 
58 | | **field**   | **type** | **required** | **description**                                      |
59 | | ----------- | :------: | :----------: | ---------------------------------------------------- |
60 | | kind        |  string  |     true     | Must be alloydb-create-instance.                     |
61 | | source      |  string  |     true     | The name of an `alloydb-admin` source.               |
62 | | description |  string  |     false    | Description of the tool that is passed to the agent. |
63 | 
```

--------------------------------------------------------------------------------
/internal/sources/bigtable/bigtable_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package bigtable_test
 16 | 
 17 | import (
 18 | 	"testing"
 19 | 
 20 | 	yaml "github.com/goccy/go-yaml"
 21 | 	"github.com/google/go-cmp/cmp"
 22 | 	"github.com/googleapis/genai-toolbox/internal/server"
 23 | 	"github.com/googleapis/genai-toolbox/internal/sources"
 24 | 	"github.com/googleapis/genai-toolbox/internal/sources/bigtable"
 25 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 26 | )
 27 | 
 28 | func TestParseFromYamlBigtableDb(t *testing.T) {
 29 | 	tcs := []struct {
 30 | 		desc string
 31 | 		in   string
 32 | 		want server.SourceConfigs
 33 | 	}{
 34 | 		{
 35 | 			desc: "can configure with a bigtable table",
 36 | 			in: `
 37 | 			sources:
 38 | 				my-bigtable-instance:
 39 | 					kind: bigtable
 40 | 					project: my-project
 41 | 					instance: my-instance
 42 | 			`,
 43 | 			want: map[string]sources.SourceConfig{
 44 | 				"my-bigtable-instance": bigtable.Config{
 45 | 					Name:     "my-bigtable-instance",
 46 | 					Kind:     bigtable.SourceKind,
 47 | 					Project:  "my-project",
 48 | 					Instance: "my-instance",
 49 | 				},
 50 | 			},
 51 | 		},
 52 | 	}
 53 | 	for _, tc := range tcs {
 54 | 		t.Run(tc.desc, func(t *testing.T) {
 55 | 			got := struct {
 56 | 				Sources server.SourceConfigs `yaml:"sources"`
 57 | 			}{}
 58 | 			// Parse contents
 59 | 			err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got)
 60 | 			if err != nil {
 61 | 				t.Fatalf("unable to unmarshal: %s", err)
 62 | 			}
 63 | 			if !cmp.Equal(tc.want, got.Sources) {
 64 | 				t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources)
 65 | 			}
 66 | 		})
 67 | 	}
 68 | 
 69 | }
 70 | 
 71 | func TestFailParseFromYaml(t *testing.T) {
 72 | 	tcs := []struct {
 73 | 		desc string
 74 | 		in   string
 75 | 		err  string
 76 | 	}{
 77 | 		{
 78 | 			desc: "extra field",
 79 | 			in: `
 80 | 			sources:
 81 | 				my-bigtable-instance:
 82 | 					kind: bigtable
 83 | 					project: my-project
 84 | 					instance: my-instance
 85 | 					foo: bar
 86 | 			`,
 87 | 			err: "unable to parse source \"my-bigtable-instance\" as \"bigtable\": [1:1] unknown field \"foo\"\n>  1 | foo: bar\n       ^\n   2 | instance: my-instance\n   3 | kind: bigtable\n   4 | project: my-project",
 88 | 		},
 89 | 		{
 90 | 			desc: "missing required field",
 91 | 			in: `
 92 | 			sources:
 93 | 				my-bigtable-instance:
 94 | 					kind: bigtable
 95 | 					project: my-project
 96 | 			`,
 97 | 			err: "unable to parse source \"my-bigtable-instance\" as \"bigtable\": Key: 'Config.Instance' Error:Field validation for 'Instance' failed on the 'required' tag",
 98 | 		},
 99 | 	}
100 | 	for _, tc := range tcs {
101 | 		t.Run(tc.desc, func(t *testing.T) {
102 | 			got := struct {
103 | 				Sources server.SourceConfigs `yaml:"sources"`
104 | 			}{}
105 | 			// Parse contents
106 | 			err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got)
107 | 			if err == nil {
108 | 				t.Fatalf("expect parsing to fail")
109 | 			}
110 | 			errStr := err.Error()
111 | 			if errStr != tc.err {
112 | 				t.Fatalf("unexpected error: got %q, want %q", errStr, tc.err)
113 | 			}
114 | 		})
115 | 	}
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookergetlooks/lookergetlooks_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookergetlooks_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetlooks"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerGetLooks(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-get-looks
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-get-looks",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerGetLooks(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-get-looks
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-get-looks\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-get-looks\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookermakelook/lookermakelook_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookermakelook_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookermakelook"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerMakeLook(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-make-look
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-make-look",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerMakeLook(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-make-look
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-make-look\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-make-look\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookerquerysql/lookerquerysql_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookerquerysql_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerquerysql"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerQuerySql(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-query-sql
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-query-sql",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerQuerySql(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-query-sql
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-query-sql\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-query-sql\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookerqueryurl/lookerqueryurl_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookerqueryurl_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerqueryurl"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerQueryUrl(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-query-url
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-query-url",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerQueryUrl(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-query-url
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-query-url\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-query-url\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package mongodbinsertmany_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	"github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbinsertmany"
 22 | 
 23 | 	yaml "github.com/goccy/go-yaml"
 24 | 	"github.com/google/go-cmp/cmp"
 25 | 	"github.com/googleapis/genai-toolbox/internal/server"
 26 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 27 | )
 28 | 
 29 | func TestParseFromYamlMongoQuery(t *testing.T) {
 30 | 	ctx, err := testutils.ContextWithNewLogger()
 31 | 	if err != nil {
 32 | 		t.Fatalf("unexpected error: %s", err)
 33 | 	}
 34 | 	tcs := []struct {
 35 | 		desc string
 36 | 		in   string
 37 | 		want server.ToolConfigs
 38 | 	}{
 39 | 		{
 40 | 			desc: "basic example",
 41 | 			in: `
 42 | 			tools:
 43 | 				example_tool:
 44 | 					kind: mongodb-insert-many
 45 | 					source: my-instance
 46 | 					description: some description
 47 | 					database: test_db
 48 | 					collection: test_coll
 49 | 					canonical: true
 50 | 			`,
 51 | 			want: server.ToolConfigs{
 52 | 				"example_tool": mongodbinsertmany.Config{
 53 | 					Name:         "example_tool",
 54 | 					Kind:         "mongodb-insert-many",
 55 | 					Source:       "my-instance",
 56 | 					AuthRequired: []string{},
 57 | 					Database:     "test_db",
 58 | 					Collection:   "test_coll",
 59 | 					Description:  "some description",
 60 | 					Canonical:    true,
 61 | 				},
 62 | 			},
 63 | 		},
 64 | 	}
 65 | 	for _, tc := range tcs {
 66 | 		t.Run(tc.desc, func(t *testing.T) {
 67 | 			got := struct {
 68 | 				Tools server.ToolConfigs `yaml:"tools"`
 69 | 			}{}
 70 | 			// Parse contents
 71 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 72 | 			if err != nil {
 73 | 				t.Fatalf("unable to unmarshal: %s", err)
 74 | 			}
 75 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 76 | 				t.Fatalf("incorrect parse: diff %v", diff)
 77 | 			}
 78 | 		})
 79 | 	}
 80 | 
 81 | }
 82 | 
 83 | func TestFailParseFromYamlMongoQuery(t *testing.T) {
 84 | 	ctx, err := testutils.ContextWithNewLogger()
 85 | 	if err != nil {
 86 | 		t.Fatalf("unexpected error: %s", err)
 87 | 	}
 88 | 	tcs := []struct {
 89 | 		desc string
 90 | 		in   string
 91 | 		err  string
 92 | 	}{
 93 | 		{
 94 | 			desc: "Invalid method",
 95 | 			in: `
 96 | 			tools:
 97 | 				example_tool:
 98 | 					kind: mongodb-insert-many
 99 | 					source: my-instance
100 | 					description: some description
101 | 					collection: test_coll
102 | 			`,
103 | 			err: `unable to parse tool "example_tool" as kind "mongodb-insert-many"`,
104 | 		},
105 | 	}
106 | 	for _, tc := range tcs {
107 | 		t.Run(tc.desc, func(t *testing.T) {
108 | 			got := struct {
109 | 				Tools server.ToolConfigs `yaml:"tools"`
110 | 			}{}
111 | 			// Parse contents
112 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
113 | 			if err == nil {
114 | 				t.Fatalf("expect parsing to fail")
115 | 			}
116 | 			errStr := err.Error()
117 | 			if !strings.Contains(errStr, tc.err) {
118 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
119 | 			}
120 | 		})
121 | 	}
122 | 
123 | }
124 | 
```

--------------------------------------------------------------------------------
/.hugo/layouts/partials/page-meta-links.html:
--------------------------------------------------------------------------------

```html
 1 | {{/* cSpell:ignore querify subdir */ -}}
 2 | {{/* Class names ending with `--KIND` are deprecated in favor of `__KIND`, but we're keeping them for a few releases after 0.9.0 */ -}}
 3 | 
 4 | {{ if .File -}}
 5 | {{ $path := urls.JoinPath $.Language.Lang $.File.Path -}}
 6 | {{ $gh_repo := $.Param "github_repo" -}}
 7 | {{ $gh_url := $.Param "github_url" -}}
 8 | {{ $gh_subdir := $.Param "github_subdir" | default "" -}}
 9 | {{ $gh_project_repo := $.Param "github_project_repo" -}}
10 | {{ $gh_branch := $.Param "github_branch" | default "main" -}}
11 | <div class="td-page-meta ms-2 pb-1 pt-2 mb-0">
12 | {{ if $gh_url -}}
13 |   {{ warnf "Warning: use of `github_url` is deprecated. For details, see https://www.docsy.dev/docs/adding-content/repository-links/#github_url-optional" -}}
14 |   <a href="{{ $gh_url }}" target="_blank"><i class="fa-solid fa-pen-to-square fa-fw"></i> {{ T "post_edit_this" }}</a>
15 | {{ else if $gh_repo -}}
16 | 
17 |   {{/* Adjust $path based on path_base_for_github_subdir */ -}}
18 |   {{ $ghs_base := $.Param "path_base_for_github_subdir" -}}
19 |   {{ $ghs_rename := "" -}}
20 |   {{ if reflect.IsMap $ghs_base -}}
21 |     {{ $ghs_rename = $ghs_base.to -}}
22 |     {{ $ghs_base = $ghs_base.from -}}
23 |   {{ end -}}
24 |   {{ with $ghs_base -}}
25 |     {{ $path = replaceRE . $ghs_rename $path -}}
26 |   {{ end -}}
27 | 
28 |   {{ $gh_repo_path := printf "%s/%s/%s" $gh_branch $gh_subdir $path -}}
29 |   {{ $gh_repo_path = replaceRE "//+" "/" $gh_repo_path -}}
30 | 
31 |   {{ $viewURL := printf "%s/tree/%s" $gh_repo $gh_repo_path -}}
32 |   {{ $editURL := printf "%s/edit/%s" $gh_repo $gh_repo_path -}}
33 |   {{ $issuesURL := printf "%s/issues/new?title=%s" $gh_repo (safeURL $.Title ) -}}
34 |   {{ $newPageStub := resources.Get "stubs/new-page-template.md" -}}
35 |   {{ $newPageQS := querify "value" $newPageStub.Content "filename" "change-me.md" | safeURL -}}
36 |   {{ $newPageURL := printf "%s/new/%s?%s" $gh_repo (path.Dir $gh_repo_path) $newPageQS -}}
37 | 
38 |   <a href="{{ $viewURL }}" class="td-page-meta--view td-page-meta__view" target="_blank" rel="noopener"><i class="fa-solid fa-file-lines fa-fw"></i> {{ T "post_view_this" }}</a>
39 |   <a href="{{ $editURL }}" class="td-page-meta--edit td-page-meta__edit" target="_blank" rel="noopener"><i class="fa-solid fa-pen-to-square fa-fw"></i> {{ T "post_edit_this" }}</a>
40 |   <a href="{{ $newPageURL }}" class="td-page-meta--child td-page-meta__child" target="_blank" rel="noopener"><i class="fa-solid fa-pen-to-square fa-fw"></i> {{ T "post_create_child_page" }}</a>
41 |   <a href="{{ $issuesURL }}" class="td-page-meta--issue td-page-meta__issue" target="_blank" rel="noopener"><i class="fa-solid fa-list-check fa-fw"></i> {{ T "post_create_issue" }}</a>
42 |   {{ with $gh_project_repo -}}
43 |     {{ $project_issueURL := printf "%s/issues/new" . -}}
44 |     <a href="{{ $project_issueURL }}" class="td-page-meta--project td-page-meta__project-issue" target="_blank" rel="noopener"><i class="fa-solid fa-list-check fa-fw"></i> {{ T "post_create_project_issue" }}</a>
45 |   {{ end -}}
46 | 
47 | {{ end -}}
48 | {{ with .CurrentSection.AlternativeOutputFormats.Get "print" -}}
49 |   <a id="print" href="{{ .RelPermalink | safeURL }}"><i class="fa-solid fa-print fa-fw"></i> {{ T "print_entire_section" }}</a>
50 | {{ end }}
51 | </div>
52 | {{ end -}}
53 | 
```

--------------------------------------------------------------------------------
/internal/sources/neo4j/neo4j.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2024 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package neo4j
 16 | 
 17 | import (
 18 | 	"context"
 19 | 	"fmt"
 20 | 
 21 | 	"github.com/goccy/go-yaml"
 22 | 	"github.com/googleapis/genai-toolbox/internal/sources"
 23 | 	"github.com/neo4j/neo4j-go-driver/v5/neo4j"
 24 | 	"go.opentelemetry.io/otel/trace"
 25 | )
 26 | 
 27 | const SourceKind string = "neo4j"
 28 | 
 29 | // validate interface
 30 | var _ sources.SourceConfig = Config{}
 31 | 
 32 | func init() {
 33 | 	if !sources.Register(SourceKind, newConfig) {
 34 | 		panic(fmt.Sprintf("source kind %q already registered", SourceKind))
 35 | 	}
 36 | }
 37 | 
 38 | func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources.SourceConfig, error) {
 39 | 	actual := Config{Name: name, Database: "neo4j"} // Default database
 40 | 	if err := decoder.DecodeContext(ctx, &actual); err != nil {
 41 | 		return nil, err
 42 | 	}
 43 | 	return actual, nil
 44 | }
 45 | 
 46 | type Config struct {
 47 | 	Name     string `yaml:"name" validate:"required"`
 48 | 	Kind     string `yaml:"kind" validate:"required"`
 49 | 	Uri      string `yaml:"uri" validate:"required"`
 50 | 	User     string `yaml:"user" validate:"required"`
 51 | 	Password string `yaml:"password" validate:"required"`
 52 | 	Database string `yaml:"database" validate:"required"`
 53 | }
 54 | 
 55 | func (r Config) SourceConfigKind() string {
 56 | 	return SourceKind
 57 | }
 58 | 
 59 | func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) {
 60 | 	driver, err := initNeo4jDriver(ctx, tracer, r.Uri, r.User, r.Password, r.Name)
 61 | 	if err != nil {
 62 | 		return nil, fmt.Errorf("unable to create driver: %w", err)
 63 | 	}
 64 | 
 65 | 	err = driver.VerifyConnectivity(ctx)
 66 | 	if err != nil {
 67 | 		return nil, fmt.Errorf("unable to connect successfully: %w", err)
 68 | 	}
 69 | 
 70 | 	if r.Database == "" {
 71 | 		r.Database = "neo4j"
 72 | 	}
 73 | 	s := &Source{
 74 | 		Name:     r.Name,
 75 | 		Kind:     SourceKind,
 76 | 		Database: r.Database,
 77 | 		Driver:   driver,
 78 | 	}
 79 | 	return s, nil
 80 | }
 81 | 
 82 | var _ sources.Source = &Source{}
 83 | 
 84 | type Source struct {
 85 | 	Name     string `yaml:"name"`
 86 | 	Kind     string `yaml:"kind"`
 87 | 	Database string `yaml:"database"`
 88 | 	Driver   neo4j.DriverWithContext
 89 | }
 90 | 
 91 | func (s *Source) SourceKind() string {
 92 | 	return SourceKind
 93 | }
 94 | 
 95 | func (s *Source) Neo4jDriver() neo4j.DriverWithContext {
 96 | 	return s.Driver
 97 | }
 98 | 
 99 | func (s *Source) Neo4jDatabase() string {
100 | 	return s.Database
101 | }
102 | 
103 | func initNeo4jDriver(ctx context.Context, tracer trace.Tracer, uri, user, password, name string) (neo4j.DriverWithContext, error) {
104 | 	//nolint:all // Reassigned ctx
105 | 	ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name)
106 | 	defer span.End()
107 | 
108 | 	auth := neo4j.BasicAuth(user, password, "")
109 | 	driver, err := neo4j.NewDriverWithContext(uri, auth)
110 | 	if err != nil {
111 | 		return nil, fmt.Errorf("unable to create connection driver: %w", err)
112 | 	}
113 | 	return driver, nil
114 | }
115 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookergetmodels/lookergetmodels_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookergetmodels_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetmodels"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerGetModels(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-get-models
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-get-models",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerGetModels(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-get-models
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-get-models\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-get-models\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/mongodb/mongodbinsertone/mongodbinsertone_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package mongodbinsertone_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	"github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbinsertone"
 22 | 
 23 | 	yaml "github.com/goccy/go-yaml"
 24 | 	"github.com/google/go-cmp/cmp"
 25 | 	"github.com/googleapis/genai-toolbox/internal/server"
 26 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 27 | )
 28 | 
 29 | func TestParseFromYamlMongoQuery(t *testing.T) {
 30 | 	ctx, err := testutils.ContextWithNewLogger()
 31 | 	if err != nil {
 32 | 		t.Fatalf("unexpected error: %s", err)
 33 | 	}
 34 | 	tcs := []struct {
 35 | 		desc string
 36 | 		in   string
 37 | 		want server.ToolConfigs
 38 | 	}{
 39 | 		{
 40 | 			desc: "basic example",
 41 | 			in: `
 42 | 			tools:
 43 | 				example_tool:
 44 | 					kind: mongodb-insert-one
 45 | 					source: my-instance
 46 | 					description: some description
 47 | 					database: test_db
 48 | 					collection: test_coll
 49 | 					canonical: true
 50 | 			`,
 51 | 			want: server.ToolConfigs{
 52 | 				"example_tool": mongodbinsertone.Config{
 53 | 					Name:         "example_tool",
 54 | 					Kind:         "mongodb-insert-one",
 55 | 					Source:       "my-instance",
 56 | 					AuthRequired: []string{},
 57 | 					Database:     "test_db",
 58 | 					Collection:   "test_coll",
 59 | 					Canonical:    true,
 60 | 					Description:  "some description",
 61 | 				},
 62 | 			},
 63 | 		},
 64 | 	}
 65 | 	for _, tc := range tcs {
 66 | 		t.Run(tc.desc, func(t *testing.T) {
 67 | 			got := struct {
 68 | 				Tools server.ToolConfigs `yaml:"tools"`
 69 | 			}{}
 70 | 			// Parse contents
 71 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 72 | 			if err != nil {
 73 | 				t.Fatalf("unable to unmarshal: %s", err)
 74 | 			}
 75 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 76 | 				t.Fatalf("incorrect parse: diff %v", diff)
 77 | 			}
 78 | 		})
 79 | 	}
 80 | 
 81 | }
 82 | 
 83 | func TestFailParseFromYamlMongoQuery(t *testing.T) {
 84 | 	ctx, err := testutils.ContextWithNewLogger()
 85 | 	if err != nil {
 86 | 		t.Fatalf("unexpected error: %s", err)
 87 | 	}
 88 | 	tcs := []struct {
 89 | 		desc string
 90 | 		in   string
 91 | 		err  string
 92 | 	}{
 93 | 		{
 94 | 			desc: "Invalid method",
 95 | 			in: `
 96 | 			tools:
 97 | 				example_tool:
 98 | 					kind: mongodb-insert-one
 99 | 					source: my-instance
100 | 					description: some description
101 | 					collection: test_coll
102 | 					canonical: true
103 | 			`,
104 | 			err: `unable to parse tool "example_tool" as kind "mongodb-insert-one"`,
105 | 		},
106 | 	}
107 | 	for _, tc := range tcs {
108 | 		t.Run(tc.desc, func(t *testing.T) {
109 | 			got := struct {
110 | 				Tools server.ToolConfigs `yaml:"tools"`
111 | 			}{}
112 | 			// Parse contents
113 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
114 | 			if err == nil {
115 | 				t.Fatalf("expect parsing to fail")
116 | 			}
117 | 			errStr := err.Error()
118 | 			if !strings.Contains(errStr, tc.err) {
119 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
120 | 			}
121 | 		})
122 | 	}
123 | 
124 | }
125 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookergetfilters/lookergetfilters_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookergetfilters_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetfilters"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerGetFilters(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-get-filters
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-get-filters",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerGetFilters(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-get-filters
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-get-filters\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-get-filters\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookergetexplores/lookergetexplores_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookergetexplores_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetexplores"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerGetExplores(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-get-explores
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-get-explores",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerGetFilters(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-get-explores
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-get-explores\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-get-explores\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookergetmeasures/lookergetmeasures_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookergetmeasures_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetmeasures"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerGetMeasures(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-get-measures
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-get-measures",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerGetMeasures(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-get-measures
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-get-measures\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-get-measures\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/sources/postgres.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "PostgreSQL"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   PostgreSQL is a powerful, open source object-relational database.
 7 | 
 8 | ---
 9 | 
10 | ## About
11 | 
12 | [PostgreSQL][pg-docs] is a powerful, open source object-relational database
13 | system with over 35 years of active development that has earned it a strong
14 | reputation for reliability, feature robustness, and performance.
15 | 
16 | [pg-docs]: https://www.postgresql.org/
17 | 
18 | ## Available Tools
19 | 
20 | - [`postgres-sql`](../tools/postgres/postgres-sql.md)
21 |   Execute SQL queries as prepared statements in PostgreSQL.
22 | 
23 | - [`postgres-execute-sql`](../tools/postgres/postgres-execute-sql.md)
24 |   Run parameterized SQL statements in PostgreSQL.
25 | 
26 | - [`postgres-list-tables`](../tools/postgres/postgres-list-tables.md)
27 |   List tables in a PostgreSQL database.
28 | 
29 | - [`postgres-list-active-queries`](../tools/postgres/postgres-list-active-queries.md)
30 |   List active queries in a PostgreSQL database.
31 | 
32 | - [`postgres-list-available-extensions`](../tools/postgres/postgres-list-available-extensions.md)
33 |   List available extensions for installation in a PostgreSQL database.
34 | 
35 | - [`postgres-list-installed-extensions`](../tools/postgres/postgres-list-installed-extensions.md)
36 |   List installed extensions in a PostgreSQL database.
37 | 
38 | ### Pre-built Configurations
39 | 
40 | - [PostgreSQL using MCP](https://googleapis.github.io/genai-toolbox/how-to/connect-ide/postgres_mcp/)
41 | Connect your IDE to PostgreSQL using Toolbox.
42 | 
43 | ## Requirements
44 | 
45 | ### Database User
46 | 
47 | This source only uses standard authentication. You will need to [create a
48 | PostgreSQL user][pg-users] to login to the database with.
49 | 
50 | [pg-users]: https://www.postgresql.org/docs/current/sql-createuser.html
51 | 
52 | ## Example
53 | 
54 | ```yaml
55 | sources:
56 |     my-pg-source:
57 |         kind: postgres
58 |         host: 127.0.0.1
59 |         port: 5432
60 |         database: my_db
61 |         user: ${USER_NAME}
62 |         password: ${PASSWORD}
63 | ```
64 | 
65 | {{< notice tip >}}
66 | Use environment variable replacement with the format ${ENV_NAME}
67 | instead of hardcoding your secrets into the configuration file.
68 | {{< /notice >}}
69 | 
70 | ## Reference
71 | 
72 | |  **field**  |      **type**      | **required** | **description**                                                        |
73 | |-------------|:------------------:|:------------:|------------------------------------------------------------------------|
74 | | kind        |       string       |     true     | Must be "postgres".                                                    |
75 | | host        |       string       |     true     | IP address to connect to (e.g. "127.0.0.1")                            |
76 | | port        |       string       |     true     | Port to connect to (e.g. "5432")                                       |
77 | | database    |       string       |     true     | Name of the Postgres database to connect to (e.g. "my_db").            |
78 | | user        |       string       |     true     | Name of the Postgres user to connect as (e.g. "my-pg-user").           |
79 | | password    |       string       |     true     | Password of the Postgres user (e.g. "my-password").                    |
80 | | queryParams |  map[string]string |     false    | Raw query to be added to the db connection string.                     |
81 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/sources/valkey.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "Valkey"
 3 | linkTitle: "Valkey"
 4 | type: docs
 5 | weight: 1
 6 | description: >
 7 |     Valkey is an open-source, in-memory data structure store, forked from Redis.
 8 |     
 9 | ---
10 | 
11 | ## About
12 | 
13 | Valkey is an open-source, in-memory data structure store that originated as a
14 | fork of Redis. It's designed to be used as a database, cache, and message
15 | broker, supporting a wide range of data structures like strings, hashes, lists,
16 | sets, sorted sets with range queries, bitmaps, hyperloglogs, and geospatial
17 | indexes with radius queries.
18 | 
19 | If you're new to Valkey, you can find installation and getting started guides on
20 | the [official Valkey website](https://valkey.io/topics/quickstart/).
21 | 
22 | ## Available Tools
23 | 
24 | - [`valkey`](../tools/valkey/valkey.md)  
25 |   Issue Valkey (Redis-compatible) commands.
26 | 
27 | ## Example
28 | 
29 | ```yaml
30 | sources:
31 |     my-valkey-instance:
32 |      kind: valkey
33 |      address:
34 |        - 127.0.0.1:6379
35 |      username: ${YOUR_USERNAME}
36 |      password: ${YOUR_PASSWORD}
37 |      # database: 0
38 |      # useGCPIAM: false
39 |      # disableCache: false
40 | ```
41 | 
42 | {{< notice tip >}}
43 | Use environment variable replacement with the format ${ENV_NAME}
44 | instead of hardcoding your secrets into the configuration file.
45 | {{< /notice >}}
46 | 
47 | ### IAM Authentication
48 | 
49 | If you are using GCP's Memorystore for Valkey, you can connect using IAM
50 | authentication. Grant your account the required [IAM role][iam] and set
51 | `useGCPIAM` to `true`:
52 | 
53 | ```yaml
54 | sources:
55 |     my-valkey-instance:
56 |      kind: valkey
57 |      address:
58 |        - 127.0.0.1:6379
59 |      useGCPIAM: true
60 | ```
61 | 
62 | [iam]: https://cloud.google.com/memorystore/docs/valkey/about-iam-auth
63 | 
64 | ## Reference
65 | 
66 | | **field**    | **type** | **required** | **description**                                                                                                                  |
67 | |--------------|:--------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------|
68 | | kind         |  string  |     true     | Must be "valkey".                                                                                                                |
69 | | address      | []string |     true     | Endpoints for the Valkey instance to connect to.                                                                                 |
70 | | username     |  string  |    false     | If you are using a non-default user, specify the user name here. If you are using Memorystore for Valkey, leave this field blank |
71 | | password     |  string  |    false     | Password for the Valkey instance                                                                                                 |
72 | | database     |   int    |    false     | The Valkey database to connect to. Not applicable for cluster enabled instances. The default database is `0`.                    |
73 | | useGCPIAM    |   bool   |    false     | Set it to `true` if you are using GCP's IAM authentication. Defaults to `false`.                                                 |
74 | | disableCache |   bool   |    false     | Set it to `true` if you want to enable client-side caching. Defaults to `false`.                                                 |
75 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/sources/couchbase.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "couchbase"
 3 | type: docs
 4 | weight: 1
 5 | description: > 
 6 |   A "couchbase" source connects to a Couchbase database.
 7 | ---
 8 | 
 9 | ## About
10 | 
11 | A `couchbase` source establishes a connection to a Couchbase database cluster,
12 | allowing tools to execute SQL queries against it.
13 | 
14 | ## Available Tools
15 | 
16 | - [`couchbase-sql`](../tools/couchbase/couchbase-sql.md)  
17 |   Run SQL++ statements on Couchbase with parameterized input.
18 | 
19 | ## Example
20 | 
21 | ```yaml
22 | sources:
23 |     my-couchbase-instance:
24 |         kind: couchbase
25 |         connectionString: couchbase://localhost
26 |         bucket: travel-sample
27 |         scope: inventory
28 |         username: Administrator
29 |         password: password
30 | ```
31 | 
32 | {{< notice note >}}
33 | For more details about alternate addresses and custom ports refer to [Managing Connections](https://docs.couchbase.com/java-sdk/current/howtos/managing-connections.html).
34 | {{< /notice >}}
35 | 
36 | ## Reference
37 | 
38 | | **field**            | **type** | **required** | **description**                                         |
39 | |----------------------|:--------:|:------------:|---------------------------------------------------------|
40 | | kind                 | string   |    true      | Must be "couchbase".                                    |
41 | | connectionString     | string   |    true      | Connection string for the Couchbase cluster.            |
42 | | bucket               | string   |    true      | Name of the bucket to connect to.                       |
43 | | scope                | string   |    true      | Name of the scope within the bucket.                    |
44 | | username             | string   |    false     | Username for authentication.                            |
45 | | password             | string   |    false     | Password for authentication.                            |
46 | | clientCert           | string   |    false     | Path to client certificate file for TLS authentication. |
47 | | clientCertPassword   | string   |    false     | Password for the client certificate.                    |
48 | | clientKey            | string   |    false     | Path to client key file for TLS authentication.         |
49 | | clientKeyPassword    | string   |    false     | Password for the client key.                            |
50 | | caCert               | string   |    false     | Path to CA certificate file.                            |
51 | | noSslVerify          | boolean  |    false     | If true, skip server certificate verification. **Warning:** This option should only be used in development or testing environments. Disabling SSL verification poses significant security risks in production as it makes your connection vulnerable to man-in-the-middle attacks. |
52 | | profile              | string   |    false     | Name of the connection profile to apply.                |
53 | | queryScanConsistency | integer  |    false     | Query scan consistency. Controls the consistency guarantee for index scanning. Values: 1 for "not_bounded" (fastest option, but results may not include the most recent operations), 2 for "request_plus" (highest consistency level, includes all operations up until the query started, but incurs a performance penalty). If not specified, defaults to the Couchbase Go SDK default. |
54 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookermakedashboard/lookermakedashboard_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookermakedashboard_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookermakedashboard"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerMakeDashboard(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-make-dashboard
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-make-dashboard",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlMakeDashboard(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-make-dashboard
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-make-dashboard\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-make-dashboard\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookergetdashboards/lookergetdashboards_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookergetdashboards_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetdashboards"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerGetDashboards(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-get-dashboards
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-get-dashboards",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerGetDashboards(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-get-dashboards
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-get-dashboards\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-get-dashboards\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookergetdimensions/lookergetdimensions_test.go:
--------------------------------------------------------------------------------

```go
  1 | // Copyright 2025 Google LLC
  2 | //
  3 | // Licensed under the Apache License, Version 2.0 (the "License");
  4 | // you may not use this file except in compliance with the License.
  5 | // You may obtain a copy of the License at
  6 | //
  7 | //     http://www.apache.org/licenses/LICENSE-2.0
  8 | //
  9 | // Unless required by applicable law or agreed to in writing, software
 10 | // distributed under the License is distributed on an "AS IS" BASIS,
 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | // See the License for the specific language governing permissions and
 13 | // limitations under the License.
 14 | 
 15 | package lookergetdimensions_test
 16 | 
 17 | import (
 18 | 	"strings"
 19 | 	"testing"
 20 | 
 21 | 	yaml "github.com/goccy/go-yaml"
 22 | 	"github.com/google/go-cmp/cmp"
 23 | 	"github.com/googleapis/genai-toolbox/internal/server"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | 	lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetdimensions"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerGetDimensions(t *testing.T) {
 29 | 	ctx, err := testutils.ContextWithNewLogger()
 30 | 	if err != nil {
 31 | 		t.Fatalf("unexpected error: %s", err)
 32 | 	}
 33 | 	tcs := []struct {
 34 | 		desc string
 35 | 		in   string
 36 | 		want server.ToolConfigs
 37 | 	}{
 38 | 		{
 39 | 			desc: "basic example",
 40 | 			in: `
 41 | 			tools:
 42 | 				example_tool:
 43 | 					kind: looker-get-dimensions
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 				`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lkr.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-get-dimensions",
 51 | 					Source:       "my-instance",
 52 | 					Description:  "some description",
 53 | 					AuthRequired: []string{},
 54 | 				},
 55 | 			},
 56 | 		},
 57 | 	}
 58 | 	for _, tc := range tcs {
 59 | 		t.Run(tc.desc, func(t *testing.T) {
 60 | 			got := struct {
 61 | 				Tools server.ToolConfigs `yaml:"tools"`
 62 | 			}{}
 63 | 			// Parse contents
 64 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 65 | 			if err != nil {
 66 | 				t.Fatalf("unable to unmarshal: %s", err)
 67 | 			}
 68 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 69 | 				t.Fatalf("incorrect parse: diff %v", diff)
 70 | 			}
 71 | 		})
 72 | 	}
 73 | 
 74 | }
 75 | 
 76 | func TestFailParseFromYamlLookerGetDimensions(t *testing.T) {
 77 | 	ctx, err := testutils.ContextWithNewLogger()
 78 | 	if err != nil {
 79 | 		t.Fatalf("unexpected error: %s", err)
 80 | 	}
 81 | 	tcs := []struct {
 82 | 		desc string
 83 | 		in   string
 84 | 		err  string
 85 | 	}{
 86 | 		{
 87 | 			desc: "Invalid method",
 88 | 			in: `
 89 | 			tools:
 90 | 				example_tool:
 91 | 					kind: looker-get-dimensions
 92 | 					source: my-instance
 93 | 					method: GOT
 94 | 					description: some description
 95 | 			`,
 96 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-get-dimensions\": [4:1] unknown field \"method\"\n   1 | authRequired: []\n   2 | description: some description\n   3 | kind: looker-get-dimensions\n>  4 | method: GOT\n       ^\n   5 | source: my-instance",
 97 | 		},
 98 | 	}
 99 | 	for _, tc := range tcs {
100 | 		t.Run(tc.desc, func(t *testing.T) {
101 | 			got := struct {
102 | 				Tools server.ToolConfigs `yaml:"tools"`
103 | 			}{}
104 | 			// Parse contents
105 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
106 | 			if err == nil {
107 | 				t.Fatalf("expect parsing to fail")
108 | 			}
109 | 			errStr := err.Error()
110 | 			if !strings.Contains(errStr, tc.err) {
111 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
112 | 			}
113 | 		})
114 | 	}
115 | 
116 | }
117 | 
```
Page 6/45FirstPrevNextLast