#
tokens: 49264/50000 36/786 files (page 5/45)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 5 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

--------------------------------------------------------------------------------
/internal/prebuiltconfigs/prebuiltconfigs.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 prebuiltconfigs
16 | 
17 | import (
18 | 	"embed"
19 | 	"fmt"
20 | 	"path"
21 | 	"strings"
22 | )
23 | 
24 | var (
25 | 	//go:embed tools/*.yaml
26 | 	prebuiltConfigsFS embed.FS
27 | 
28 | 	// Map of sources to their prebuilt tools
29 | 	prebuiltToolYAMLs map[string][]byte
30 | 	// List of sources with prebuilt tools
31 | 	prebuiltToolsSources []string
32 | )
33 | 
34 | func init() {
35 | 	var err error
36 | 	prebuiltToolYAMLs, prebuiltToolsSources, err = loadPrebuiltToolYAMLs()
37 | 	if err != nil {
38 | 		panic(fmt.Sprintf("Unexpected Error: %v\n", err))
39 | 	}
40 | }
41 | 
42 | // Getter for the prebuiltToolsSources
43 | func GetPrebuiltSources() []string {
44 | 	return prebuiltToolsSources
45 | }
46 | 
47 | // Get prebuilt tools for a source
48 | func Get(prebuiltSourceConfig string) ([]byte, error) {
49 | 	content, ok := prebuiltToolYAMLs[prebuiltSourceConfig]
50 | 	if !ok {
51 | 		prebuiltHelpSuffix := "no prebuilt configurations found."
52 | 		if len(prebuiltToolsSources) > 0 {
53 | 			prebuiltHelpSuffix = fmt.Sprintf("available: %s", strings.Join(prebuiltToolsSources, ", "))
54 | 		}
55 | 		errMsg := fmt.Errorf("prebuilt source tool for '%s' not found. %s", prebuiltSourceConfig, prebuiltHelpSuffix)
56 | 		return nil, errMsg
57 | 	}
58 | 	return content, nil
59 | }
60 | 
61 | // Load all available pre built tools
62 | func loadPrebuiltToolYAMLs() (map[string][]byte, []string, error) {
63 | 	toolYAMLs := make(map[string][]byte)
64 | 	var sourceTypes []string
65 | 	entries, err := prebuiltConfigsFS.ReadDir("tools")
66 | 	if err != nil {
67 | 		errMsg := fmt.Errorf("failed to read prebuilt tools %w", err)
68 | 		return nil, nil, errMsg
69 | 	}
70 | 
71 | 	for _, entry := range entries {
72 | 		lowerName := strings.ToLower(entry.Name())
73 | 		if !entry.IsDir() && (strings.HasSuffix(lowerName, ".yaml")) {
74 | 			filePathInFS := path.Join("tools", entry.Name())
75 | 			content, err := prebuiltConfigsFS.ReadFile(filePathInFS)
76 | 			if err != nil {
77 | 				errMsg := fmt.Errorf("failed to read a prebuilt tool %w", err)
78 | 				return nil, nil, errMsg
79 | 			}
80 | 			sourceTypeKey := entry.Name()[:len(entry.Name())-len(".yaml")]
81 | 
82 | 			sourceTypes = append(sourceTypes, sourceTypeKey)
83 | 			toolYAMLs[sourceTypeKey] = content
84 | 		}
85 | 	}
86 | 	if len(toolYAMLs) == 0 {
87 | 		errMsg := fmt.Errorf("no prebuilt tool configurations were loaded.%w", err)
88 | 		return nil, nil, errMsg
89 | 	}
90 | 
91 | 	return toolYAMLs, sourceTypes, nil
92 | }
93 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/mysql/mysql-list-table-fragmentation.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "mysql-list-table-fragmentation"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   A "mysql-list-table-fragmentation" tool lists top N fragemented tables in MySQL.
 7 | aliases:
 8 | - /resources/tools/mysql-list-table-fragmentation
 9 | ---
10 | 
11 | ## About
12 | 
13 | A `mysql-list-table-fragmentation` tool checks table fragmentation of MySQL
14 | tables by calculating the size of the data and index files in bytes and
15 | comparing with free space allocated to each table. This tool calculates
16 | `fragmentation_percentage` which represents the proportion of free space
17 | relative to the total data and index size. It's compatible with
18 | 
19 | - [cloud-sql-mysql](../../sources/cloud-sql-mysql.md)
20 | - [mysql](../../sources/mysql.md)
21 | 
22 | `mysql-list-table-fragmentation` outputs detailed information as JSON , ordered
23 | by the fragmentation percentage in descending order.
24 | This tool takes 4 optional input parameters:
25 | 
26 | - `table_schema` (optional): The database where fragmentation check is to be
27 |   executed. Check all tables visible to the current user if not specified.
28 | - `table_name` (optional): Name of the table to be checked. Check all tables
29 |   visible to the current user if not specified.
30 | - `data_free_threshold_bytes` (optional): Only show tables with at least this
31 |   much free space in bytes. Default 1.
32 | - `limit` (optional): Max rows to return, default 10.
33 | 
34 | ## Example
35 | 
36 | ```yaml
37 | tools:
38 |   list_table_fragmentation:
39 |     kind: mysql-list-table-fragmentation
40 |     source: my-mysql-instance
41 |     description: List table fragmentation in MySQL, by calculating the size of the data and index files and free space allocated to each table. The query calculates fragmentation percentage which represents the proportion of free space relative to the total data and index size. Storage can be reclaimed for tables with high fragmentation using OPTIMIZE TABLE.
42 | ```
43 | The response is a json array with the following fields:
44 | ```json
45 | {
46 |   "table_schema": "The schema/database this table belongs to",
47 |   "table_name": "Name of this table",
48 |   "data_size": "Size of the table data in bytes",
49 |   "index_size": "Size of the table's indexes in bytes",
50 |   "data_free": "Free space (bytes) available in the table's data file",
51 |   "fragmentation_percentage": "How much fragementation this table has",
52 | }
53 | ```
54 | 
55 | ## Reference
56 | 
57 | | **field**   | **type** | **required** | **description**                                    |
58 | |-------------|:--------:|:------------:|----------------------------------------------------|
59 | | kind        |  string  |     true     | Must be "mysql-list-table-fragmentation".          |
60 | | source      |  string  |     true     | Name of the source the SQL should execute on.      |
61 | | description |  string  |     true     | Description of the tool that is passed to the LLM. |
62 | 
```

--------------------------------------------------------------------------------
/internal/tools/neo4j/neo4jschema/neo4jschema_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 not use this file except in compliance with the License.
  6 | // You may obtain a copy of the License at
  7 | //
  8 | //     http://www.apache.org/licenses/LICENSE-2.0
  9 | //
 10 | // Unless required by applicable law or agreed to in writing, software
 11 | // distributed under the License is distributed on an "AS IS" BASIS,
 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 | // See the License for the specific language governing permissions and
 14 | // limitations under the License.
 15 | 
 16 | package neo4jschema
 17 | 
 18 | import (
 19 | 	"testing"
 20 | 
 21 | 	"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 | )
 26 | 
 27 | func TestParseFromYamlNeo4j(t *testing.T) {
 28 | 	ctx, err := testutils.ContextWithNewLogger()
 29 | 	exp := 30
 30 | 
 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 with default cache expiration",
 41 | 			in: `
 42 | 			tools:
 43 | 				example_tool:
 44 | 					kind: neo4j-schema
 45 | 					source: my-neo4j-instance
 46 | 					description: some tool description
 47 | 					authRequired:
 48 | 						- my-google-auth-service
 49 | 						- other-auth-service
 50 | 			`,
 51 | 			want: server.ToolConfigs{
 52 | 				"example_tool": Config{
 53 | 					Name:               "example_tool",
 54 | 					Kind:               "neo4j-schema",
 55 | 					Source:             "my-neo4j-instance",
 56 | 					Description:        "some tool description",
 57 | 					AuthRequired:       []string{"my-google-auth-service", "other-auth-service"},
 58 | 					CacheExpireMinutes: nil,
 59 | 				},
 60 | 			},
 61 | 		},
 62 | 		{
 63 | 			desc: "cache expire minutes set explicitly",
 64 | 			in: `
 65 | 			tools:
 66 | 				example_tool:
 67 | 					kind: neo4j-schema
 68 | 					source: my-neo4j-instance
 69 | 					description: some tool description
 70 | 					cacheExpireMinutes: 30
 71 | 			`,
 72 | 			want: server.ToolConfigs{
 73 | 				"example_tool": Config{
 74 | 					Name:               "example_tool",
 75 | 					Kind:               "neo4j-schema",
 76 | 					Source:             "my-neo4j-instance",
 77 | 					Description:        "some tool description",
 78 | 					AuthRequired:       []string{}, // Expect an empty slice, not nil.
 79 | 					CacheExpireMinutes: &exp,
 80 | 				},
 81 | 			},
 82 | 		},
 83 | 	}
 84 | 	for _, tc := range tcs {
 85 | 		t.Run(tc.desc, func(t *testing.T) {
 86 | 			got := struct {
 87 | 				Tools server.ToolConfigs `yaml:"tools"`
 88 | 			}{}
 89 | 			// Parse contents
 90 | 			err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 91 | 			if err != nil {
 92 | 				t.Fatalf("unable to unmarshal: %s", err)
 93 | 			}
 94 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 95 | 				t.Fatalf("incorrect parse: diff %v", diff)
 96 | 			}
 97 | 		})
 98 | 	}
 99 | }
100 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/mongodb/mongodb-delete-many.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "mongodb-delete-many"
 3 | type: docs
 4 | weight: 1
 5 | description: > 
 6 |   A "mongodb-delete-many" tool deletes all documents from a MongoDB collection that match a filter.
 7 | aliases:
 8 | - /resources/tools/mongodb-delete-many
 9 | ---
10 | 
11 | ## About
12 | 
13 | The `mongodb-delete-many` tool performs a **bulk destructive operation**,
14 | deleting **ALL** documents from a collection that match a specified filter.
15 | 
16 | The tool returns the total count of documents that were deleted. If the filter
17 | does not match any documents (i.e., the deleted count is 0), the tool will
18 | return an error.
19 | 
20 | This tool is compatible with the following source kind:
21 | 
22 | * [`mongodb`](../../sources/mongodb.md)
23 | 
24 | ---
25 | 
26 | ## Example
27 | 
28 | Here is an example that performs a cleanup task by deleting all products from
29 | the `inventory` collection that belong to a discontinued brand.
30 | 
31 | ```yaml
32 | tools:
33 |   retire_brand_products:
34 |     kind: mongodb-delete-many
35 |     source: my-mongo-source
36 |     description: Deletes all products from a specified discontinued brand.
37 |     database: ecommerce
38 |     collection: inventory
39 |     filterPayload: |
40 |         { "brand_name": {{json .brand_to_delete}} }
41 |     filterParams:
42 |       - name: brand_to_delete
43 |         type: string
44 |         description: The name of the discontinued brand whose products should be deleted.
45 | ```
46 | 
47 | ## Reference
48 | 
49 | | **field**     | **type** | **required** | **description**                                                                                                     |
50 | |:--------------|:---------|:-------------|:--------------------------------------------------------------------------------------------------------------------|
51 | | kind          | string   | true         | Must be `mongodb-delete-many`.                                                                                      |
52 | | source        | string   | true         | The name of the `mongodb` source to use.                                                                            |
53 | | description   | string   | true         | A description of the tool that is passed to the LLM.                                                                |
54 | | database      | string   | true         | The name of the MongoDB database containing the collection.                                                         |
55 | | collection    | string   | true         | The name of the MongoDB collection from which to delete documents.                                                  |
56 | | filterPayload | string   | true         | The MongoDB query filter document to select the documents for deletion. Uses `{{json .param_name}}` for templating. |
57 | | filterParams  | list     | true         | A list of parameter objects that define the variables used in the `filterPayload`.                                  |
58 | 
```

--------------------------------------------------------------------------------
/docs/en/getting-started/local_quickstart_js.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | title: "JS Quickstart (Local)"
  3 | type: docs
  4 | weight: 3
  5 | description: >
  6 |   How to get started running Toolbox locally with [JavaScript](https://github.com/googleapis/mcp-toolbox-sdk-js), PostgreSQL, and orchestration frameworks such as [LangChain](https://js.langchain.com/docs/introduction/), [GenkitJS](https://genkit.dev/docs/get-started/),  [LlamaIndex](https://ts.llamaindex.ai/) and [GoogleGenAI](https://github.com/googleapis/js-genai).
  7 | ---
  8 | 
  9 | ## Before you begin
 10 | 
 11 | This guide assumes you have already done the following:
 12 | 
 13 | 1. Installed [Node.js (v18 or higher)].
 14 | 1. Installed [PostgreSQL 16+ and the `psql` client][install-postgres].
 15 | 
 16 | [Node.js (v18 or higher)]: https://nodejs.org/
 17 | [install-postgres]: https://www.postgresql.org/download/
 18 | 
 19 | ### Cloud Setup (Optional)
 20 | 
 21 | {{< regionInclude "quickstart/shared/cloud_setup.md" "cloud_setup" >}}
 22 | 
 23 | ## Step 1: Set up your database
 24 | 
 25 | {{< regionInclude "quickstart/shared/database_setup.md" "database_setup" >}}
 26 | 
 27 | ## Step 2: Install and configure Toolbox
 28 | 
 29 | {{< regionInclude "quickstart/shared/configure_toolbox.md" "configure_toolbox" >}}
 30 | 
 31 | ## Step 3: Connect your agent to Toolbox
 32 | 
 33 | In this section, we will write and run an agent that will load the Tools
 34 | from Toolbox.
 35 | 
 36 | 1. (Optional) Initialize a Node.js project:
 37 | 
 38 |     ```bash
 39 |     npm init -y
 40 |     ```
 41 | 
 42 | 1. In a new terminal, install the
 43 |    [SDK](https://www.npmjs.com/package/@toolbox-sdk/core).
 44 | 
 45 |     ```bash
 46 |     npm install @toolbox-sdk/core
 47 |     ```
 48 | 
 49 | 1. Install other required dependencies
 50 | 
 51 |    {{< tabpane persist=header >}}
 52 | {{< tab header="LangChain" lang="bash" >}}
 53 | npm install langchain @langchain/google-genai
 54 | {{< /tab >}}
 55 | {{< tab header="GenkitJS" lang="bash" >}}
 56 | npm install genkit @genkit-ai/googleai
 57 | {{< /tab >}}
 58 | {{< tab header="LlamaIndex" lang="bash" >}}
 59 | npm install llamaindex @llamaindex/google @llamaindex/workflow
 60 | {{< /tab >}}
 61 | {{< tab header="GoogleGenAI" lang="bash" >}}
 62 | npm install @google/genai 
 63 | {{< /tab >}}
 64 | {{< /tabpane >}}
 65 | 
 66 | 1. Create a new file named `hotelAgent.js` and copy the following code to create
 67 |    an agent:
 68 | 
 69 |     {{< tabpane persist=header >}}
 70 | {{< tab header="LangChain" lang="js" >}}
 71 | 
 72 | {{< include "quickstart/js/langchain/quickstart.js" >}}
 73 | 
 74 | {{< /tab >}}
 75 | 
 76 | {{< tab header="GenkitJS" lang="js" >}}
 77 | 
 78 | {{< include "quickstart/js/genkit/quickstart.js" >}}
 79 | 
 80 | {{< /tab >}}
 81 | 
 82 | {{< tab header="LlamaIndex" lang="js" >}}
 83 | 
 84 | {{< include "quickstart/js/llamaindex/quickstart.js" >}}
 85 | 
 86 | {{< /tab >}}
 87 | 
 88 | {{< tab header="GoogleGenAI" lang="js" >}}
 89 | 
 90 | {{< include "quickstart/js/genAI/quickstart.js" >}}
 91 | 
 92 | {{< /tab >}}
 93 | 
 94 | {{< /tabpane >}}
 95 | 
 96 | 1. Run your agent, and observe the results:
 97 | 
 98 |     ```sh
 99 |     node hotelAgent.js
100 |     ```
101 | 
102 | {{< notice info >}}
103 | For more information, visit the [JS SDK
104 | repo](https://github.com/googleapis/mcp-toolbox-sdk-js).
105 | {{</ notice >}}
106 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/neo4j/neo4j-execute-cypher.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "neo4j-execute-cypher"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   A "neo4j-execute-cypher" tool executes any arbitrary Cypher statement against a Neo4j
 7 |   database.
 8 | aliases:
 9 | - /resources/tools/neo4j-execute-cypher
10 | ---
11 | 
12 | ## About
13 | 
14 | A `neo4j-execute-cypher` tool executes an arbitrary Cypher query provided as a
15 | string parameter against a Neo4j database. It's designed to be a flexible tool
16 | for interacting with the database when a pre-defined query is not sufficient.
17 | This tool is compatible with any of the following sources:
18 | 
19 | - [neo4j](../../sources/neo4j.md)
20 | 
21 | For security, the tool can be configured to be read-only. If the `readOnly` flag
22 | is set to `true`, the tool will analyze the incoming Cypher query and reject any
23 | write operations (like `CREATE`, `MERGE`, `DELETE`, etc.) before execution.
24 | 
25 | The Cypher query uses standard [Neo4j
26 | Cypher](https://neo4j.com/docs/cypher-manual/current/queries/) syntax and
27 | supports all Cypher features, including pattern matching, filtering, and
28 | aggregation.
29 | 
30 | `neo4j-execute-cypher` takes one input parameter `cypher` and run the cypher
31 | query against the `source`.
32 | 
33 | > **Note:** This tool is intended for developer assistant workflows with
34 | > human-in-the-loop and shouldn't be used for production agents.
35 | 
36 | ## Example
37 | 
38 | ```yaml
39 | tools:
40 |   query_neo4j:
41 |     kind: neo4j-execute-cypher
42 |     source: my-neo4j-prod-db
43 |     readOnly: true
44 |     description: |
45 |       Use this tool to execute a Cypher query against the production database.
46 |       Only read-only queries are allowed.
47 |       Takes a single 'cypher' parameter containing the full query string.
48 |       Example:
49 |       {{
50 |           "cypher": "MATCH (m:Movie {title: 'The Matrix'}) RETURN m.released"
51 |       }}
52 | ```
53 | 
54 | ## Reference
55 | 
56 | | **field**   |                  **type**                  | **required** | **description**                                                                                 |
57 | |-------------|:------------------------------------------:|:------------:|-------------------------------------------------------------------------------------------------|
58 | | kind        |                   string                   |     true     | Must be "neo4j-cypher".                                                                         |
59 | | source      |                   string                   |     true     | Name of the source the Cypher query should execute on.                                          |
60 | | description |                   string                   |     true     | Description of the tool that is passed to the LLM.                                              |
61 | | readOnly    |                   boolean                  |     false    | If set to `true`, the tool will reject any write operations in the Cypher query. Default is `false`. |
62 | 
```

--------------------------------------------------------------------------------
/docs/en/samples/looker/looker_mcp_inspector/_index.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | title: "Quickstart (MCP with Looker)"
  3 | type: docs
  4 | weight: 2
  5 | description: >
  6 |   How to get started running Toolbox with MCP Inspector and Looker as the source.
  7 | ---
  8 | 
  9 | ## Overview
 10 | 
 11 | [Model Context Protocol](https://modelcontextprotocol.io) is an open protocol
 12 | that standardizes how applications provide context to LLMs. Check out this page
 13 | on how to [connect to Toolbox via MCP](../../how-to/connect_via_mcp.md).
 14 | 
 15 | ## Step 1: Get a Looker Client ID and Client Secret
 16 | 
 17 | The Looker Client ID and Client Secret can be obtained from the Users page of
 18 | your Looker instance. Refer to the documentation
 19 | [here](https://cloud.google.com/looker/docs/api-auth#authentication_with_an_sdk).
 20 | You may need to ask an administrator to get the Client ID and Client Secret
 21 | for you.
 22 | 
 23 | ## Step 2: Install and configure Toolbox
 24 | 
 25 | In this section, we will download Toolbox and run the Toolbox server.
 26 | 
 27 | 1. Download the latest version of Toolbox as a binary:
 28 | 
 29 |     {{< notice tip >}}
 30 |    Select the
 31 |    [correct binary](https://github.com/googleapis/genai-toolbox/releases)
 32 |    corresponding to your OS and CPU architecture.
 33 |     {{< /notice >}}
 34 |     <!-- {x-release-please-start-version} -->
 35 |     ```bash
 36 |     export OS="linux/amd64" # one of linux/amd64, darwin/arm64, darwin/amd64, or windows/amd64
 37 |     curl -O https://storage.googleapis.com/genai-toolbox/v0.17.0/$OS/toolbox
 38 |     ```
 39 |     <!-- {x-release-please-end} -->
 40 | 
 41 | 1. Make the binary executable:
 42 | 
 43 |     ```bash
 44 |     chmod +x toolbox
 45 |     ```
 46 | 
 47 | 1. Create a file `looker_env` with the settings for your
 48 |    Looker instance. Use the Client ID and Client Secret
 49 |    you obtained earlier.
 50 | 
 51 |    ```bash
 52 |     export LOOKER_BASE_URL=https://looker.example.com
 53 |     export LOOKER_VERIFY_SSL=true
 54 |     export LOOKER_CLIENT_ID=Q7ynZkRkvj9S9FHPm4Wj
 55 |     export LOOKER_CLIENT_SECRET=P5JvZstFnhpkhCYy2yNSfJ6x
 56 |    ```
 57 | 
 58 |    In some instances you may need to append `:19999` to
 59 |    the LOOKER_BASE_URL.
 60 | 
 61 | 1. Load the looker_env file into your environment.
 62 | 
 63 |    ```bash
 64 |    source looker_env
 65 |    ```
 66 | 
 67 | 1. Run the Toolbox server using the prebuilt Looker tools.
 68 | 
 69 |     ```bash
 70 |     ./toolbox --prebuilt looker
 71 |     ```
 72 | 
 73 | ## Step 3: Connect to MCP Inspector
 74 | 
 75 | 1. Run the MCP Inspector:
 76 | 
 77 |     ```bash
 78 |     npx @modelcontextprotocol/inspector
 79 |     ```
 80 | 
 81 | 1. Type `y` when it asks to install the inspector package.
 82 | 
 83 | 1. It should show the following when the MCP Inspector is up and running:
 84 | 
 85 |     ```bash
 86 |     🔍 MCP Inspector is up and running at http://127.0.0.1:5173 🚀
 87 |     ```
 88 | 
 89 | 1. Open the above link in your browser.
 90 | 
 91 | 1. For `Transport Type`, select `SSE`.
 92 | 
 93 | 1. For `URL`, type in `http://127.0.0.1:5000/mcp/sse`.
 94 | 
 95 | 1. Click Connect.
 96 | 
 97 |     ![inspector](./inspector.png)
 98 | 
 99 | 1. Select `List Tools`, you will see a list of tools.
100 | 
101 |     ![inspector_tools](./inspector_tools.png)
102 | 
103 | 1. Test out your tools here!
104 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/mysql/mysql-list-active-queries.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "mysql-list-active-queries"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   A "mysql-list-active-queries" tool lists active queries in a MySQL database.
 7 | aliases:
 8 | - /resources/tools/mysql-list-active-queries
 9 | ---
10 | 
11 | ## About
12 | 
13 | A `mysql-list-active-queries` tool retrieves information about active queries in
14 | a MySQL database. It's compatible with:
15 | 
16 | - [cloud-sql-mysql](../../sources/cloud-sql-mysql.md)
17 | - [mysql](../../sources/mysql.md)
18 | 
19 | `mysql-list-active-queries` outputs detailed information as JSON for current
20 | active queries, ordered by execution time in descending order.
21 | This tool takes 2 optional input parameters:
22 | 
23 | - `min_duration_secs` (optional): Only show queries running for at least this
24 |   long in seconds, default `0`.
25 | - `limit` (optional):  max number of queries to return, default `10`.
26 | 
27 | ## Example
28 | 
29 | ```yaml
30 | tools:
31 |   list_active_queries:
32 |     kind: mysql-list-active-queries
33 |     source: my-mysql-instance
34 |     description: Lists top N (default 10) ongoing queries from processlist and innodb_trx, ordered by execution time in descending order. Returns detailed information of those queries in json format, including process id, query, transaction duration, transaction wait duration, process time, transaction state, process state, username with host, transaction rows locked, transaction rows modified, and db schema.
35 | ```
36 | 
37 | The response is a json array with the following fields:
38 | 
39 | ```json
40 | {
41 |   "proccess_id": "id of the MySQL process/connection this query belongs to",
42 |   "query": "query text",
43 |   "trx_started": "the time when the transaction (this query belongs to) started",
44 |   "trx_duration_seconds": "the total elapsed time (in seconds) of the owning transaction so far",
45 |   "trx_wait_duration_seconds": "the total wait time (in seconds) of the owning transaction so far",
46 |   "query_time": "the time (in seconds) that the owning connection has been in its current state",
47 |   "trx_state": "the transaction execution state",
48 |   "proces_state": "the current state of the owning connection",
49 |   "user": "the user who issued this query",
50 |   "trx_rows_locked": "the approximate number of rows locked by the owning transaction",
51 |   "trx_rows_modified": "the approximate number of rows modified by the owning transaction",
52 |   "db": "the default database for the owning connection"
53 | }
54 | ```
55 | 
56 | ## Reference
57 | 
58 | | **field**   | **type** | **required** | **description**                                    |
59 | |-------------|:--------:|:------------:|----------------------------------------------------|
60 | | kind        |  string  |     true     | Must be "mysql-list-active-queries".               |
61 | | source      |  string  |     true     | Name of the source the SQL should execute on.      |
62 | | description |  string  |     true     | Description of the tool that is passed to the LLM. |
63 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/looker/looker-health-pulse.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "looker-health-pulse"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   "looker-health-pulse" performs health checks on a Looker instance, with multiple actions available (e.g., checking database connections, dashboard performance, etc).
 7 | aliases:
 8 | - /resources/tools/looker-health-pulse
 9 | ---
10 | 
11 | ## About
12 | 
13 | The `looker-health-pulse` tool performs health checks on a Looker instance. The `action` parameter selects the type of check to perform:
14 | 
15 | - `check_db_connections`: Checks all database connections, runs supported tests, and reports query counts.
16 | - `check_dashboard_performance`: Finds dashboards with slow running queries in the last 7 days.
17 | - `check_dashboard_errors`: Lists dashboards with erroring queries in the last 7 days.
18 | - `check_explore_performance`: Lists the slowest explores in the last 7 days and reports average query runtime.
19 | - `check_schedule_failures`: Lists schedules that have failed in the last 7 days.
20 | - `check_legacy_features`: Lists enabled legacy features. (*To note, this function is not available in Looker Core. You will get an error running this command with a Core instance configured.*)
21 | 
22 | ## Parameters
23 | 
24 | | **field**     | **type** | **required** | **description**                             |
25 | |---------------|:--------:|:------------:|---------------------------------------------|
26 | | kind          | string   | true         | Must be "looker-health-pulse"                      |
27 | | source        | string   | true         | Looker source name                          |
28 | | action        | string   | true         | The health check to perform                 |
29 | 
30 | ## Example
31 | 
32 | ```yaml
33 | tools:
34 |   pulse:
35 |     kind: looker-health-pulse
36 |     source: looker-source
37 |     description: |
38 |       Pulse Tool
39 | 
40 |       Performs health checks on Looker instance.
41 |       Specify the `action` parameter to select the check.
42 |     parameters:
43 |       action: check_dashboard_performance
44 | ```
45 | 
46 | ## Reference
47 | 
48 | | **action**                | **description**                                                                |
49 | |---------------------------|--------------------------------------------------------------------------------|
50 | | check_db_connections      | Checks all database connections and reports query counts and errors            |
51 | | check_dashboard_performance | Finds dashboards with slow queries (>30s) in the last 7 days                 |
52 | | check_dashboard_errors    | Lists dashboards with erroring queries in the last 7 days                      |
53 | | check_explore_performance | Lists slowest explores and average query runtime                               |
54 | | check_schedule_failures   | Lists failed schedules in the last 7 days                                      |
55 | | check_legacy_features     | Lists enabled legacy features                                                  |
```

--------------------------------------------------------------------------------
/internal/sources/sqlite/sqlite.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 sqlite
 16 | 
 17 | import (
 18 | 	"context"
 19 | 	"database/sql"
 20 | 	"fmt"
 21 | 
 22 | 	"github.com/goccy/go-yaml"
 23 | 	"github.com/googleapis/genai-toolbox/internal/sources"
 24 | 	"go.opentelemetry.io/otel/trace"
 25 | 	_ "modernc.org/sqlite" // Pure Go SQLite driver
 26 | )
 27 | 
 28 | const SourceKind string = "sqlite"
 29 | 
 30 | // validate interface
 31 | var _ sources.SourceConfig = Config{}
 32 | 
 33 | func init() {
 34 | 	if !sources.Register(SourceKind, newConfig) {
 35 | 		panic(fmt.Sprintf("source kind %q already registered", SourceKind))
 36 | 	}
 37 | }
 38 | 
 39 | func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources.SourceConfig, error) {
 40 | 	actual := Config{Name: name}
 41 | 	if err := decoder.DecodeContext(ctx, &actual); err != nil {
 42 | 		return nil, err
 43 | 	}
 44 | 	return actual, nil
 45 | }
 46 | 
 47 | type Config struct {
 48 | 	Name     string `yaml:"name" validate:"required"`
 49 | 	Kind     string `yaml:"kind" validate:"required"`
 50 | 	Database string `yaml:"database" validate:"required"` // Path to SQLite database file
 51 | }
 52 | 
 53 | func (r Config) SourceConfigKind() string {
 54 | 	return SourceKind
 55 | }
 56 | 
 57 | func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) {
 58 | 	db, err := initSQLiteConnection(ctx, tracer, r.Name, r.Database)
 59 | 	if err != nil {
 60 | 		return nil, fmt.Errorf("unable to create db connection: %w", err)
 61 | 	}
 62 | 
 63 | 	err = db.PingContext(context.Background())
 64 | 	if err != nil {
 65 | 		return nil, fmt.Errorf("unable to connect successfully: %w", err)
 66 | 	}
 67 | 
 68 | 	s := &Source{
 69 | 		Name: r.Name,
 70 | 		Kind: SourceKind,
 71 | 		Db:   db,
 72 | 	}
 73 | 	return s, nil
 74 | }
 75 | 
 76 | var _ sources.Source = &Source{}
 77 | 
 78 | type Source struct {
 79 | 	Name string `yaml:"name"`
 80 | 	Kind string `yaml:"kind"`
 81 | 	Db   *sql.DB
 82 | }
 83 | 
 84 | func (s *Source) SourceKind() string {
 85 | 	return SourceKind
 86 | }
 87 | 
 88 | func (s *Source) SQLiteDB() *sql.DB {
 89 | 	return s.Db
 90 | }
 91 | 
 92 | func initSQLiteConnection(ctx context.Context, tracer trace.Tracer, name, dbPath string) (*sql.DB, error) {
 93 | 	//nolint:all // Reassigned ctx
 94 | 	ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name)
 95 | 	defer span.End()
 96 | 
 97 | 	// Open database connection
 98 | 	db, err := sql.Open("sqlite", dbPath)
 99 | 	if err != nil {
100 | 		return nil, fmt.Errorf("sql.Open: %w", err)
101 | 	}
102 | 
103 | 	// Set some reasonable defaults for SQLite
104 | 	db.SetMaxOpenConns(1) // SQLite only supports one writer at a time
105 | 	db.SetMaxIdleConns(1)
106 | 
107 | 	return db, nil
108 | }
109 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/postgres/postgres-list-active-queries.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "postgres-list-active-queries"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   The "postgres-list-active-queries" tool lists currently active queries in a Postgres database.
 7 | aliases:
 8 | - /resources/tools/postgres-list-active-queries
 9 | ---
10 | 
11 | ## About
12 | 
13 | The `postgres-list-active-queries` tool retrieves information about currently
14 | active queries in a Postgres database. It's compatible with any of the following
15 | sources:
16 | 
17 | - [alloydb-postgres](../../sources/alloydb-pg.md)
18 | - [cloud-sql-postgres](../../sources/cloud-sql-pg.md)
19 | - [postgres](../../sources/postgres.md)
20 | 
21 | `postgres-list-active-queries` lists detailed information as JSON for currently
22 | active queries. The tool takes the following input parameters:
23 | 
24 | - `min_duraton` (optional): Only show queries running at least this long (e.g.,
25 |   '1 minute', '1 second', '2 seconds'). Default: '1 minute'.
26 | - `exclude_application_names` (optional): A comma-separated list of application
27 |   names to exclude from the query results. This is useful for filtering out
28 |   queries from specific applications (e.g., 'psql', 'pgAdmin', 'DBeaver'). The
29 |   match is case-sensitive. Whitespace around commas and names is automatically
30 |   handled. If this parameter is omitted, no applications are excluded.
31 | - `limit` (optional): The maximum number of rows to return. Default: `50`.
32 | 
33 | ## Example
34 | 
35 | ```yaml
36 | tools:
37 |   list_active_queries:
38 |     kind: postgres-list-active-queries
39 |     source: postgres-source
40 |     description: List the top N (default 50) currently running queries (state='active') from pg_stat_activity, ordered by longest-running first. Returns pid, user, database, application_name, client_addr, state, wait_event_type/wait_event, backend/xact/query start times, computed query_duration, and the SQL text.
41 | ```
42 | 
43 | The response is a json array with the following elements:
44 | 
45 | ```json
46 | {
47 |   "pid": "process id",
48 |   "user": "database user name",
49 |   "datname": "database name",
50 |   "application_name": "connecting application name",
51 |   "client_addr": "connecting client ip address",
52 |   "state": "connection state",
53 |   "wait_event_type": "connection wait event type",
54 |   "wait_event": "connection wait event",
55 |   "backend_start": "connection start time",
56 |   "xact_start": "transaction start time",
57 |   "query_start": "query start time",
58 |   "query_duration": "query duration",
59 |   "query": "query text"
60 | }
61 | ```
62 | 
63 | ## Reference
64 | 
65 | | **field**   | **type** | **required** | **description**                                    |
66 | |-------------|:--------:|:------------:|----------------------------------------------------|
67 | | kind        |  string  |     true     | Must be "postgres-list-active-queries".            |
68 | | source      |  string  |     true     | Name of the source the SQL should execute on.      |
69 | | description |  string  |     true     | Description of the tool that is passed to the LLM. |
70 | 
```

--------------------------------------------------------------------------------
/internal/sources/dataplex/dataplex_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 dataplex_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/dataplex"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | )
 26 | 
 27 | func TestParseFromYamlDataplex(t *testing.T) {
 28 | 	tcs := []struct {
 29 | 		desc string
 30 | 		in   string
 31 | 		want server.SourceConfigs
 32 | 	}{
 33 | 		{
 34 | 			desc: "basic example",
 35 | 			in: `
 36 | 			sources:
 37 | 				my-instance:
 38 | 					kind: dataplex
 39 | 					project: my-project
 40 | 			`,
 41 | 			want: server.SourceConfigs{
 42 | 				"my-instance": dataplex.Config{
 43 | 					Name:    "my-instance",
 44 | 					Kind:    dataplex.SourceKind,
 45 | 					Project: "my-project",
 46 | 				},
 47 | 			},
 48 | 		},
 49 | 	}
 50 | 	for _, tc := range tcs {
 51 | 		t.Run(tc.desc, func(t *testing.T) {
 52 | 			got := struct {
 53 | 				Sources server.SourceConfigs `yaml:"sources"`
 54 | 			}{}
 55 | 			// Parse contents
 56 | 			err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got)
 57 | 			if err != nil {
 58 | 				t.Fatalf("unable to unmarshal: %s", err)
 59 | 			}
 60 | 			if !cmp.Equal(tc.want, got.Sources) {
 61 | 				t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources)
 62 | 			}
 63 | 		})
 64 | 	}
 65 | 
 66 | }
 67 | 
 68 | func TestFailParseFromYaml(t *testing.T) {
 69 | 	tcs := []struct {
 70 | 		desc string
 71 | 		in   string
 72 | 		err  string
 73 | 	}{
 74 | 		{
 75 | 			desc: "extra field",
 76 | 			in: `
 77 | 			sources:
 78 | 				my-instance:
 79 | 					kind: dataplex
 80 | 					project: my-project
 81 | 					foo: bar
 82 | 			`,
 83 | 			err: "unable to parse source \"my-instance\" as \"dataplex\": [1:1] unknown field \"foo\"\n>  1 | foo: bar\n       ^\n   2 | kind: dataplex\n   3 | project: my-project",
 84 | 		},
 85 | 		{
 86 | 			desc: "missing required field",
 87 | 			in: `
 88 | 			sources:
 89 | 				my-instance:
 90 | 					kind: dataplex
 91 | 			`,
 92 | 			err: "unable to parse source \"my-instance\" as \"dataplex\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag",
 93 | 		},
 94 | 	}
 95 | 	for _, tc := range tcs {
 96 | 		t.Run(tc.desc, func(t *testing.T) {
 97 | 			got := struct {
 98 | 				Sources server.SourceConfigs `yaml:"sources"`
 99 | 			}{}
100 | 			// Parse contents
101 | 			err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got)
102 | 			if err == nil {
103 | 				t.Fatalf("expect parsing to fail")
104 | 			}
105 | 			errStr := err.Error()
106 | 			if errStr != tc.err {
107 | 				t.Fatalf("unexpected error: got %q, want %q", errStr, tc.err)
108 | 			}
109 | 		})
110 | 	}
111 | }
112 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/clickhouse/clickhouse-sql.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "clickhouse-sql"
 3 | type: docs
 4 | weight: 2
 5 | description: >
 6 |   A "clickhouse-sql" tool executes SQL queries as prepared statements in ClickHouse.
 7 | aliases:
 8 | - /resources/tools/clickhouse-sql
 9 | ---
10 | 
11 | ## About
12 | 
13 | A `clickhouse-sql` tool executes SQL queries as prepared statements against a
14 | ClickHouse database. It's compatible with the
15 | [clickhouse](../../sources/clickhouse.md) source.
16 | 
17 | This tool supports both template parameters (for SQL statement customization) 
18 | and regular parameters (for prepared statement values), providing flexible 
19 | query execution capabilities.
20 | 
21 | ## Example
22 | 
23 | ```yaml
24 | tools:
25 |   my_analytics_query:
26 |     kind: clickhouse-sql
27 |     source: my-clickhouse-instance
28 |     description: Get user analytics for a specific date range
29 |     statement: |
30 |       SELECT 
31 |         user_id,
32 |         count(*) as event_count,
33 |         max(timestamp) as last_event
34 |       FROM events 
35 |       WHERE date >= ? AND date <= ?
36 |       GROUP BY user_id
37 |       ORDER BY event_count DESC
38 |       LIMIT ?
39 |     parameters:
40 |       - name: start_date
41 |         description: Start date for the query (YYYY-MM-DD format)
42 |       - name: end_date  
43 |         description: End date for the query (YYYY-MM-DD format)
44 |       - name: limit
45 |         description: Maximum number of results to return
46 | ```
47 | 
48 | ## Template Parameters Example
49 | 
50 | ```yaml
51 | tools:
52 |   flexible_table_query:
53 |     kind: clickhouse-sql
54 |     source: my-clickhouse-instance
55 |     description: Query any table with flexible columns
56 |     statement: |
57 |       SELECT {{columns}}
58 |       FROM {{table_name}}
59 |       WHERE created_date >= ?
60 |       LIMIT ?
61 |     templateParameters:
62 |       - name: columns
63 |         description: Comma-separated list of columns to select
64 |       - name: table_name
65 |         description: Name of the table to query
66 |     parameters:
67 |       - name: start_date
68 |         description: Start date filter
69 |       - name: limit
70 |         description: Maximum number of results
71 | ```
72 | 
73 | ## Reference
74 | 
75 | | **field**          |      **type**      | **required** | **description**                                       |
76 | |--------------------|:------------------:|:------------:|-------------------------------------------------------|
77 | | kind               |       string       |     true     | Must be "clickhouse-sql".                             |
78 | | source             |       string       |     true     | Name of the ClickHouse source to execute SQL against. |
79 | | description        |       string       |     true     | Description of the tool that is passed to the LLM.    |
80 | | statement          |       string       |     true     | The SQL statement template to execute.                |
81 | | parameters         | array of Parameter |    false     | Parameters for prepared statement values.             |
82 | | templateParameters | array of Parameter |    false     | Parameters for SQL statement template customization.  |
83 | 
```

--------------------------------------------------------------------------------
/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser_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 alloydbcreateuser_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/testutils"
24 | 	alloydbcreateuser "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydbcreateuser"
25 | )
26 | 
27 | func TestParseFromYaml(t *testing.T) {
28 | 	ctx, err := testutils.ContextWithNewLogger()
29 | 	if err != nil {
30 | 		t.Fatalf("unexpected error: %s", err)
31 | 	}
32 | 	tcs := []struct {
33 | 		desc string
34 | 		in   string
35 | 		want server.ToolConfigs
36 | 	}{
37 | 		{
38 | 			desc: "basic example",
39 | 			in: `
40 |             tools:
41 |                 create-my-user:
42 |                     kind: alloydb-create-user
43 |                     source: my-alloydb-admin-source
44 |                     description: some description
45 |             `,
46 | 			want: server.ToolConfigs{
47 | 				"create-my-user": alloydbcreateuser.Config{
48 | 					Name:         "create-my-user",
49 | 					Kind:         "alloydb-create-user",
50 | 					Source:       "my-alloydb-admin-source",
51 | 					Description:  "some description",
52 | 					AuthRequired: []string{},
53 | 				},
54 | 			},
55 | 		},
56 | 		{
57 | 			desc: "with auth required",
58 | 			in: `
59 |             tools:
60 |                 create-my-user-auth:
61 |                     kind: alloydb-create-user
62 |                     source: my-alloydb-admin-source
63 |                     description: some description
64 |                     authRequired: 
65 |                         - my-google-auth-service
66 |                         - other-auth-service
67 |             `,
68 | 			want: server.ToolConfigs{
69 | 				"create-my-user-auth": alloydbcreateuser.Config{
70 | 					Name:         "create-my-user-auth",
71 | 					Kind:         "alloydb-create-user",
72 | 					Source:       "my-alloydb-admin-source",
73 | 					Description:  "some description",
74 | 					AuthRequired: []string{"my-google-auth-service", "other-auth-service"},
75 | 				},
76 | 			},
77 | 		},
78 | 	}
79 | 	for _, tc := range tcs {
80 | 		t.Run(tc.desc, func(t *testing.T) {
81 | 			got := struct {
82 | 				Tools server.ToolConfigs `yaml:"tools"`
83 | 			}{}
84 | 			// Parse contents
85 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
86 | 			if err != nil {
87 | 				t.Fatalf("unable to unmarshal: %s", err)
88 | 			}
89 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
90 | 				t.Fatalf("incorrect parse: diff %v", diff)
91 | 			}
92 | 		})
93 | 	}
94 | }
95 | 
```

--------------------------------------------------------------------------------
/internal/tools/dgraph/dgraph_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 dgraph_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/testutils"
 24 | 	"github.com/googleapis/genai-toolbox/internal/tools/dgraph"
 25 | )
 26 | 
 27 | func TestParseFromYamlDgraph(t *testing.T) {
 28 | 	ctx, err := testutils.ContextWithNewLogger()
 29 | 	if err != nil {
 30 | 		t.Fatalf("unexpected error: %s", err)
 31 | 	}
 32 | 	tcs := []struct {
 33 | 		desc string
 34 | 		in   string
 35 | 		want server.ToolConfigs
 36 | 	}{
 37 | 		{
 38 | 			desc: "basic query example",
 39 | 			in: `
 40 | 			tools:
 41 | 				example_tool:
 42 | 					kind: dgraph-dql
 43 | 					source: my-dgraph-instance
 44 | 					description: some tool description
 45 | 					isQuery: true
 46 | 					timeout: 20s
 47 | 					statement: |
 48 | 						    query {q(func: eq(email, "[email protected]")) {email}}
 49 | 			`,
 50 | 			want: server.ToolConfigs{
 51 | 				"example_tool": dgraph.Config{
 52 | 					Name:         "example_tool",
 53 | 					Kind:         "dgraph-dql",
 54 | 					Source:       "my-dgraph-instance",
 55 | 					AuthRequired: []string{},
 56 | 					Description:  "some tool description",
 57 | 					IsQuery:      true,
 58 | 					Timeout:      "20s",
 59 | 					Statement:    "query {q(func: eq(email, \"[email protected]\")) {email}}\n",
 60 | 				},
 61 | 			},
 62 | 		},
 63 | 		{
 64 | 			desc: "basic mutation example",
 65 | 			in: `
 66 | 			tools:
 67 | 				example_tool:
 68 | 					kind: dgraph-dql
 69 | 					source: my-dgraph-instance
 70 | 					description: some tool description
 71 | 					statement: |
 72 | 					  mutation {set { _:a <name> "[email protected]" . _:b <email> "[email protected]" .}}
 73 | 			`,
 74 | 			want: server.ToolConfigs{
 75 | 				"example_tool": dgraph.Config{
 76 | 					Name:         "example_tool",
 77 | 					Kind:         "dgraph-dql",
 78 | 					Source:       "my-dgraph-instance",
 79 | 					Description:  "some tool description",
 80 | 					AuthRequired: []string{},
 81 | 					Statement:    "mutation {set { _:a <name> \"[email protected]\" . _:b <email> \"[email protected]\" .}}\n",
 82 | 				},
 83 | 			},
 84 | 		},
 85 | 	}
 86 | 	for _, tc := range tcs {
 87 | 		t.Run(tc.desc, func(t *testing.T) {
 88 | 			got := struct {
 89 | 				Tools server.ToolConfigs `yaml:"tools"`
 90 | 			}{}
 91 | 			// Parse contents
 92 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 93 | 			if err != nil {
 94 | 				t.Fatalf("unable to unmarshal: %s", err)
 95 | 			}
 96 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 97 | 				t.Fatalf("incorrect parse: diff %v", diff)
 98 | 			}
 99 | 		})
100 | 	}
101 | 
102 | }
103 | 
```

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

```markdown
 1 | ---
 2 | title: "Trino"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   Trino is a distributed SQL query engine for big data analytics.
 7 | ---
 8 | 
 9 | ## About
10 | 
11 | [Trino][trino-docs] is a distributed SQL query engine designed for fast analytic
12 | queries against data of any size. It allows you to query data where it lives,
13 | including Hive, Cassandra, relational databases or even proprietary data stores.
14 | 
15 | [trino-docs]: https://trino.io/docs/
16 | 
17 | ## Available Tools
18 | 
19 | - [`trino-sql`](../tools/trino/trino-sql.md)  
20 |   Execute parameterized SQL queries against Trino.
21 | 
22 | - [`trino-execute-sql`](../tools/trino/trino-execute-sql.md)  
23 |   Execute arbitrary SQL queries against Trino.
24 | 
25 | ## Requirements
26 | 
27 | ### Trino Cluster
28 | 
29 | You need access to a running Trino cluster with appropriate user permissions for
30 | the catalogs and schemas you want to query.
31 | 
32 | ## Example
33 | 
34 | ```yaml
35 | sources:
36 |     my-trino-source:
37 |     kind: trino
38 |     host: trino.example.com
39 |     port: "8080"
40 |     user: ${TRINO_USER}  # Optional for anonymous access
41 |     password: ${TRINO_PASSWORD}  # Optional
42 |     catalog: hive
43 |     schema: default
44 | ```
45 | 
46 | {{< notice tip >}}
47 | Use environment variable replacement with the format ${ENV_NAME}
48 | instead of hardcoding your secrets into the configuration file.
49 | {{< /notice >}}
50 | 
51 | ## Reference
52 | 
53 | | **field**       | **type** | **required** | **description**                                                              |
54 | |-----------------|:--------:|:------------:|------------------------------------------------------------------------------|
55 | | kind            |  string  |     true     | Must be "trino".                                                             |
56 | | host            |  string  |     true     | Trino coordinator hostname (e.g. "trino.example.com")                        |
57 | | port            |  string  |     true     | Trino coordinator port (e.g. "8080", "8443")                                 |
58 | | user            |  string  |    false     | Username for authentication (e.g. "analyst"). Optional for anonymous access. |
59 | | password        |  string  |    false     | Password for basic authentication                                            |
60 | | catalog         |  string  |     true     | Default catalog to use for queries (e.g. "hive")                             |
61 | | schema          |  string  |     true     | Default schema to use for queries (e.g. "default")                           |
62 | | queryTimeout    |  string  |    false     | Query timeout duration (e.g. "30m", "1h")                                    |
63 | | accessToken     |  string  |    false     | JWT access token for authentication                                          |
64 | | kerberosEnabled | boolean  |    false     | Enable Kerberos authentication (default: false)                              |
65 | | sslEnabled      | boolean  |    false     | Enable SSL/TLS (default: false)                                              |
66 | 
```

--------------------------------------------------------------------------------
/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster_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 alloydbcreatecluster_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/testutils"
24 | 	alloydbcreatecluster "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydbcreatecluster"
25 | )
26 | 
27 | func TestParseFromYaml(t *testing.T) {
28 | 	ctx, err := testutils.ContextWithNewLogger()
29 | 	if err != nil {
30 | 		t.Fatalf("unexpected error: %s", err)
31 | 	}
32 | 	tcs := []struct {
33 | 		desc string
34 | 		in   string
35 | 		want server.ToolConfigs
36 | 	}{
37 | 		{
38 | 			desc: "basic example",
39 | 			in: `
40 |             tools:
41 |                 create-my-cluster:
42 |                     kind: alloydb-create-cluster
43 |                     source: my-alloydb-admin-source
44 |                     description: some description
45 |             `,
46 | 			want: server.ToolConfigs{
47 | 				"create-my-cluster": alloydbcreatecluster.Config{
48 | 					Name:         "create-my-cluster",
49 | 					Kind:         "alloydb-create-cluster",
50 | 					Source:       "my-alloydb-admin-source",
51 | 					Description:  "some description",
52 | 					AuthRequired: []string{},
53 | 				},
54 | 			},
55 | 		},
56 | 		{
57 | 			desc: "with auth required",
58 | 			in: `
59 |             tools:
60 |                 create-my-cluster-auth:
61 |                     kind: alloydb-create-cluster
62 |                     source: my-alloydb-admin-source
63 |                     description: some description
64 |                     authRequired: 
65 |                         - my-google-auth-service
66 |                         - other-auth-service
67 |             `,
68 | 			want: server.ToolConfigs{
69 | 				"create-my-cluster-auth": alloydbcreatecluster.Config{
70 | 					Name:         "create-my-cluster-auth",
71 | 					Kind:         "alloydb-create-cluster",
72 | 					Source:       "my-alloydb-admin-source",
73 | 					Description:  "some description",
74 | 					AuthRequired: []string{"my-google-auth-service", "other-auth-service"},
75 | 				},
76 | 			},
77 | 		},
78 | 	}
79 | 	for _, tc := range tcs {
80 | 		t.Run(tc.desc, func(t *testing.T) {
81 | 			got := struct {
82 | 				Tools server.ToolConfigs `yaml:"tools"`
83 | 			}{}
84 | 			// Parse contents
85 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
86 | 			if err != nil {
87 | 				t.Fatalf("unable to unmarshal: %s", err)
88 | 			}
89 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
90 | 				t.Fatalf("incorrect parse: diff %v", diff)
91 | 			}
92 | 		})
93 | 	}
94 | }
95 | 
```

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

```markdown
  1 | ---
  2 | title: "Deploy using Docker Compose"
  3 | type: docs
  4 | weight: 4
  5 | description: >
  6 |   How to deploy Toolbox using Docker Compose.
  7 | ---
  8 | 
  9 | <!-- Contributor: Sujith R Pillai <[email protected]> -->
 10 | 
 11 | ## Before you begin
 12 | 
 13 | 1. [Install Docker Compose.](https://docs.docker.com/compose/install/)
 14 | 
 15 | ## Configure `tools.yaml` file
 16 | 
 17 | Create a `tools.yaml` file that contains your configuration for Toolbox. For
 18 | details, see the
 19 | [configuration](https://github.com/googleapis/genai-toolbox/blob/main/README.md#configuration)
 20 | section.
 21 | 
 22 | ## Deploy using Docker Compose
 23 | 
 24 | 1. Create a `docker-compose.yml` file, customizing as needed:
 25 | 
 26 | ```yaml
 27 | services:
 28 |   toolbox:
 29 |     # TODO: It is recommended to pin to a specific image version instead of latest.
 30 |     image:  us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest
 31 |     hostname: toolbox
 32 |     platform: linux/amd64
 33 |     ports:
 34 |       - "5000:5000"
 35 |     volumes:
 36 |       - ./config:/config
 37 |     command: [ "toolbox", "--tools-file", "/config/tools.yaml", "--address", "0.0.0.0"]
 38 |     depends_on:
 39 |       db:
 40 |         condition: service_healthy
 41 |     networks:
 42 |       - tool-network
 43 |   db:
 44 |     # TODO: It is recommended to pin to a specific image version instead of latest.
 45 |     image: postgres
 46 |     hostname: db
 47 |     environment:
 48 |       POSTGRES_USER: toolbox_user
 49 |       POSTGRES_PASSWORD: my-password
 50 |       POSTGRES_DB: toolbox_db
 51 |     ports:
 52 |       - "5432:5432"
 53 |     volumes:
 54 |       - ./db:/var/lib/postgresql/data
 55 |       # This file can be used to bootstrap your schema if needed.
 56 |       # See "initialization scripts" on https://hub.docker.com/_/postgres/ for more info
 57 |       - ./config/init.sql:/docker-entrypoint-initdb.d/init.sql
 58 |     healthcheck:
 59 |       test: ["CMD-SHELL", "pg_isready -U toolbox_user -d toolbox_db"]
 60 |       interval: 10s
 61 |       timeout: 5s
 62 |       retries: 5
 63 |     networks:
 64 |       - tool-network
 65 | networks:
 66 |   tool-network:
 67 | 
 68 | ```
 69 | 
 70 | 1. Run the following command to bring up the Toolbox and Postgres instance
 71 | 
 72 |     ```bash
 73 |     docker-compose up -d
 74 |     ```
 75 | 
 76 | {{< notice tip >}}
 77 | 
 78 | You can use this setup to quickly set up Toolbox + Postgres to follow along in our
 79 | [Quickstart](../getting-started/local_quickstart.md)
 80 | 
 81 | {{< /notice >}}
 82 | 
 83 | ## Connecting with Toolbox Client SDK
 84 | 
 85 | Next, we will use Toolbox with the Client SDKs:
 86 | 
 87 | 1. The url for the Toolbox server running using docker-compose will be:
 88 | 
 89 |     ```
 90 |     http://localhost:5000
 91 |     ```
 92 | 
 93 | 1. Import and initialize the client with the URL:
 94 | 
 95 |    {{< tabpane persist=header >}}
 96 | {{< tab header="LangChain" lang="Python" >}}
 97 | from toolbox_langchain import ToolboxClient
 98 | 
 99 | # Replace with the cloud run service URL generated above
100 | 
101 | async with ToolboxClient("http://$YOUR_URL") as toolbox:
102 | {{< /tab >}}
103 | {{< tab header="Llamaindex" lang="Python" >}}
104 | from toolbox_llamaindex import ToolboxClient
105 | 
106 | # Replace with the cloud run service URL generated above
107 | 
108 | async with ToolboxClient("http://$YOUR_URL") as toolbox:
109 | {{< /tab >}}
110 | {{< /tabpane >}}
111 | 
```

--------------------------------------------------------------------------------
/internal/sources/mongodb/mongodb_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 mongodb_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/mongodb"
 24 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
 25 | )
 26 | 
 27 | func TestParseFromYamlMongoDB(t *testing.T) {
 28 | 	tcs := []struct {
 29 | 		desc string
 30 | 		in   string
 31 | 		want server.SourceConfigs
 32 | 	}{
 33 | 		{
 34 | 			desc: "basic example",
 35 | 			in: `
 36 | 			sources:
 37 | 				mongo-db:
 38 | 					kind: "mongodb"
 39 | 					uri: "mongodb+srv://username:password@host/dbname"
 40 | 			`,
 41 | 			want: server.SourceConfigs{
 42 | 				"mongo-db": mongodb.Config{
 43 | 					Name: "mongo-db",
 44 | 					Kind: mongodb.SourceKind,
 45 | 					Uri:  "mongodb+srv://username:password@host/dbname",
 46 | 				},
 47 | 			},
 48 | 		},
 49 | 	}
 50 | 	for _, tc := range tcs {
 51 | 		t.Run(tc.desc, func(t *testing.T) {
 52 | 			got := struct {
 53 | 				Sources server.SourceConfigs `yaml:"sources"`
 54 | 			}{}
 55 | 			// Parse contents
 56 | 			err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got)
 57 | 			if err != nil {
 58 | 				t.Fatalf("unable to unmarshal: %s", err)
 59 | 			}
 60 | 			if !cmp.Equal(tc.want, got.Sources) {
 61 | 				t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources)
 62 | 			}
 63 | 		})
 64 | 	}
 65 | 
 66 | }
 67 | 
 68 | func TestFailParseFromYaml(t *testing.T) {
 69 | 	tcs := []struct {
 70 | 		desc string
 71 | 		in   string
 72 | 		err  string
 73 | 	}{
 74 | 		{
 75 | 			desc: "extra field",
 76 | 			in: `
 77 | 			sources:
 78 | 				mongo-db:
 79 | 					kind: mongodb
 80 | 					uri: "mongodb+srv://username:password@host/dbname"
 81 | 					foo: bar
 82 | 			`,
 83 | 			err: "unable to parse source \"mongo-db\" as \"mongodb\": [1:1] unknown field \"foo\"\n>  1 | foo: bar\n       ^\n   2 | kind: mongodb\n   3 | uri: mongodb+srv://username:password@host/dbname",
 84 | 		},
 85 | 		{
 86 | 			desc: "missing required field",
 87 | 			in: `
 88 | 			sources:
 89 | 				mongo-db:
 90 | 					kind: mongodb
 91 | 			`,
 92 | 			err: "unable to parse source \"mongo-db\" as \"mongodb\": Key: 'Config.Uri' Error:Field validation for 'Uri' failed on the 'required' tag",
 93 | 		},
 94 | 	}
 95 | 	for _, tc := range tcs {
 96 | 		t.Run(tc.desc, func(t *testing.T) {
 97 | 			got := struct {
 98 | 				Sources server.SourceConfigs `yaml:"sources"`
 99 | 			}{}
100 | 			// Parse contents
101 | 			err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got)
102 | 			if err == nil {
103 | 				t.Fatalf("expect parsing to fail")
104 | 			}
105 | 			errStr := err.Error()
106 | 			if errStr != tc.err {
107 | 				t.Fatalf("unexpected error: got \n%q, want \n%q", errStr, tc.err)
108 | 			}
109 | 		})
110 | 	}
111 | }
112 | 
```

--------------------------------------------------------------------------------
/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance_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 alloydbcreateinstance_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/testutils"
24 | 	alloydbcreateinstance "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydbcreateinstance"
25 | )
26 | 
27 | func TestParseFromYaml(t *testing.T) {
28 | 	ctx, err := testutils.ContextWithNewLogger()
29 | 	if err != nil {
30 | 		t.Fatalf("unexpected error: %s", err)
31 | 	}
32 | 	tcs := []struct {
33 | 		desc string
34 | 		in   string
35 | 		want server.ToolConfigs
36 | 	}{
37 | 		{
38 | 			desc: "basic example",
39 | 			in: `
40 |             tools:
41 |                 create-my-instance:
42 |                     kind: alloydb-create-instance
43 |                     source: my-alloydb-admin-source
44 |                     description: some description
45 |             `,
46 | 			want: server.ToolConfigs{
47 | 				"create-my-instance": alloydbcreateinstance.Config{
48 | 					Name:         "create-my-instance",
49 | 					Kind:         "alloydb-create-instance",
50 | 					Source:       "my-alloydb-admin-source",
51 | 					Description:  "some description",
52 | 					AuthRequired: []string{},
53 | 				},
54 | 			},
55 | 		},
56 | 		{
57 | 			desc: "with auth required",
58 | 			in: `
59 |             tools:
60 |                 create-my-instance-auth:
61 |                     kind: alloydb-create-instance
62 |                     source: my-alloydb-admin-source
63 |                     description: some description
64 |                     authRequired: 
65 |                         - my-google-auth-service
66 |                         - other-auth-service
67 |             `,
68 | 			want: server.ToolConfigs{
69 | 				"create-my-instance-auth": alloydbcreateinstance.Config{
70 | 					Name:         "create-my-instance-auth",
71 | 					Kind:         "alloydb-create-instance",
72 | 					Source:       "my-alloydb-admin-source",
73 | 					Description:  "some description",
74 | 					AuthRequired: []string{"my-google-auth-service", "other-auth-service"},
75 | 				},
76 | 			},
77 | 		},
78 | 	}
79 | 	for _, tc := range tcs {
80 | 		t.Run(tc.desc, func(t *testing.T) {
81 | 			got := struct {
82 | 				Tools server.ToolConfigs `yaml:"tools"`
83 | 			}{}
84 | 			// Parse contents
85 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
86 | 			if err != nil {
87 | 				t.Fatalf("unable to unmarshal: %s", err)
88 | 			}
89 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
90 | 				t.Fatalf("incorrect parse: diff %v", diff)
91 | 			}
92 | 		})
93 | 	}
94 | }
95 | 
```

--------------------------------------------------------------------------------
/internal/tools/clickhouse/clickhouselistdatabases/clickhouselistdatabases_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 clickhouse
 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/testutils"
 25 | 	"github.com/googleapis/genai-toolbox/internal/tools"
 26 | )
 27 | 
 28 | func TestListDatabasesConfigToolConfigKind(t *testing.T) {
 29 | 	cfg := Config{}
 30 | 	if cfg.ToolConfigKind() != listDatabasesKind {
 31 | 		t.Errorf("expected %q, got %q", listDatabasesKind, cfg.ToolConfigKind())
 32 | 	}
 33 | }
 34 | 
 35 | func TestListDatabasesConfigInitializeMissingSource(t *testing.T) {
 36 | 	cfg := Config{
 37 | 		Name:        "test-list-databases",
 38 | 		Kind:        listDatabasesKind,
 39 | 		Source:      "missing-source",
 40 | 		Description: "Test list databases tool",
 41 | 	}
 42 | 
 43 | 	srcs := map[string]sources.Source{}
 44 | 	_, err := cfg.Initialize(srcs)
 45 | 	if err == nil {
 46 | 		t.Error("expected error for missing source")
 47 | 	}
 48 | }
 49 | 
 50 | func TestParseFromYamlClickHouseListDatabases(t *testing.T) {
 51 | 	ctx, err := testutils.ContextWithNewLogger()
 52 | 	if err != nil {
 53 | 		t.Fatalf("unexpected error: %s", err)
 54 | 	}
 55 | 	tcs := []struct {
 56 | 		desc string
 57 | 		in   string
 58 | 		want server.ToolConfigs
 59 | 	}{
 60 | 		{
 61 | 			desc: "basic example",
 62 | 			in: `
 63 | 			tools:
 64 | 				example_tool:
 65 | 					kind: clickhouse-list-databases
 66 | 					source: my-instance
 67 | 					description: some description
 68 | 			`,
 69 | 			want: server.ToolConfigs{
 70 | 				"example_tool": Config{
 71 | 					Name:         "example_tool",
 72 | 					Kind:         "clickhouse-list-databases",
 73 | 					Source:       "my-instance",
 74 | 					Description:  "some description",
 75 | 					AuthRequired: []string{},
 76 | 				},
 77 | 			},
 78 | 		},
 79 | 	}
 80 | 	for _, tc := range tcs {
 81 | 		t.Run(tc.desc, func(t *testing.T) {
 82 | 			got := struct {
 83 | 				Tools server.ToolConfigs `yaml:"tools"`
 84 | 			}{}
 85 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
 86 | 			if err != nil {
 87 | 				t.Fatalf("unable to unmarshal: %s", err)
 88 | 			}
 89 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
 90 | 				t.Fatalf("incorrect parse: diff %v", diff)
 91 | 			}
 92 | 		})
 93 | 	}
 94 | }
 95 | 
 96 | func TestListDatabasesToolParseParams(t *testing.T) {
 97 | 	tool := Tool{
 98 | 		Parameters: tools.Parameters{},
 99 | 	}
100 | 
101 | 	params, err := tool.ParseParams(map[string]any{}, map[string]map[string]any{})
102 | 	if err != nil {
103 | 		t.Errorf("unexpected error: %v", err)
104 | 	}
105 | 
106 | 	if len(params) != 0 {
107 | 		t.Errorf("expected 0 parameters, got %d", len(params))
108 | 	}
109 | }
110 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/cloudsql/cloudsqlmysqlcreateinstance.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: cloud-sql-mysql-create-instance
 3 | type: docs
 4 | weight: 2
 5 | description: "Create a Cloud SQL for MySQL instance."
 6 | ---
 7 | 
 8 | The `cloud-sql-mysql-create-instance` tool creates a new Cloud SQL for MySQL
 9 | instance in a specified Google Cloud project.
10 | 
11 | {{< notice info >}}
12 | This tool uses the `cloud-sql-admin` source.
13 | {{< /notice >}}
14 | 
15 | ## Configuration
16 | 
17 | Here is an example of how to configure the `cloud-sql-mysql-create-instance`
18 | tool in your `tools.yaml` file:
19 | 
20 | ```yaml
21 | sources:
22 |   my-cloud-sql-admin-source:
23 |     kind: cloud-sql-admin
24 | 
25 | tools:
26 |   create_my_mysql_instance:
27 |     kind: cloud-sql-mysql-create-instance
28 |     source: my-cloud-sql-admin-source
29 |     description: "Creates a MySQL instance using `Production` and `Development` presets. For the `Development` template, it chooses a 2 vCPU, 16 GiB RAM, 100 GiB SSD configuration with Non-HA/zonal availability. For the `Production` template, it chooses an 8 vCPU, 64 GiB RAM, 250 GiB SSD configuration with HA/regional availability. The Enterprise Plus edition is used in both cases. The default database version is `MYSQL_8_4`. The agent should ask the user if they want to use a different version."
30 | ```
31 | 
32 | ## Parameters
33 | 
34 | The `cloud-sql-mysql-create-instance` tool has the following parameters:
35 | 
36 | | **field**       | **type** | **required** | **description**                                                                                                 |
37 | | --------------- | :------: | :----------: | --------------------------------------------------------------------------------------------------------------- |
38 | | project         |  string  |     true     | The Google Cloud project ID.                                                                                    |
39 | | name            |  string  |     true     | The name of the instance to create.                                                                             |
40 | | databaseVersion |  string  |     false    | The database version for MySQL. If not specified, defaults to the latest available version (e.g., `MYSQL_8_4`). |
41 | | rootPassword    |  string  |     true     | The root password for the instance.                                                                             |
42 | | editionPreset   |  string  |     false    | The edition of the instance. Can be `Production` or `Development`. Defaults to `Development`.                   |
43 | 
44 | ## Reference
45 | 
46 | | **field**   | **type** | **required** | **description**                                                |
47 | | ----------- | :------: | :----------: | -------------------------------------------------------------- |
48 | | kind        |  string  |     true     | Must be `cloud-sql-mysql-create-instance`.                     |
49 | | source      |  string  |     true     | The name of the `cloud-sql-admin` source to use for this tool. |
50 | | description |  string  |     false    | A description of the tool that is passed to the agent.         |
51 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/cloudsql/cloudsqlpgcreateinstances.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: cloud-sql-postgres-create-instance
 3 | type: docs
 4 | weight: 10
 5 | description: Create a Cloud SQL for PostgreSQL instance.
 6 | ---
 7 | 
 8 | The `cloud-sql-postgres-create-instance` tool creates a Cloud SQL for PostgreSQL
 9 | instance using the Cloud SQL Admin API.
10 | 
11 | {{< notice info >}}
12 | This tool uses a `source` of kind `cloud-sql-admin`.
13 | {{< /notice >}}
14 | 
15 | ## Example
16 | 
17 | ```yaml
18 | tools:
19 |   create-sql-instance:
20 |     kind: cloud-sql-postgres-create-instance
21 |     source: cloud-sql-admin-source
22 |     description: "Creates a Postgres instance using `Production` and `Development` presets. For the `Development` template, it chooses a 2 vCPU, 16 GiB RAM, 100 GiB SSD configuration with Non-HA/zonal availability. For the `Production` template, it chooses an 8 vCPU, 64 GiB RAM, 250 GiB SSD configuration with HA/regional availability. The Enterprise Plus edition is used in both cases. The default database version is `POSTGRES_17`. The agent should ask the user if they want to use a different version."
23 | ```
24 | 
25 | ## Reference
26 | 
27 | ### Tool Configuration
28 | 
29 | | **field**   | **type** | **required** | **description**                                  |
30 | | ----------- | :------: | :----------: | ------------------------------------------------ |
31 | | kind        |  string  |     true     | Must be "cloud-sql-postgres-create-instance".    |
32 | | source      |  string  |     true     | The name of the `cloud-sql-admin` source to use. |
33 | | description |  string  |     false    | A description of the tool.                       |
34 | 
35 | ### Tool Inputs
36 | 
37 | | **parameter**   | **type** | **required** | **description**                                                                                                                                          |
38 | |-----------------|:--------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------|
39 | | project         |  string  |     true     | The project ID.                                                                                                                                          |
40 | | name            |  string  |     true     | The name of the instance.                                                                                                                                |
41 | | databaseVersion |  string  |    false     | The database version for Postgres. If not specified, defaults to the latest available version (e.g., POSTGRES_17).                                       |
42 | | rootPassword    |  string  |     true     | The root password for the instance.                                                                                                                      |
43 | | editionPreset   |  string  |    false     | The edition of the instance. Can be `Production` or `Development`. This determines the default machine type and availability. Defaults to `Development`. |
44 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/mongodb/mongodb-delete-one.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "mongodb-delete-one"
 3 | type: docs
 4 | weight: 1
 5 | description: > 
 6 |   A "mongodb-delete-one" tool deletes a single document from a MongoDB collection.
 7 | aliases:
 8 | - /resources/tools/mongodb-delete-one
 9 | ---
10 | 
11 | ## About
12 | 
13 | The `mongodb-delete-one` tool performs a destructive operation, deleting the
14 | **first single document** that matches a specified filter from a MongoDB
15 | collection.
16 | 
17 | If the filter matches multiple documents, only the first one found by the
18 | database will be deleted. This tool is useful for removing specific entries,
19 | such as a user account or a single item from an inventory based on a unique ID.
20 | 
21 | The tool returns the number of documents deleted, which will be either `1` if a
22 | document was found and deleted, or `0` if no matching document was found.
23 | 
24 | This tool is compatible with the following source kind:
25 | 
26 | * [`mongodb`](../../sources/mongodb.md)
27 | 
28 | ---
29 | 
30 | ## Example
31 | 
32 | Here is an example that deletes a specific user account from the `users`
33 | collection by matching their unique email address. This is a permanent action.
34 | 
35 | ```yaml
36 | tools:
37 |   delete_user_account:
38 |     kind: mongodb-delete-one
39 |     source: my-mongo-source
40 |     description: Permanently deletes a user account by their email address.
41 |     database: user_data
42 |     collection: users
43 |     filterPayload: |
44 |         { "email": {{json .email_address}} }
45 |     filterParams:
46 |       - name: email_address
47 |         type: string
48 |         description: The email of the user account to delete.
49 | ```
50 | 
51 | ## Reference
52 | 
53 | | **field**     | **type** | **required** | **description**                                                                                                    |
54 | |:--------------|:---------|:-------------|:-------------------------------------------------------------------------------------------------------------------|
55 | | kind          | string   | true         | Must be `mongodb-delete-one`.                                                                                      |
56 | | source        | string   | true         | The name of the `mongodb` source to use.                                                                           |
57 | | description   | string   | true         | A description of the tool that is passed to the LLM.                                                               |
58 | | database      | string   | true         | The name of the MongoDB database containing the collection.                                                        |
59 | | collection    | string   | true         | The name of the MongoDB collection from which to delete a document.                                                |
60 | | filterPayload | string   | true         | The MongoDB query filter document to select the document for deletion. Uses `{{json .param_name}}` for templating. |
61 | | filterParams  | list     | true         | A list of parameter objects that define the variables used in the `filterPayload`.                                 |
62 | 
```

--------------------------------------------------------------------------------
/internal/sources/bigtable/bigtable.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
 16 | 
 17 | import (
 18 | 	"context"
 19 | 	"fmt"
 20 | 
 21 | 	"cloud.google.com/go/bigtable"
 22 | 	"github.com/goccy/go-yaml"
 23 | 	"github.com/googleapis/genai-toolbox/internal/sources"
 24 | 	"github.com/googleapis/genai-toolbox/internal/util"
 25 | 	"go.opentelemetry.io/otel/trace"
 26 | 	"google.golang.org/api/option"
 27 | )
 28 | 
 29 | const SourceKind string = "bigtable"
 30 | 
 31 | // validate interface
 32 | var _ sources.SourceConfig = Config{}
 33 | 
 34 | func init() {
 35 | 	if !sources.Register(SourceKind, newConfig) {
 36 | 		panic(fmt.Sprintf("source kind %q already registered", SourceKind))
 37 | 	}
 38 | }
 39 | 
 40 | func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources.SourceConfig, error) {
 41 | 	actual := Config{Name: name}
 42 | 	if err := decoder.DecodeContext(ctx, &actual); err != nil {
 43 | 		return nil, err
 44 | 	}
 45 | 	return actual, nil
 46 | }
 47 | 
 48 | type Config struct {
 49 | 	Name     string `yaml:"name" validate:"required"`
 50 | 	Kind     string `yaml:"kind" validate:"required"`
 51 | 	Project  string `yaml:"project" validate:"required"`
 52 | 	Instance string `yaml:"instance" 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 | 	client, err := initBigtableClient(ctx, tracer, r.Name, r.Project, r.Instance)
 61 | 	if err != nil {
 62 | 		return nil, fmt.Errorf("unable to create client: %w", err)
 63 | 	}
 64 | 
 65 | 	s := &Source{
 66 | 		Name:   r.Name,
 67 | 		Kind:   SourceKind,
 68 | 		Client: client,
 69 | 	}
 70 | 	return s, nil
 71 | }
 72 | 
 73 | var _ sources.Source = &Source{}
 74 | 
 75 | type Source struct {
 76 | 	Name   string `yaml:"name"`
 77 | 	Kind   string `yaml:"kind"`
 78 | 	Client *bigtable.Client
 79 | }
 80 | 
 81 | func (s *Source) SourceKind() string {
 82 | 	return SourceKind
 83 | }
 84 | 
 85 | func (s *Source) BigtableClient() *bigtable.Client {
 86 | 	return s.Client
 87 | }
 88 | 
 89 | func initBigtableClient(ctx context.Context, tracer trace.Tracer, name, project, instance string) (*bigtable.Client, error) {
 90 | 	//nolint:all // Reassigned ctx
 91 | 	ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name)
 92 | 	defer span.End()
 93 | 
 94 | 	// Set up Bigtable data operations client.
 95 | 	poolSize := 10
 96 | 	userAgent, err := util.UserAgentFromContext(ctx)
 97 | 	if err != nil {
 98 | 		return nil, err
 99 | 	}
100 | 
101 | 	client, err := bigtable.NewClient(ctx, project, instance, option.WithUserAgent(userAgent), option.WithGRPCConnectionPool(poolSize))
102 | 
103 | 	if err != nil {
104 | 		return nil, fmt.Errorf("unable to create bigtable.NewClient: %w", err)
105 | 	}
106 | 
107 | 	return client, nil
108 | }
109 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/cloudsql/cloudsqlmssqlcreateinstance.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: cloud-sql-mssql-create-instance
 3 | type: docs
 4 | weight: 10
 5 | description: "Create a Cloud SQL for SQL Server instance."
 6 | ---
 7 | 
 8 | The `cloud-sql-mssql-create-instance` tool creates a Cloud SQL for SQL Server
 9 | instance using the Cloud SQL Admin API.
10 | 
11 | {{< notice info dd>}}
12 | This tool uses a `source` of kind `cloud-sql-admin`.
13 | {{< /notice >}}
14 | 
15 | ## Example
16 | 
17 | ```yaml
18 | tools:
19 |   create-sql-instance:
20 |     kind: cloud-sql-mssql-create-instance
21 |     source: cloud-sql-admin-source
22 |     description: "Creates a SQL Server instance using `Production` and `Development` presets. For the `Development` template, it chooses a 2 vCPU, 8 GiB RAM (`db-custom-2-8192`) configuration with Non-HA/zonal availability. For the `Production` template, it chooses a 4 vCPU, 26 GiB RAM (`db-custom-4-26624`) configuration with HA/regional availability. The Enterprise edition is used in both cases. The default database version is `SQLSERVER_2022_STANDARD`. The agent should ask the user if they want to use a different version."
23 | ```
24 | 
25 | ## Reference
26 | 
27 | ### Tool Configuration
28 | 
29 | | **field**   | **type** | **required** | **description**                                  |
30 | | ----------- | :------: | :----------: | ------------------------------------------------ |
31 | | kind        |  string  |     true     | Must be "cloud-sql-mssql-create-instance".       |
32 | | source      |  string  |     true     | The name of the `cloud-sql-admin` source to use. |
33 | | description |  string  |    false     | A description of the tool.                       |
34 | 
35 | ### Tool Inputs
36 | 
37 | | **parameter**   | **type** | **required** | **description**                                                                                                                                          |
38 | |-----------------|:--------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------|
39 | | project         |  string  |     true     | The project ID.                                                                                                                                          |
40 | | name            |  string  |     true     | The name of the instance.                                                                                                                                |
41 | | databaseVersion |  string  |    false     | The database version for SQL Server. If not specified, defaults to the latest available version (e.g., SQLSERVER_2022_STANDARD).                         |
42 | | rootPassword    |  string  |     true     | The root password for the instance.                                                                                                                      |
43 | | editionPreset   |  string  |    false     | The edition of the instance. Can be `Production` or `Development`. This determines the default machine type and availability. Defaults to `Development`. |
44 | 
```

--------------------------------------------------------------------------------
/.ci/quickstart_test/run_py_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_python"
 20 | QUICKSTART_PYTHON_DIR="docs/en/getting-started/quickstart/python"
 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 |     python3-venv \
 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 |     set -e
 75 |     setup_orch_table
 76 |     cd "$orch_dir"
 77 |     local VENV_DIR=".venv"
 78 |     python3 -m venv "$VENV_DIR"
 79 |     source "$VENV_DIR/bin/activate"
 80 |     pip install -r requirements.txt
 81 |     echo "--- Running tests for $orch_name ---"
 82 |     cd ..
 83 |     ORCH_NAME="$orch_name" pytest
 84 |     rm -rf "$VENV_DIR"
 85 |   )
 86 | }
 87 | 
 88 | cleanup_all() {
 89 |   echo "--- Final cleanup: Shutting down processes and dropping table ---"
 90 |   if [ -n "$TOOLBOX_PID" ]; then
 91 |     kill $TOOLBOX_PID || true
 92 |   fi
 93 |   if [ -n "$PROXY_PID" ]; then
 94 |     kill $PROXY_PID || true
 95 |   fi
 96 | }
 97 | trap cleanup_all EXIT
 98 | 
 99 | # Main script execution
100 | install_system_packages
101 | start_cloud_sql_proxy
102 | 
103 | export PGHOST=127.0.0.1
104 | export PGPORT=5432
105 | export PGPASSWORD="$DB_PASSWORD"
106 | export GOOGLE_API_KEY="$GOOGLE_API_KEY"
107 | 
108 | setup_toolbox
109 | 
110 | for ORCH_DIR in "$QUICKSTART_PYTHON_DIR"/*/; do
111 |   if [ ! -d "$ORCH_DIR" ]; then
112 |     continue
113 |   fi
114 |   run_orch_test "$ORCH_DIR"
115 | done
116 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/bigquery/bigquery-conversational-analytics.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "bigquery-conversational-analytics"
 3 | type: docs
 4 | weight: 1
 5 | description: > 
 6 |   A "bigquery-conversational-analytics" tool allows conversational interaction with a BigQuery source.
 7 | aliases:
 8 | - /resources/tools/bigquery-conversational-analytics
 9 | ---
10 | 
11 | ## About
12 | 
13 | A `bigquery-conversational-analytics` tool allows you to ask questions about
14 | your data in natural language.
15 | 
16 | This function takes a user's question (which can include conversational history
17 | for context) and references to specific BigQuery tables, and sends them to a
18 | stateless conversational API.
19 | 
20 | The API uses a GenAI agent to understand the question, generate and execute SQL
21 | queries and Python code, and formulate an answer. This function returns a
22 | detailed, sequential log of this entire process, which includes any generated
23 | SQL or Python code, the data retrieved, and the final text answer.
24 | 
25 | **Note**: This tool requires additional setup in your project. Please refer to
26 | the official [Conversational Analytics API
27 | documentation](https://cloud.google.com/gemini/docs/conversational-analytics-api/overview)
28 | for instructions.
29 | 
30 | It's compatible with the following sources:
31 | 
32 | - [bigquery](../../sources/bigquery.md)
33 | 
34 | `bigquery-conversational-analytics` accepts the following parameters:
35 | 
36 | - **`user_query_with_context`:** The user's question, potentially including
37 |   conversation history and system instructions for context.
38 | - **`table_references`:** A JSON string of a list of BigQuery tables to use as
39 |   context. Each object in the list must contain `projectId`, `datasetId`, and
40 |   `tableId`. Example: `'[{"projectId": "my-gcp-project", "datasetId": "my_dataset", "tableId": "my_table"}]'`
41 | 
42 | The tool's behavior regarding these parameters is influenced by the `allowedDatasets` 
43 | restriction on the `bigquery` source:
44 | - **Without `allowedDatasets` restriction:** The tool can use tables from any 
45 | dataset specified in the `table_references` parameter.
46 | - **With `allowedDatasets` restriction:** Before processing the request, the tool 
47 | verifies that every table in `table_references` belongs to a dataset in the allowed 
48 | list. If any table is from a dataset that is not in the list, the request is denied.
49 | 
50 | ## Example
51 | 
52 | ```yaml
53 | tools:
54 |   ask_data_insights:
55 |     kind: bigquery-conversational-analytics
56 |     source: my-bigquery-source
57 |     description: |
58 |       Use this tool to perform data analysis, get insights, or answer complex 
59 |       questions about the contents of specific BigQuery tables.
60 | ```
61 | 
62 | ## Reference
63 | 
64 | | **field**   | **type** | **required** | **description**                                    |
65 | |-------------|:--------:|:------------:|----------------------------------------------------|
66 | | kind        |  string  |     true     | Must be "bigquery-conversational-analytics".       |
67 | | source      |  string  |     true     | Name of the source for chat.                       |
68 | | description |  string  |     true     | Description of the tool that is passed to the LLM. |
69 | 
```

--------------------------------------------------------------------------------
/internal/testutils/testutils.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 testutils
 16 | 
 17 | import (
 18 | 	"bufio"
 19 | 	"context"
 20 | 	"fmt"
 21 | 	"io"
 22 | 	"os"
 23 | 	"regexp"
 24 | 	"strings"
 25 | 
 26 | 	"github.com/googleapis/genai-toolbox/internal/log"
 27 | 	"github.com/googleapis/genai-toolbox/internal/util"
 28 | )
 29 | 
 30 | // formatYaml is a utility function for stripping out tabs in multiline strings
 31 | func FormatYaml(in string) []byte {
 32 | 	// removes any leading indentation(tabs)
 33 | 	in = strings.ReplaceAll(in, "\n\t", "\n ")
 34 | 	// converts remaining indentation
 35 | 	in = strings.ReplaceAll(in, "\t", "  ")
 36 | 	return []byte(in)
 37 | }
 38 | 
 39 | // ContextWithNewLogger create a new context with new logger
 40 | func ContextWithNewLogger() (context.Context, error) {
 41 | 	ctx := context.Background()
 42 | 	logger, err := log.NewStdLogger(os.Stdout, os.Stderr, "info")
 43 | 	if err != nil {
 44 | 		return nil, fmt.Errorf("unable to create logger: %s", err)
 45 | 	}
 46 | 	return util.WithLogger(ctx, logger), nil
 47 | }
 48 | 
 49 | // WaitForString waits until the server logs a single line that matches the provided regex.
 50 | // returns the output of whatever the server sent so far.
 51 | func WaitForString(ctx context.Context, re *regexp.Regexp, pr io.ReadCloser) (string, error) {
 52 | 	in := bufio.NewReader(pr)
 53 | 	ctx, cancel := context.WithCancel(ctx)
 54 | 	defer cancel()
 55 | 
 56 | 	// read lines in background, sending result of each read over a channel
 57 | 	// this allows us to use in.ReadString without blocking
 58 | 	type result struct {
 59 | 		s   string
 60 | 		err error
 61 | 	}
 62 | 	output := make(chan result)
 63 | 	go func() {
 64 | 		defer close(output)
 65 | 		for {
 66 | 			select {
 67 | 			case <-ctx.Done():
 68 | 				// if the context is canceled, the orig thread will send back the error
 69 | 				// so we can just exit the goroutine here
 70 | 				return
 71 | 			default:
 72 | 				// otherwise read a line from the output
 73 | 				s, err := in.ReadString('\n')
 74 | 				if err != nil {
 75 | 					output <- result{err: err}
 76 | 					return
 77 | 				}
 78 | 				output <- result{s: s}
 79 | 				// if that last string matched, exit the goroutine
 80 | 				if re.MatchString(s) {
 81 | 					return
 82 | 				}
 83 | 			}
 84 | 		}
 85 | 	}()
 86 | 
 87 | 	// collect the output until the ctx is canceled, an error was hit,
 88 | 	// or match was found (which is indicated the channel is closed)
 89 | 	var sb strings.Builder
 90 | 	for {
 91 | 		select {
 92 | 		case <-ctx.Done():
 93 | 			// if ctx is done, return that error
 94 | 			return sb.String(), ctx.Err()
 95 | 		case o, ok := <-output:
 96 | 			if !ok {
 97 | 				// match was found!
 98 | 				return sb.String(), nil
 99 | 			}
100 | 			if o.err != nil {
101 | 				// error was found!
102 | 				return sb.String(), o.err
103 | 			}
104 | 			sb.WriteString(o.s)
105 | 		}
106 | 	}
107 | }
108 | 
```

--------------------------------------------------------------------------------
/internal/sources/mongodb/mongodb.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 mongodb
 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/googleapis/genai-toolbox/internal/util"
 24 | 	"go.mongodb.org/mongo-driver/mongo"
 25 | 	"go.mongodb.org/mongo-driver/mongo/options"
 26 | 	"go.opentelemetry.io/otel/trace"
 27 | )
 28 | 
 29 | const SourceKind string = "mongodb"
 30 | 
 31 | // validate interface
 32 | var _ sources.SourceConfig = Config{}
 33 | 
 34 | func init() {
 35 | 	if !sources.Register(SourceKind, newConfig) {
 36 | 		panic(fmt.Sprintf("source kind %q already registered", SourceKind))
 37 | 	}
 38 | }
 39 | 
 40 | func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources.SourceConfig, error) {
 41 | 	actual := Config{Name: name}
 42 | 	if err := decoder.DecodeContext(ctx, &actual); err != nil {
 43 | 		return nil, err
 44 | 	}
 45 | 	return actual, nil
 46 | }
 47 | 
 48 | type Config struct {
 49 | 	Name string `yaml:"name" validate:"required"`
 50 | 	Kind string `yaml:"kind" validate:"required"`
 51 | 	Uri  string `yaml:"uri" validate:"required"` // MongoDB Atlas connection URI
 52 | }
 53 | 
 54 | func (r Config) SourceConfigKind() string {
 55 | 	return SourceKind
 56 | }
 57 | 
 58 | func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) {
 59 | 	client, err := initMongoDBClient(ctx, tracer, r.Name, r.Uri)
 60 | 	if err != nil {
 61 | 		return nil, fmt.Errorf("unable to create MongoDB client: %w", err)
 62 | 	}
 63 | 
 64 | 	// Verify the connection
 65 | 	err = client.Ping(ctx, nil)
 66 | 	if err != nil {
 67 | 		return nil, fmt.Errorf("unable to connect successfully: %w", err)
 68 | 	}
 69 | 
 70 | 	s := &Source{
 71 | 		Name:   r.Name,
 72 | 		Kind:   SourceKind,
 73 | 		Client: client,
 74 | 	}
 75 | 	return s, nil
 76 | }
 77 | 
 78 | var _ sources.Source = &Source{}
 79 | 
 80 | type Source struct {
 81 | 	Name   string `yaml:"name"`
 82 | 	Kind   string `yaml:"kind"`
 83 | 	Client *mongo.Client
 84 | }
 85 | 
 86 | func (s *Source) SourceKind() string {
 87 | 	return SourceKind
 88 | }
 89 | 
 90 | func (s *Source) MongoClient() *mongo.Client {
 91 | 	return s.Client
 92 | }
 93 | 
 94 | func initMongoDBClient(ctx context.Context, tracer trace.Tracer, name, uri string) (*mongo.Client, error) {
 95 | 	// Start a tracing span
 96 | 	ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name)
 97 | 	defer span.End()
 98 | 
 99 | 	userAgent, err := util.UserAgentFromContext(ctx)
100 | 	if err != nil {
101 | 		return nil, err
102 | 	}
103 | 
104 | 	// Create a new MongoDB client
105 | 	clientOpts := options.Client().ApplyURI(uri).SetAppName(userAgent)
106 | 	client, err := mongo.Connect(ctx, clientOpts)
107 | 	if err != nil {
108 | 		return nil, fmt.Errorf("unable to create MongoDB client: %w", err)
109 | 	}
110 | 
111 | 	return client, nil
112 | }
113 | 
```

--------------------------------------------------------------------------------
/internal/tools/tools_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 tools_test
16 | 
17 | import (
18 | 	"testing"
19 | 
20 | 	"github.com/google/go-cmp/cmp"
21 | 	"github.com/googleapis/genai-toolbox/internal/tools"
22 | )
23 | 
24 | func TestGetMcpManifestMetadata(t *testing.T) {
25 | 	authServices := []tools.ParamAuthService{
26 | 		{
27 | 			Name:  "my-google-auth-service",
28 | 			Field: "auth_field",
29 | 		},
30 | 		{
31 | 			Name:  "other-auth-service",
32 | 			Field: "other_auth_field",
33 | 		}}
34 | 	tcs := []struct {
35 | 		desc         string
36 | 		name         string
37 | 		description  string
38 | 		authInvoke   []string
39 | 		params       tools.Parameters
40 | 		wantMetadata map[string]any
41 | 	}{
42 | 		{
43 | 			desc:         "basic manifest without metadata",
44 | 			name:         "basic",
45 | 			description:  "foo bar",
46 | 			authInvoke:   []string{},
47 | 			params:       tools.Parameters{tools.NewStringParameter("string-param", "string parameter")},
48 | 			wantMetadata: nil,
49 | 		},
50 | 		{
51 | 			desc:         "with auth invoke metadata",
52 | 			name:         "basic",
53 | 			description:  "foo bar",
54 | 			authInvoke:   []string{"auth1", "auth2"},
55 | 			params:       tools.Parameters{tools.NewStringParameter("string-param", "string parameter")},
56 | 			wantMetadata: map[string]any{"toolbox/authInvoke": []string{"auth1", "auth2"}},
57 | 		},
58 | 		{
59 | 			desc:        "with auth param metadata",
60 | 			name:        "basic",
61 | 			description: "foo bar",
62 | 			authInvoke:  []string{},
63 | 			params:      tools.Parameters{tools.NewStringParameterWithAuth("string-param", "string parameter", authServices)},
64 | 			wantMetadata: map[string]any{
65 | 				"toolbox/authParam": map[string][]string{
66 | 					"string-param": []string{"my-google-auth-service", "other-auth-service"},
67 | 				},
68 | 			},
69 | 		},
70 | 		{
71 | 			desc:        "with auth invoke and auth param metadata",
72 | 			name:        "basic",
73 | 			description: "foo bar",
74 | 			authInvoke:  []string{"auth1", "auth2"},
75 | 			params:      tools.Parameters{tools.NewStringParameterWithAuth("string-param", "string parameter", authServices)},
76 | 			wantMetadata: map[string]any{
77 | 				"toolbox/authInvoke": []string{"auth1", "auth2"},
78 | 				"toolbox/authParam": map[string][]string{
79 | 					"string-param": []string{"my-google-auth-service", "other-auth-service"},
80 | 				},
81 | 			},
82 | 		},
83 | 	}
84 | 	for _, tc := range tcs {
85 | 		t.Run(tc.name, func(t *testing.T) {
86 | 			got := tools.GetMcpManifest(tc.name, tc.description, tc.authInvoke, tc.params)
87 | 			gotM := got.Metadata
88 | 			if diff := cmp.Diff(tc.wantMetadata, gotM); diff != "" {
89 | 				t.Fatalf("unexpected metadata (-want +got):\n%s", diff)
90 | 			}
91 | 		})
92 | 	}
93 | }
94 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookerhealthpulse/lookerhealthpulse_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 lookerhealthpulse_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 | 	lhp "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerhealthpulse"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerHealthPulse(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-health-pulse
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 			`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lhp.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-health-pulse",
 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 | func TestFailParseFromYamlLookerHealthPulse(t *testing.T) {
 76 | 	ctx, err := testutils.ContextWithNewLogger()
 77 | 	if err != nil {
 78 | 		t.Fatalf("unexpected error: %s", err)
 79 | 	}
 80 | 	tcs := []struct {
 81 | 		desc string
 82 | 		in   string
 83 | 		err  string
 84 | 	}{
 85 | 		{
 86 | 			desc: "Invalid field",
 87 | 			in: `
 88 | 			tools:
 89 | 				example_tool:
 90 | 					kind: looker-health-pulse
 91 | 					source: my-instance
 92 | 					invalid_field: true
 93 | 			`,
 94 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-health-pulse\": [2:1] unknown field \"invalid_field\"",
 95 | 		},
 96 | 	}
 97 | 	for _, tc := range tcs {
 98 | 		t.Run(tc.desc, func(t *testing.T) {
 99 | 			got := struct {
100 | 				Tools server.ToolConfigs `yaml:"tools"`
101 | 			}{}
102 | 			// Parse contents
103 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
104 | 			if err == nil {
105 | 				t.Fatalf("expect parsing to fail")
106 | 			}
107 | 			errStr := err.Error()
108 | 			if !strings.Contains(errStr, tc.err) {
109 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
110 | 			}
111 | 		})
112 | 	}
113 | }
114 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum_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 lookerhealthvacuum_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 | 	lhv "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerhealthvacuum"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerHealthVacuum(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-health-vacuum
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 			`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lhv.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-health-vacuum",
 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 | func TestFailParseFromYamlLookerHealthVacuum(t *testing.T) {
 76 | 	ctx, err := testutils.ContextWithNewLogger()
 77 | 	if err != nil {
 78 | 		t.Fatalf("unexpected error: %s", err)
 79 | 	}
 80 | 	tcs := []struct {
 81 | 		desc string
 82 | 		in   string
 83 | 		err  string
 84 | 	}{
 85 | 		{
 86 | 			desc: "Invalid field",
 87 | 			in: `
 88 | 			tools:
 89 | 				example_tool:
 90 | 					kind: looker-health-vacuum
 91 | 					source: my-instance
 92 | 					invalid_field: true
 93 | 			`,
 94 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-health-vacuum\": [2:1] unknown field \"invalid_field\"",
 95 | 		},
 96 | 	}
 97 | 	for _, tc := range tcs {
 98 | 		t.Run(tc.desc, func(t *testing.T) {
 99 | 			got := struct {
100 | 				Tools server.ToolConfigs `yaml:"tools"`
101 | 			}{}
102 | 			// Parse contents
103 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
104 | 			if err == nil {
105 | 				t.Fatalf("expect parsing to fail")
106 | 			}
107 | 			errStr := err.Error()
108 | 			if !strings.Contains(errStr, tc.err) {
109 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
110 | 			}
111 | 		})
112 | 	}
113 | }
114 | 
```

--------------------------------------------------------------------------------
/internal/tools/spanner/spannerlisttables/spannerlisttables_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 spannerlisttables_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/testutils"
 24 | 	"github.com/googleapis/genai-toolbox/internal/tools/spanner/spannerlisttables"
 25 | )
 26 | 
 27 | func TestParseFromYamlListTables(t *testing.T) {
 28 | 	ctx, err := testutils.ContextWithNewLogger()
 29 | 	if err != nil {
 30 | 		t.Fatalf("unexpected error: %s", err)
 31 | 	}
 32 | 	tcs := []struct {
 33 | 		desc string
 34 | 		in   string
 35 | 		want server.ToolConfigs
 36 | 	}{
 37 | 		{
 38 | 			desc: "basic example",
 39 | 			in: `
 40 | 			tools:
 41 | 				example_tool:
 42 | 					kind: spanner-list-tables
 43 | 					source: my-spanner-instance
 44 | 					description: Lists tables in the database
 45 | 			`,
 46 | 			want: server.ToolConfigs{
 47 | 				"example_tool": spannerlisttables.Config{
 48 | 					Name:         "example_tool",
 49 | 					Kind:         "spanner-list-tables",
 50 | 					Source:       "my-spanner-instance",
 51 | 					Description:  "Lists tables in the database",
 52 | 					AuthRequired: []string{},
 53 | 				},
 54 | 			},
 55 | 		},
 56 | 		{
 57 | 			desc: "with auth required",
 58 | 			in: `
 59 | 			tools:
 60 | 				example_tool:
 61 | 					kind: spanner-list-tables
 62 | 					source: my-spanner-instance
 63 | 					description: Lists tables in the database
 64 | 					authRequired:
 65 | 						- auth1
 66 | 						- auth2
 67 | 			`,
 68 | 			want: server.ToolConfigs{
 69 | 				"example_tool": spannerlisttables.Config{
 70 | 					Name:         "example_tool",
 71 | 					Kind:         "spanner-list-tables",
 72 | 					Source:       "my-spanner-instance",
 73 | 					Description:  "Lists tables in the database",
 74 | 					AuthRequired: []string{"auth1", "auth2"},
 75 | 				},
 76 | 			},
 77 | 		},
 78 | 		{
 79 | 			desc: "minimal config",
 80 | 			in: `
 81 | 			tools:
 82 | 				example_tool:
 83 | 					kind: spanner-list-tables
 84 | 					source: my-spanner-instance
 85 | 			`,
 86 | 			want: server.ToolConfigs{
 87 | 				"example_tool": spannerlisttables.Config{
 88 | 					Name:         "example_tool",
 89 | 					Kind:         "spanner-list-tables",
 90 | 					Source:       "my-spanner-instance",
 91 | 					Description:  "",
 92 | 					AuthRequired: []string{},
 93 | 				},
 94 | 			},
 95 | 		},
 96 | 	}
 97 | 	for _, tc := range tcs {
 98 | 		t.Run(tc.desc, func(t *testing.T) {
 99 | 			got := struct {
100 | 				Tools server.ToolConfigs `yaml:"tools"`
101 | 			}{}
102 | 			// Parse contents
103 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
104 | 			if err != nil {
105 | 				t.Fatalf("unable to unmarshal: %s", err)
106 | 			}
107 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
108 | 				t.Fatalf("incorrect parse: diff %v", diff)
109 | 			}
110 | 		})
111 | 	}
112 | }
113 | 
```

--------------------------------------------------------------------------------
/internal/tools/looker/lookerhealthanalyze/lookerhealthanalyze_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 lookerhealthanalyze_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 | 	lha "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerhealthanalyze"
 26 | )
 27 | 
 28 | func TestParseFromYamlLookerHealthAnalyze(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-health-analyze
 44 | 					source: my-instance
 45 | 					description: some description
 46 | 			`,
 47 | 			want: server.ToolConfigs{
 48 | 				"example_tool": lha.Config{
 49 | 					Name:         "example_tool",
 50 | 					Kind:         "looker-health-analyze",
 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 | func TestFailParseFromYamlLookerHealthAnalyze(t *testing.T) {
 76 | 	ctx, err := testutils.ContextWithNewLogger()
 77 | 	if err != nil {
 78 | 		t.Fatalf("unexpected error: %s", err)
 79 | 	}
 80 | 	tcs := []struct {
 81 | 		desc string
 82 | 		in   string
 83 | 		err  string
 84 | 	}{
 85 | 		{
 86 | 			desc: "Invalid field",
 87 | 			in: `
 88 | 			tools:
 89 | 				example_tool:
 90 | 					kind: looker-health-analyze
 91 | 					source: my-instance
 92 | 					invalid_field: true
 93 | 			`,
 94 | 			err: "unable to parse tool \"example_tool\" as kind \"looker-health-analyze\": [2:1] unknown field \"invalid_field\"",
 95 | 		},
 96 | 	}
 97 | 	for _, tc := range tcs {
 98 | 		t.Run(tc.desc, func(t *testing.T) {
 99 | 			got := struct {
100 | 				Tools server.ToolConfigs `yaml:"tools"`
101 | 			}{}
102 | 			// Parse contents
103 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
104 | 			if err == nil {
105 | 				t.Fatalf("expect parsing to fail")
106 | 			}
107 | 			errStr := err.Error()
108 | 			if !strings.Contains(errStr, tc.err) {
109 | 				t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
110 | 			}
111 | 		})
112 | 	}
113 | }
114 | 
```

--------------------------------------------------------------------------------
/.github/workflows/deploy_versioned_docs.yaml:
--------------------------------------------------------------------------------

```yaml
 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 | name: "Deploy Versioned Docs"
16 | 
17 | permissions:
18 |   contents: write
19 | 
20 | on:
21 |   release:
22 |     types: [published]
23 | 
24 | jobs:
25 |   deploy:
26 |     runs-on: ubuntu-24.04
27 |     # This shared concurrency group ensures only one docs deployment runs at a time.
28 |     concurrency:
29 |       group: docs-deployment
30 |       cancel-in-progress: false
31 |     steps:
32 |       - name: Checkout Code at Tag
33 |         uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
34 |         with:
35 |           ref: ${{ github.event.release.tag_name }}
36 | 
37 |       - name: Get Version from Release Tag
38 |         run: echo "VERSION=${{ github.event.release.tag_name }}" >> $GITHUB_ENV
39 | 
40 |       - name: Setup Hugo
41 |         uses: peaceiris/actions-hugo@75d2e84710de30f6ff7268e08f310b60ef14033f # v3
42 |         with:
43 |           hugo-version: "0.145.0"
44 |           extended: true
45 | 
46 |       - name: Setup Node
47 |         uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
48 |         with:
49 |           node-version: "22"
50 | 
51 |       - name: Install Dependencies
52 |         run: npm ci
53 |         working-directory: .hugo
54 | 
55 |       - name: Build Hugo Site
56 |         run: hugo --minify
57 |         working-directory: .hugo
58 |         env:
59 |           HUGO_BASEURL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/${{ env.VERSION }}/
60 |           HUGO_RELATIVEURLS: false
61 | 
62 |       - name: Deploy
63 |         uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4
64 |         with:
65 |           github_token: ${{ secrets.GITHUB_TOKEN }}
66 |           publish_dir: .hugo/public
67 |           publish_branch: versioned-gh-pages
68 |           destination_dir: ./${{ env.VERSION }}
69 |           keep_files: true
70 |           commit_message: "deploy: docs for ${{ env.VERSION }}"
71 | 
72 |       - name: Clean Build Directory
73 |         run: rm -rf .hugo/public
74 | 
75 |       - name: Build Hugo Site
76 |         run: hugo --minify
77 |         working-directory: .hugo
78 |         env:
79 |           HUGO_BASEURL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/
80 |           HUGO_RELATIVEURLS: false
81 | 
82 |       - name: Deploy to root
83 |         uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4
84 |         with:
85 |           github_token: ${{ secrets.GITHUB_TOKEN }}
86 |           publish_dir: .hugo/public
87 |           publish_branch: versioned-gh-pages
88 |           keep_files: true
89 |           allow_empty_commit: true
90 |           commit_message: "deploy: docs to root for ${{ env.VERSION }}"
91 | 
```
Page 5/45FirstPrevNextLast