#
tokens: 49710/50000 44/784 files (page 4/45)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 4 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
├── 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
├── 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/tools/redis/redis_test.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 redis_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"
25 | 	"github.com/googleapis/genai-toolbox/internal/tools/redis"
26 | )
27 | 
28 | func TestParseFromYamlRedis(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 | 				redis_tool:
43 | 					kind: redis
44 | 					source: my-redis-instance
45 | 					description: some description
46 | 					commands:
47 | 						- [SET, greeting, "hello, {{.name}}"]
48 | 						- [GET, id]
49 | 					parameters:
50 | 						- name: name
51 | 						  type: string
52 | 						  description: user name
53 | 			`,
54 | 			want: server.ToolConfigs{
55 | 				"redis_tool": redis.Config{
56 | 					Name:         "redis_tool",
57 | 					Kind:         "redis",
58 | 					Source:       "my-redis-instance",
59 | 					Description:  "some description",
60 | 					AuthRequired: []string{},
61 | 					Commands:     [][]string{{"SET", "greeting", "hello, {{.name}}"}, {"GET", "id"}},
62 | 					Parameters: []tools.Parameter{
63 | 						tools.NewStringParameter("name", "user name"),
64 | 					},
65 | 				},
66 | 			},
67 | 		},
68 | 	}
69 | 	for _, tc := range tcs {
70 | 		t.Run(tc.desc, func(t *testing.T) {
71 | 			got := struct {
72 | 				Tools server.ToolConfigs `yaml:"tools"`
73 | 			}{}
74 | 			// Parse contents
75 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
76 | 			if err != nil {
77 | 				t.Fatalf("unable to unmarshal: %s", err)
78 | 			}
79 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
80 | 				t.Fatalf("incorrect parse: diff %v", diff)
81 | 			}
82 | 		})
83 | 	}
84 | 
85 | }
86 | 
```

--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------

```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 | #     https://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: ✨ Feature Request
16 | description: Suggest an idea for new or improved behavior.
17 | title: "<brief summary of the proposed feature>"
18 | labels: ["type: feature request"]
19 | type: feature
20 | body:
21 |   - type: markdown
22 |     attributes:
23 |       value: |
24 |         Thanks for helping us improve! 🙏 Please answer these questions and provide as much information as possible about your feature request. 
25 |   
26 |   - id: preamble
27 |     type: checkboxes
28 |     attributes:
29 |       label: Prerequisites
30 |       description: |
31 |         Please run through the following list and make sure you've tried the usual "quick fixes":
32 |       options:
33 |         - label: "Search the [current open issues](https://github.com/googleapis/genai-toolbox/issues)"
34 |           required: true
35 | 
36 |   - type: textarea
37 |     id: use-case
38 |     attributes:
39 |       label: What are you trying to do that currently feels hard or impossible? 
40 |       description: "A clear and concise description of what the end goal for the feature should be -- avoid generalizing and try to provide a specific use-case."
41 |     validations:
42 |       required: true
43 | 
44 |   - type: textarea
45 |     id: suggested-solution
46 |     attributes:
47 |       label: Suggested Solution(s)
48 |       description: "If you have a suggestion for how this use-case can be solved, please feel free to include it."
49 | 
50 |   - type: textarea
51 |     id: alternatives-considered
52 |     attributes:
53 |       label: Alternatives Considered
54 |       description: "Are there any workaround or third party tools to replicate this behavior? Why would adding this feature be preferred over them?"
55 | 
56 |   - type: textarea
57 |     id: additional-details
58 |     attributes:
59 |       label: Additional Details
60 |       description: "Any additional information we should know? Please reference it here (issues, PRs, descriptions, or screenshots)"
61 | 
```

--------------------------------------------------------------------------------
/internal/tools/valkey/valkey_test.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 valkey_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"
25 | 	"github.com/googleapis/genai-toolbox/internal/tools/valkey"
26 | )
27 | 
28 | func TestParseFromYamlvalkey(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 | 				valkey_tool:
43 | 					kind: valkey
44 | 					source: my-valkey-instance
45 | 					description: some description
46 | 					commands:
47 | 						- [SET, greeting, "hello, {{.name}}"]
48 | 						- [GET, id]
49 | 					parameters:
50 | 						- name: name
51 | 						  type: string
52 | 						  description: user name
53 | 			`,
54 | 			want: server.ToolConfigs{
55 | 				"valkey_tool": valkey.Config{
56 | 					Name:         "valkey_tool",
57 | 					Kind:         "valkey",
58 | 					Source:       "my-valkey-instance",
59 | 					Description:  "some description",
60 | 					AuthRequired: []string{},
61 | 					Commands:     [][]string{{"SET", "greeting", "hello, {{.name}}"}, {"GET", "id"}},
62 | 					Parameters: []tools.Parameter{
63 | 						tools.NewStringParameter("name", "user name"),
64 | 					},
65 | 				},
66 | 			},
67 | 		},
68 | 	}
69 | 	for _, tc := range tcs {
70 | 		t.Run(tc.desc, func(t *testing.T) {
71 | 			got := struct {
72 | 				Tools server.ToolConfigs `yaml:"tools"`
73 | 			}{}
74 | 			// Parse contents
75 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
76 | 			if err != nil {
77 | 				t.Fatalf("unable to unmarshal: %s", err)
78 | 			}
79 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
80 | 				t.Fatalf("incorrect parse: diff %v", diff)
81 | 			}
82 | 		})
83 | 	}
84 | 
85 | }
86 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/looker/looker-get-looks.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "looker-get-looks"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   "looker-get-looks" searches for saved Looks in a Looker
 7 |   source.
 8 | aliases:
 9 | - /resources/tools/looker-get-looks
10 | ---
11 | 
12 | ## About
13 | 
14 | The `looker-get-looks` tool searches for a saved Look by
15 | name or description.
16 | 
17 | It's compatible with the following sources:
18 | 
19 | - [looker](../../sources/looker.md)
20 | 
21 | `looker-get-looks` takes four parameters, the `title`, `desc`, `limit`
22 | and `offset`.
23 | 
24 | Title and description use SQL style wildcards and are case insensitive.
25 | 
26 | Limit and offset are used to page through a larger set of matches and
27 | default to 100 and 0.
28 | 
29 | ## Example
30 | 
31 | ```yaml
32 | tools:
33 |     get_looks:
34 |         kind: looker-get-looks
35 |         source: looker-source
36 |         description: |
37 |           get_looks Tool
38 | 
39 |           This tool is used to search for saved looks in a Looker instance.
40 |           String search params use case-insensitive matching. String search
41 |           params can contain % and '_' as SQL LIKE pattern match wildcard
42 |           expressions. example="dan%" will match "danger" and "Danzig" but
43 |           not "David" example="D_m%" will match "Damage" and "dump".
44 | 
45 |           Most search params can accept "IS NULL" and "NOT NULL" as special
46 |           expressions to match or exclude (respectively) rows where the
47 |           column is null.
48 | 
49 |           The limit and offset are used to paginate the results.
50 | 
51 |           The result of the get_looks tool is a list of json objects.
52 | ```
53 | 
54 | ## Reference
55 | 
56 | | **field**   |                  **type**                  | **required** | **description**                                                                                  |
57 | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------|
58 | | kind        |                   string                   |     true     | Must be "looker-get-looks"                                                                       |
59 | | source      |                   string                   |     true     | Name of the source the SQL should execute on.                                                    |
60 | | description |                   string                   |     true     | Description of the tool that is passed to the LLM.                                               |
61 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/clickhouse/clickhouse-list-tables.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "clickhouse-list-tables"
 3 | type: docs
 4 | weight: 4
 5 | description: >
 6 |   A "clickhouse-list-tables" tool lists all tables in a specific ClickHouse database.
 7 | aliases:
 8 | - /resources/tools/clickhouse-list-tables
 9 | ---
10 | 
11 | ## About
12 | 
13 | A `clickhouse-list-tables` tool lists all available tables in a specified 
14 | ClickHouse database. It's compatible with the [clickhouse](../../sources/clickhouse.md) source.
15 | 
16 | This tool executes the `SHOW TABLES FROM <database>` command and returns a list 
17 | of all tables in the specified database that are accessible to the configured 
18 | user, making it useful for schema exploration and table discovery tasks.
19 | 
20 | ## Example
21 | 
22 | ```yaml
23 | tools:
24 |   list_clickhouse_tables:
25 |     kind: clickhouse-list-tables
26 |     source: my-clickhouse-instance
27 |     description: List all tables in a specific ClickHouse database
28 | ```
29 | 
30 | ## Parameters
31 | 
32 | | **parameter** | **type** | **required** | **description**                            |
33 | |---------------|:--------:|:------------:|---------------------------------------------|
34 | | database      | string   | true         | The database to list tables from.          |
35 | 
36 | ## Return Value
37 | 
38 | The tool returns an array of objects, where each object contains:
39 | - `name`: The name of the table
40 | - `database`: The database the table belongs to
41 | 
42 | Example response:
43 | ```json
44 | [
45 |   {"name": "users", "database": "analytics"},
46 |   {"name": "events", "database": "analytics"},
47 |   {"name": "products", "database": "analytics"},
48 |   {"name": "orders", "database": "analytics"}
49 | ]
50 | ```
51 | 
52 | ## Reference
53 | 
54 | | **field**          | **type**           | **required** | **description**                                           |
55 | |--------------------|:------------------:|:------------:|-----------------------------------------------------------|
56 | | kind               | string             | true         | Must be "clickhouse-list-tables".                        |
57 | | source             | string             | true         | Name of the ClickHouse source to list tables from.       |
58 | | description        | string             | true         | Description of the tool that is passed to the LLM.       |
59 | | authRequired       | array of string    | false        | Authentication services required to use this tool.       |
60 | | parameters         | array of Parameter | false        | Parameters for the tool (see Parameters section above).  |
61 | 
```

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

```markdown
 1 | ---
 2 | title: "mongodb-insert-one"
 3 | type: docs
 4 | weight: 1
 5 | description: > 
 6 |   A "mongodb-insert-one" tool inserts a single new document into a MongoDB collection.
 7 | aliases:
 8 | - /resources/tools/mongodb-insert-one
 9 | ---
10 | 
11 | ## About
12 | 
13 | The `mongodb-insert-one` tool inserts a **single new document** into a specified
14 | MongoDB collection.
15 | 
16 | This tool takes one required parameter named `data`, which must be a string
17 | containing the JSON object you want to insert. Upon successful insertion, the
18 | tool returns the unique `_id` of the newly created document.
19 | 
20 | This tool is compatible with the following source kind:
21 | 
22 | * [`mongodb`](../../sources/mongodb.md)
23 | 
24 | ## Example
25 | 
26 | Here is an example configuration for a tool that adds a new user to a `users`
27 | collection.
28 | 
29 | ```yaml
30 | tools:
31 |   create_new_user:
32 |     kind: mongodb-insert-one
33 |     source: my-mongo-source
34 |     description: Creates a new user record in the database.
35 |     database: user_data
36 |     collection: users
37 |     canonical: false
38 | ```
39 | 
40 | An LLM would call this tool by providing the document as a JSON string in the
41 | `data` parameter, like this:
42 | `tool_code: create_new_user(data='{"email": "[email protected]", "name": "Jane Doe", "status": "active"}')`
43 | 
44 | ## Reference
45 | 
46 | | **field**   | **type** | **required** | **description**                                                                                    |
47 | |:------------|:---------|:-------------|:---------------------------------------------------------------------------------------------------|
48 | | kind        | string   | true         | Must be `mongodb-insert-one`.                                                                      |
49 | | source      | string   | true         | The name of the `mongodb` source to use.                                                           |
50 | | description | string   | true         | A description of the tool that is passed to the LLM.                                               |
51 | | database    | string   | true         | The name of the MongoDB database containing the collection.                                        |
52 | | collection  | string   | true         | The name of the MongoDB collection into which the document will be inserted.                       |
53 | | canonical   | bool     | true         | Determines if the data string is parsed using MongoDB's Canonical or Relaxed Extended JSON format. |
54 | 
```

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

```markdown
 1 | ---
 2 | title: "Firebird"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   Firebird is a powerful, cross-platform, and open-source relational database.
 7 | 
 8 | ---
 9 | 
10 | ## About
11 | 
12 | [Firebird][fb-docs] is a relational database management system offering many
13 | ANSI SQL standard features that runs on Linux, Windows, and a variety of Unix
14 | platforms. It is known for its small footprint, powerful features, and easy
15 | maintenance.
16 | 
17 | [fb-docs]: https://firebirdsql.org/
18 | 
19 | ## Available Tools
20 | 
21 | - [`firebird-sql`](../tools/firebird/firebird-sql.md)  
22 |   Execute SQL queries as prepared statements in Firebird.
23 | 
24 | - [`firebird-execute-sql`](../tools/firebird/firebird-execute-sql.md)  
25 |   Run parameterized SQL statements in Firebird.
26 | 
27 | ## Requirements
28 | 
29 | ### Database User
30 | 
31 | This source uses standard authentication. You will need to [create a Firebird
32 | user][fb-users] to login to the database with.
33 | 
34 | [fb-users]: https://www.firebirdsql.org/refdocs/langrefupd25-security-sql-user-mgmt.html#langrefupd25-security-create-user
35 | 
36 | ## Example
37 | 
38 | ```yaml
39 | sources:
40 |     my_firebird_db:
41 |         kind: firebird
42 |         host: "localhost"
43 |         port: 3050
44 |         database: "/path/to/your/database.fdb"
45 |         user: ${FIREBIRD_USER}
46 |         password: ${FIREBIRD_PASS}
47 | ```
48 | 
49 | {{< notice tip >}}
50 | Use environment variable replacement with the format ${ENV_NAME}
51 | instead of hardcoding your secrets into the configuration file.
52 | {{< /notice >}}
53 | 
54 | ## Reference
55 | 
56 | | **field** | **type** | **required** | **description**                                                              |
57 | |-----------|:--------:|:------------:|------------------------------------------------------------------------------|
58 | | kind      |  string  |     true     | Must be "firebird".                                                          |
59 | | host      |  string  |     true     | IP address to connect to (e.g. "127.0.0.1")                                  |
60 | | port      |  string  |     true     | Port to connect to (e.g. "3050")                                             |
61 | | database  |  string  |     true     | Path to the Firebird database file (e.g. "/var/lib/firebird/data/test.fdb"). |
62 | | user      |  string  |     true     | Name of the Firebird user to connect as (e.g. "SYSDBA").                     |
63 | | password  |  string  |     true     | Password of the Firebird user (e.g. "masterkey").                            |
```

--------------------------------------------------------------------------------
/internal/tools/oceanbase/oceanbasesql/oceanbasesql_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 oceanbasesql_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"
25 | 	"github.com/googleapis/genai-toolbox/internal/tools/oceanbase/oceanbasesql"
26 | )
27 | 
28 | // Test parsing OceanBase SQL tool config from YAML.
29 | func TestParseFromYamlOceanBaseSql(t *testing.T) {
30 | 	ctx, err := testutils.ContextWithNewLogger()
31 | 	if err != nil {
32 | 		t.Fatalf("unexpected error: %s", err)
33 | 	}
34 | 	tcs := []struct {
35 | 		desc string
36 | 		in   string
37 | 		want server.ToolConfigs
38 | 	}{
39 | 		{
40 | 			desc: "basic example",
41 | 			in: `
42 | 			tools:
43 | 				example_tool:
44 | 					kind: oceanbase-sql
45 | 					source: my-instance
46 | 					description: some description
47 | 					statement: select * from t where id = ?
48 | 					parameters:
49 | 					  - name: id
50 | 					    type: string
51 | 					    description: id param
52 | 			`,
53 | 			want: server.ToolConfigs{
54 | 				"example_tool": oceanbasesql.Config{
55 | 					Name:         "example_tool",
56 | 					Kind:         "oceanbase-sql",
57 | 					Source:       "my-instance",
58 | 					Description:  "some description",
59 | 					Statement:    "select * from t where id = ?",
60 | 					AuthRequired: []string{},
61 | 					Parameters: []tools.Parameter{
62 | 						tools.NewStringParameter("id", "id param"),
63 | 					},
64 | 				},
65 | 			},
66 | 		},
67 | 	}
68 | 	for _, tc := range tcs {
69 | 		t.Run(tc.desc, func(t *testing.T) {
70 | 			got := struct {
71 | 				Tools server.ToolConfigs `yaml:"tools"`
72 | 			}{}
73 | 			// Parse contents
74 | 			err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
75 | 			if err != nil {
76 | 				t.Fatalf("unable to unmarshal: %s", err)
77 | 			}
78 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
79 | 				t.Fatalf("incorrect parse: diff %v", diff)
80 | 			}
81 | 		})
82 | 	}
83 | }
84 | 
```

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

```markdown
 1 | ---
 2 | title: "Go Quickstart (Local)"
 3 | type: docs
 4 | weight: 4
 5 | description: >
 6 |   How to get started running Toolbox locally with [Go](https://github.com/googleapis/mcp-toolbox-sdk-go), PostgreSQL, and orchestration frameworks such as [LangChain Go](https://tmc.github.io/langchaingo/docs/), [GenkitGo](https://genkit.dev/go/docs/get-started-go/), [Go GenAI](https://github.com/googleapis/go-genai) and [OpenAI Go](https://github.com/openai/openai-go).
 7 | ---
 8 | 
 9 | ## Before you begin
10 | 
11 | This guide assumes you have already done the following:
12 | 
13 | 1. Installed [Go (v1.24.2 or higher)].
14 | 1. Installed [PostgreSQL 16+ and the `psql` client][install-postgres].
15 | 
16 | [Go (v1.24.2 or higher)]: https://go.dev/doc/install
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. Initialize a go module:
37 | 
38 |     ```bash
39 |     go mod init main
40 |     ```
41 | 
42 | 1. In a new terminal, install the
43 |    [SDK](https://pkg.go.dev/github.com/googleapis/mcp-toolbox-sdk-go).
44 | 
45 |     ```bash
46 |     go get github.com/googleapis/mcp-toolbox-sdk-go
47 |     ```
48 | 
49 | 1. Create a new file named `hotelagent.go` and copy the following code to create
50 |    an agent:
51 | 
52 |     {{< tabpane persist=header >}}
53 | {{< tab header="LangChain Go" lang="go" >}}
54 | 
55 | {{< include "quickstart/go/langchain/quickstart.go" >}}
56 | 
57 | {{< /tab >}}
58 | 
59 | {{< tab header="Genkit Go" lang="go" >}}
60 | 
61 | {{< include "quickstart/go/genkit/quickstart.go" >}}
62 | 
63 | {{< /tab >}}
64 | 
65 | {{< tab header="Go GenAI" lang="go" >}}
66 | 
67 | {{< include "quickstart/go/genAI/quickstart.go" >}}
68 | 
69 | {{< /tab >}}
70 | 
71 | {{< tab header="OpenAI Go" lang="go" >}}
72 | 
73 | {{< include "quickstart/go/openAI/quickstart.go" >}}
74 | 
75 | {{< /tab >}}
76 | {{< /tabpane >}}
77 | 
78 | 1. Ensure all dependencies are installed:
79 | 
80 |     ```sh
81 |     go mod tidy
82 |     ```
83 | 
84 | 1. Run your agent, and observe the results:
85 | 
86 |     ```sh
87 |     go run hotelagent.go
88 |     ```
89 | 
90 | {{< notice info >}}
91 | For more information, visit the [Go SDK
92 | repo](https://github.com/googleapis/mcp-toolbox-sdk-go).
93 | {{</ notice >}}
94 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/bigquery/bigquery-get-table-info.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "bigquery-get-table-info"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   A "bigquery-get-table-info" tool retrieves metadata for a BigQuery table.
 7 | aliases:
 8 | - /resources/tools/bigquery-get-table-info
 9 | ---
10 | 
11 | ## About
12 | 
13 | A `bigquery-get-table-info` tool retrieves metadata for a BigQuery table.
14 | It's compatible with the following sources:
15 | 
16 | - [bigquery](../../sources/bigquery.md)
17 | 
18 | `bigquery-get-table-info` accepts the following parameters:
19 | - **`table`** (required): The name of the table for which to retrieve metadata.
20 | - **`dataset`** (required): The dataset containing the specified table.
21 | - **`project`** (optional): The Google Cloud project ID. If not provided, the
22 |   tool defaults to the project from the source configuration.
23 | 
24 | The tool's behavior regarding these parameters is influenced by the
25 | `allowedDatasets` restriction on the `bigquery` source:
26 | - **Without `allowedDatasets` restriction:** The tool can retrieve metadata for
27 |   any table specified by the `table`, `dataset`, and `project` parameters.
28 | - **With `allowedDatasets` restriction:** Before retrieving metadata, the tool
29 |   verifies that the requested dataset is in the allowed list. If it is not, the
30 |   request is denied. If only one dataset is specified in the `allowedDatasets`
31 |   list, it will be used as the default value for the `dataset` parameter.
32 | 
33 | ## Example
34 | 
35 | ```yaml
36 | tools:
37 |   bigquery_get_table_info:
38 |     kind: bigquery-get-table-info
39 |     source: my-bigquery-source
40 |     description: Use this tool to get table metadata.
41 | ```
42 | 
43 | ## Reference
44 | 
45 | | **field**   |                  **type**                  | **required** | **description**                                                                                  |
46 | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------|
47 | | kind        |                   string                   |     true     | Must be "bigquery-get-table-info".                                                               |
48 | | source      |                   string                   |     true     | Name of the source the SQL should execute on.                                                    |
49 | | description |                   string                   |     true     | Description of the tool that is passed to the LLM.                                               |
50 | 
```

--------------------------------------------------------------------------------
/docs/en/getting-started/quickstart/go/quickstart_test.go:
--------------------------------------------------------------------------------

```go
 1 | // Licensed under the Apache License, Version 2.0 (the "License");
 2 | // you may not use this file except in compliance with the License.
 3 | // You may obtain a copy of the License at
 4 | //
 5 | //	http://www.apache.org/licenses/LICENSE-2.0
 6 | //
 7 | // Unless required by applicable law or agreed to in writing, software
 8 | // distributed under the License is distributed on an "AS IS" BASIS,
 9 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | // See the License for the specific language governing permissions and
11 | // limitations under the License.
12 | package main
13 | 
14 | import (
15 | 	"bytes"
16 | 	"os"
17 | 	"os/exec"
18 | 	"path/filepath"
19 | 	"strings"
20 | 	"testing"
21 | )
22 | 
23 | func TestQuickstartSample(t *testing.T) {
24 | 	framework := os.Getenv("ORCH_NAME")
25 | 	if framework == "" {
26 | 		t.Skip("Skipping test: ORCH_NAME environment variable is not set.")
27 | 	}
28 | 
29 | 	t.Logf("--- Testing: %s ---", framework)
30 | 
31 | 	if framework == "openAI" {
32 | 		if os.Getenv("OPENAI_API_KEY") == "" {
33 | 			t.Skip("Skipping test: OPENAI_API_KEY environment variable is not set for openAI framework.")
34 | 		}
35 | 	} else {
36 | 		if os.Getenv("GOOGLE_API_KEY") == "" {
37 | 			t.Skipf("Skipping test for %s: GOOGLE_API_KEY environment variable is not set.", framework)
38 | 		}
39 | 	}
40 | 
41 | 	sampleDir := filepath.Join(".", framework)
42 | 	if _, err := os.Stat(sampleDir); os.IsNotExist(err) {
43 | 		t.Fatalf("Test setup failed: directory for framework '%s' not found.", framework)
44 | 	}
45 | 
46 | 	cmd := exec.Command("go", "run", ".")
47 | 	cmd.Dir = sampleDir
48 | 	var stdout, stderr bytes.Buffer
49 | 	cmd.Stdout = &stdout
50 | 	cmd.Stderr = &stderr
51 | 
52 | 	err := cmd.Run()
53 | 	actualOutput := stdout.String()
54 | 
55 | 	if err != nil {
56 | 		t.Fatalf("Script execution failed with error: %v\n--- STDERR ---\n%s", err, stderr.String())
57 | 	}
58 | 	if len(actualOutput) == 0 {
59 | 		t.Fatal("Script ran successfully but produced no output.")
60 | 	}
61 | 
62 | 	goldenFile, err := os.ReadFile("../golden.txt")
63 | 	if err != nil {
64 | 		t.Fatalf("Could not read golden.txt to check for keywords: %v", err)
65 | 	}
66 | 
67 | 	keywords := strings.Split(string(goldenFile), "\n")
68 | 	var missingKeywords []string
69 | 	outputLower := strings.ToLower(actualOutput)
70 | 
71 | 	for _, keyword := range keywords {
72 | 		kw := strings.TrimSpace(keyword)
73 | 		if kw != "" && !strings.Contains(outputLower, strings.ToLower(kw)) {
74 | 			missingKeywords = append(missingKeywords, kw)
75 | 		}
76 | 	}
77 | 
78 | 	if len(missingKeywords) > 0 {
79 | 		t.Fatalf("FAIL: The following keywords were missing from the output: [%s]", strings.Join(missingKeywords, ", "))
80 | 	}
81 | }
82 | 
```

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

```markdown
 1 | ---
 2 | title: "Configuration"
 3 | type: docs
 4 | weight: 6
 5 | description: >
 6 |   How to configure Toolbox's tools.yaml file.
 7 | ---
 8 | 
 9 | The primary way to configure Toolbox is through the `tools.yaml` file. If you
10 | have multiple files, you can tell toolbox which to load with the `--tools-file
11 | tools.yaml` flag.
12 | 
13 | You can find more detailed reference documentation to all resource types in the
14 | [Resources](../resources/).
15 | 
16 | ### Using Environment Variables
17 | 
18 | To avoid hardcoding certain secret fields like passwords, usernames, API keys
19 | etc., you could use environment variables instead with the format `${ENV_NAME}`.
20 | 
21 | ```yaml
22 |   user: ${USER_NAME}
23 |   password: ${PASSWORD}
24 | ```
25 | 
26 | A default value can be specified like `${ENV_NAME:default}`.
27 | 
28 | ```yaml
29 |   port: ${DB_PORT:3306}
30 | ```
31 | 
32 | ### Sources
33 | 
34 | The `sources` section of your `tools.yaml` defines what data sources your
35 | Toolbox should have access to. Most tools will have at least one source to
36 | execute against.
37 | 
38 | ```yaml
39 | sources:
40 |   my-pg-source:
41 |     kind: postgres
42 |     host: 127.0.0.1
43 |     port: 5432
44 |     database: toolbox_db
45 |     user: ${USER_NAME}
46 |     password: ${PASSWORD}
47 | ```
48 | 
49 | For more details on configuring different types of sources, see the
50 | [Sources](../resources/sources/).
51 | 
52 | ### Tools
53 | 
54 | The `tools` section of your `tools.yaml` defines the actions your agent can
55 | take: what kind of tool it is, which source(s) it affects, what parameters it
56 | uses, etc.
57 | 
58 | ```yaml
59 | tools:
60 |   search-hotels-by-name:
61 |     kind: postgres-sql
62 |     source: my-pg-source
63 |     description: Search for hotels based on name.
64 |     parameters:
65 |       - name: name
66 |         type: string
67 |         description: The name of the hotel.
68 |     statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%';
69 | ```
70 | 
71 | For more details on configuring different types of tools, see the
72 | [Tools](../resources/tools/).
73 | 
74 | ### Toolsets
75 | 
76 | The `toolsets` section of your `tools.yaml` allows you to define groups of tools
77 | that you want to be able to load together. This can be useful for defining
78 | different sets for different agents or different applications.
79 | 
80 | ```yaml
81 | toolsets:
82 |   my_first_toolset:
83 |     - my_first_tool
84 |     - my_second_tool
85 |   my_second_toolset:
86 |     - my_second_tool
87 |     - my_third_tool
88 | ```
89 | 
90 | You can load toolsets by name:
91 | 
92 | ```python
93 | # This will load all tools
94 | all_tools = client.load_toolset()
95 | 
96 | # This will only load the tools listed in 'my_second_toolset'
97 | my_second_toolset = client.load_toolset("my_second_toolset")
98 | ```
99 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/looker/looker-get-dashboards.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "looker-get-dashboards"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   "looker-get-dashboards" tool searches for a saved Dashboard by name or description.
 7 | aliases:
 8 | - /resources/tools/looker-get-dashboards
 9 | ---
10 | 
11 | ## About
12 | 
13 | The `looker-get-dashboards` tool searches for a saved Dashboard by
14 | name or description.
15 | 
16 | It's compatible with the following sources:
17 | 
18 | - [looker](../../sources/looker.md)
19 | 
20 | `looker-get-dashboards` takes four parameters, the `title`, `desc`, `limit`
21 | and `offset`.
22 | 
23 | Title and description use SQL style wildcards and are case insensitive.
24 | 
25 | Limit and offset are used to page through a larger set of matches and
26 | default to 100 and 0.
27 | 
28 | ## Example
29 | 
30 | ```yaml
31 | tools:
32 |     get_dashboards:
33 |         kind: looker-get-dashboards
34 |         source: looker-source
35 |         description: |
36 |           get_dashboards Tool
37 | 
38 |           This tool is used to search for saved dashboards in a Looker instance.
39 |           String search params use case-insensitive matching. String search
40 |           params can contain % and '_' as SQL LIKE pattern match wildcard
41 |           expressions. example="dan%" will match "danger" and "Danzig" but
42 |           not "David" example="D_m%" will match "Damage" and "dump".
43 | 
44 |           Most search params can accept "IS NULL" and "NOT NULL" as special
45 |           expressions to match or exclude (respectively) rows where the
46 |           column is null.
47 | 
48 |           The limit and offset are used to paginate the results.
49 | 
50 |           The result of the get_dashboards tool is a list of json objects.
51 | ```
52 | 
53 | ## Reference
54 | 
55 | | **field**   |                  **type**                  | **required** | **description**                                                                                  |
56 | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------|
57 | | kind        |                   string                   |     true     | Must be "looker-get-dashboards"                                                                  |
58 | | source      |                   string                   |     true     | Name of the source the SQL should execute on.                                                    |
59 | | description |                   string                   |     true     | Description of the tool that is passed to the LLM.                                               |
60 | 
```

--------------------------------------------------------------------------------
/internal/prebuiltconfigs/tools/bigquery.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 | sources:
16 |   bigquery-source:
17 |     kind: "bigquery"
18 |     project: ${BIGQUERY_PROJECT}
19 |     location: ${BIGQUERY_LOCATION:}
20 |     useClientOAuth: ${BIGQUERY_USE_CLIENT_OAUTH:false}
21 | 
22 | tools:
23 |   analyze_contribution:
24 |     kind: bigquery-analyze-contribution
25 |     source: bigquery-source
26 |     description: Use this tool to analyze the contribution about changes to key metrics in multi-dimensional data.
27 | 
28 |   ask_data_insights:
29 |     kind: bigquery-conversational-analytics
30 |     source: bigquery-source
31 |     description: |
32 |       Use this tool to perform data analysis, get insights,
33 |       or answer complex questions about the contents of specific
34 |       BigQuery tables.
35 | 
36 |   execute_sql:
37 |     kind: bigquery-execute-sql
38 |     source: bigquery-source
39 |     description: Use this tool to execute sql statement.
40 | 
41 |   forecast:
42 |     kind: bigquery-forecast
43 |     source: bigquery-source
44 |     description: Use this tool to forecast time series data.
45 | 
46 |   get_dataset_info:
47 |     kind: bigquery-get-dataset-info
48 |     source: bigquery-source
49 |     description: Use this tool to get dataset metadata.
50 | 
51 |   get_table_info:
52 |     kind: bigquery-get-table-info
53 |     source: bigquery-source
54 |     description: Use this tool to get table metadata.
55 | 
56 |   list_dataset_ids:
57 |     kind: bigquery-list-dataset-ids
58 |     source: bigquery-source
59 |     description: Use this tool to list datasets.
60 | 
61 |   list_table_ids:
62 |     kind: bigquery-list-table-ids
63 |     source: bigquery-source
64 |     description: Use this tool to list tables.
65 | 
66 |   search_catalog:
67 |     kind: bigquery-search-catalog
68 |     source: bigquery-source
69 |     description: Use this tool to find tables, views, models, routines or connections.
70 | 
71 | toolsets:
72 |   bigquery_database_tools:
73 |     - analyze_contribution
74 |     - ask_data_insights
75 |     - execute_sql
76 |     - forecast
77 |     - get_dataset_info
78 |     - get_table_info
79 |     - list_dataset_ids
80 |     - list_table_ids
81 |     - search_catalog
82 | 
```

--------------------------------------------------------------------------------
/.github/workflows/docs_deploy.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: "docs"
16 | 
17 | permissions:
18 |   contents: write
19 | 
20 | on:
21 |   push:
22 |     branches:
23 |       - main
24 |     paths:
25 |       - 'docs/**'
26 |       - 'github/workflows/docs**'
27 |       - '.hugo/**'
28 | 
29 |   # Allow triggering manually.
30 |   workflow_dispatch:
31 | 
32 | jobs:
33 |   deploy:
34 |     runs-on: ubuntu-24.04
35 |     defaults:
36 |       run:
37 |         working-directory: .hugo
38 |     concurrency:
39 |       group: ${{ github.workflow }}-${{ github.ref }}
40 |       cancel-in-progress: true
41 |     steps:
42 |       - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
43 |         with:
44 |           fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
45 | 
46 |       - name: Setup Hugo
47 |         uses: peaceiris/actions-hugo@75d2e84710de30f6ff7268e08f310b60ef14033f # v3
48 |         with:
49 |           hugo-version: "0.145.0"
50 |           extended: true
51 | 
52 |       - name: Setup Node
53 |         uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
54 |         with:
55 |           node-version: "22"
56 | 
57 |       - name: Cache dependencies
58 |         uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
59 |         with:
60 |           path: ~/.npm
61 |           key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
62 |           restore-keys: |
63 |             ${{ runner.os }}-node-
64 | 
65 |       - run: npm ci
66 |       - run: hugo --minify
67 |         env:
68 |           HUGO_BASEURL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/
69 |           HUGO_RELATIVEURLS: false
70 | 
71 |       - name: Deploy
72 |         uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4
73 |         with:
74 |           github_token: ${{ secrets.GITHUB_TOKEN }}
75 |           publish_dir: .hugo/public
76 |           # Do not delete previews on each production deploy.
77 |           # CSS or JS changes will require manual clean-up.
78 |           keep_files: true
79 |           commit_message: "deploy: ${{ github.event.head_commit.message }}"
80 | 
```

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

```markdown
 1 | ---
 2 | title: "SQLite"
 3 | linkTitle: "SQLite"
 4 | type: docs
 5 | weight: 1
 6 | description: >
 7 |   SQLite is a C-language library that implements a small, fast, self-contained, 
 8 |   high-reliability, full-featured, SQL database engine.
 9 | ---
10 | 
11 | ## About
12 | 
13 | [SQLite](https://sqlite.org/) is a software library that provides a relational
14 | database management system. The lite in SQLite means lightweight in terms of
15 | setup, database administration, and required resources.
16 | 
17 | SQLite has the following notable characteristics:
18 | 
19 | - Self-contained with no external dependencies
20 | - Serverless - the SQLite library accesses its storage files directly
21 | - Single database file that can be easily copied or moved
22 | - Zero-configuration - no setup or administration needed
23 | - Transactional with ACID properties
24 | 
25 | ## Available Tools
26 | 
27 | - [`sqlite-sql`](../tools/sqlite/sqlite-sql.md)  
28 |   Run SQL queries against a local SQLite database.
29 |   
30 | - [`sqlite-execute-sql`](../tools/sqlite/sqlite-execute-sql.md)  
31 |   Run parameterized SQL statements in SQlite.
32 | 
33 | ### Pre-built Configurations
34 | 
35 | - [SQLite using MCP](../../how-to/connect-ide/sqlite_mcp.md)  
36 | Connect your IDE to SQlite using Toolbox.
37 | 
38 | ## Requirements
39 | 
40 | ### Database File
41 | 
42 | You need a SQLite database file. This can be:
43 | 
44 | - An existing database file
45 | - A path where a new database file should be created
46 | - `:memory:` for an in-memory database
47 | 
48 | ## Example
49 | 
50 | ```yaml
51 | sources:
52 |     my-sqlite-db:
53 |         kind: "sqlite"
54 |         database: "/path/to/database.db"
55 | ```
56 | 
57 | For an in-memory database:
58 | 
59 | ```yaml
60 | sources:
61 |     my-sqlite-memory-db:
62 |         kind: "sqlite"
63 |         database: ":memory:"
64 | ```
65 | 
66 | ## Reference
67 | 
68 | ### Configuration Fields
69 | 
70 | | **field** | **type** | **required** | **description**                                                                                                     |
71 | |-----------|:--------:|:------------:|---------------------------------------------------------------------------------------------------------------------|
72 | | kind      |  string  |     true     | Must be "sqlite".                                                                                                   |
73 | | database  |  string  |     true     | Path to SQLite database file, or ":memory:" for an in-memory database.                                              |
74 | 
75 | ### Connection Properties
76 | 
77 | SQLite connections are configured with these defaults for optimal performance:
78 | 
79 | - `MaxOpenConns`: 1 (SQLite only supports one writer at a time)
80 | - `MaxIdleConns`: 1
81 | 
```

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

```javascript
 1 | import { gemini, GEMINI_MODEL } from "@llamaindex/google";
 2 | import { agent } from "@llamaindex/workflow";
 3 | import { createMemory, staticBlock, tool } from "llamaindex";
 4 | import { ToolboxClient } from "@toolbox-sdk/core";
 5 | 
 6 | const TOOLBOX_URL = "http://127.0.0.1:5000"; // Update if needed
 7 | const GOOGLE_API_KEY = process.env.GOOGLE_API_KEY || 'your-api-key'; // Replace it with your API key
 8 | 
 9 | const prompt = `
10 | 
11 | You're a helpful hotel assistant. You handle hotel searching, booking and cancellations.
12 | When the user searches for a hotel, mention its name, id, location and price tier.
13 | Always mention hotel ids while performing any searches — this is very important for operations.
14 | For any bookings or cancellations, please provide the appropriate confirmation.
15 | Update check-in or check-out dates if mentioned by the user.
16 | Don't ask for confirmations from the user.
17 | 
18 | `;
19 | 
20 | const queries = [
21 |   "Find hotels in Basel with Basel in its name.",
22 |   "Can you book the Hilton Basel for me?",
23 |   "Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
24 |   "My check in dates would be from April 10, 2024 to April 19, 2024.",
25 | ];
26 | 
27 | export async function main() {
28 |   // Connect to MCP Toolbox
29 |   const client = new ToolboxClient(TOOLBOX_URL);
30 |   const toolboxTools = await client.loadToolset("my-toolset");
31 |   const tools = toolboxTools.map((toolboxTool) => {
32 |     return tool({
33 |       name: toolboxTool.getName(),
34 |       description: toolboxTool.getDescription(),
35 |       parameters: toolboxTool.getParamSchema(),
36 |       execute: toolboxTool,
37 |     });
38 |   });
39 | 
40 |   // Initialize LLM
41 |   const llm = gemini({
42 |     model: GEMINI_MODEL.GEMINI_2_0_FLASH,
43 |     apiKey: GOOGLE_API_KEY,
44 |   });
45 | 
46 |   const memory = createMemory({
47 |     memoryBlocks: [
48 |       staticBlock({
49 |         content: prompt,
50 |       }),
51 |     ],
52 |   });
53 | 
54 |   // Create the Agent
55 |   const myAgent = agent({
56 |     tools: tools,
57 |     llm,
58 |     memory,
59 |     systemPrompt: prompt,
60 |   });
61 | 
62 |   for (const query of queries) {
63 |     const result = await myAgent.run(query);
64 |     const output = result.data.result;
65 | 
66 |     console.log(`\nUser: ${query}`);
67 |     if (typeof output === "string") {
68 |       console.log(output.trim());
69 |     } else if (typeof output === "object" && "text" in output) {
70 |       console.log(output.text.trim());
71 |     } else {
72 |       console.log(JSON.stringify(output));
73 |     }
74 |   }
75 |   //You may observe some extra logs during execution due to the run method provided by Llama.
76 |   console.log("Agent run finished.");
77 | }
78 | 
79 | main();
```

--------------------------------------------------------------------------------
/internal/tools/neo4j/neo4jcypher/neo4jcypher_test.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 neo4jcypher
16 | 
17 | import (
18 | 	"testing"
19 | 
20 | 	"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"
25 | )
26 | 
27 | func TestParseFromYamlNeo4j(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: neo4j-cypher
43 | 					source: my-neo4j-instance
44 | 					description: some tool description
45 | 					authRequired:
46 | 						- my-google-auth-service
47 | 						- other-auth-service
48 | 					statement: |
49 | 						MATCH (c:Country) WHERE c.name = $country RETURN c.id as id;
50 | 					parameters:
51 | 						- name: country
52 | 						  type: string
53 | 						  description: country parameter description
54 | 			`,
55 | 			want: server.ToolConfigs{
56 | 				"example_tool": Config{
57 | 					Name:         "example_tool",
58 | 					Kind:         "neo4j-cypher",
59 | 					Source:       "my-neo4j-instance",
60 | 					Description:  "some tool description",
61 | 					AuthRequired: []string{"my-google-auth-service", "other-auth-service"},
62 | 					Statement:    "MATCH (c:Country) WHERE c.name = $country RETURN c.id as id;\n",
63 | 					Parameters: []tools.Parameter{
64 | 						tools.NewStringParameter("country", "country parameter description"),
65 | 					},
66 | 				},
67 | 			},
68 | 		},
69 | 	}
70 | 	for _, tc := range tcs {
71 | 		t.Run(tc.desc, func(t *testing.T) {
72 | 			got := struct {
73 | 				Tools server.ToolConfigs `yaml:"tools"`
74 | 			}{}
75 | 			// Parse contents
76 | 			err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got)
77 | 			if err != nil {
78 | 				t.Fatalf("unable to unmarshal: %s", err)
79 | 			}
80 | 			if diff := cmp.Diff(tc.want, got.Tools); diff != "" {
81 | 				t.Fatalf("incorrect parse: diff %v", diff)
82 | 			}
83 | 		})
84 | 	}
85 | 
86 | }
87 | 
```

--------------------------------------------------------------------------------
/tests/source.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 tests contains end to end tests meant to verify the Toolbox Server
16 | // works as expected when executed as a binary.
17 | 
18 | package tests
19 | 
20 | import (
21 | 	"context"
22 | 	"fmt"
23 | 	"regexp"
24 | 	"strings"
25 | 	"testing"
26 | 	"time"
27 | 
28 | 	"cloud.google.com/go/cloudsqlconn"
29 | 	"github.com/googleapis/genai-toolbox/internal/testutils"
30 | )
31 | 
32 | // RunSourceConnection test for source connection
33 | func RunSourceConnectionTest(t *testing.T, sourceConfig map[string]any, toolKind string) error {
34 | 	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
35 | 	defer cancel()
36 | 
37 | 	var args []string
38 | 
39 | 	// Write config into a file and pass it to command
40 | 	toolsFile := map[string]any{
41 | 		"sources": map[string]any{
42 | 			"my-instance": sourceConfig,
43 | 		},
44 | 		"tools": map[string]any{
45 | 			"my-simple-tool": map[string]any{
46 | 				"kind":        toolKind,
47 | 				"source":      "my-instance",
48 | 				"description": "Simple tool to test end to end functionality.",
49 | 				"statement":   "SELECT 1;",
50 | 			},
51 | 		},
52 | 	}
53 | 	cmd, cleanup, err := StartCmd(ctx, toolsFile, args...)
54 | 	if err != nil {
55 | 		return fmt.Errorf("command initialization returned an error: %s", err)
56 | 	}
57 | 	defer cleanup()
58 | 
59 | 	waitCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
60 | 	defer cancel()
61 | 	out, err := testutils.WaitForString(waitCtx, regexp.MustCompile(`Server ready to serve`), cmd.Out)
62 | 	if err != nil {
63 | 		t.Logf("toolbox command logs: \n%s", out)
64 | 		return fmt.Errorf("toolbox didn't start successfully: %s", err)
65 | 	}
66 | 	return nil
67 | }
68 | 
69 | // GetCloudSQLDialOpts returns cloud sql connector's dial option for ip type.
70 | func GetCloudSQLDialOpts(ipType string) ([]cloudsqlconn.DialOption, error) {
71 | 	switch strings.ToLower(ipType) {
72 | 	case "private":
73 | 		return []cloudsqlconn.DialOption{cloudsqlconn.WithPrivateIP()}, nil
74 | 	case "public":
75 | 		return []cloudsqlconn.DialOption{cloudsqlconn.WithPublicIP()}, nil
76 | 	default:
77 | 		return nil, fmt.Errorf("invalid ipType %s", ipType)
78 | 	}
79 | }
80 | 
```

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

```markdown
 1 | ---
 2 | title: Connect via Gemini CLI Extensions
 3 | type: docs
 4 | weight: 2
 5 | description: "Connect to Toolbox via Gemini CLI Extensions."
 6 | ---
 7 | 
 8 | ## Gemini CLI Extensions
 9 | 
10 | [Gemini CLI][gemini-cli] is an open-source AI agent designed to assist with development workflows by assisting with coding, debugging, data exploration, and content creation. Its mission is to provide an agentic interface for interacting with database and analytics services and popular open-source databases.
11 | 
12 | ### How extensions work
13 | Gemini CLI is highly extensible, allowing for the addition of new tools and capabilities through extensions. You can load the extensions from a GitHub URL, a local directory, or a configurable registry. They provide new tools, slash commands, and prompts to assist with your workflow.
14 | 
15 | Use the Gemini CLI Extensions to load prebuilt or custom tools to interact with your databases. 
16 | 
17 | [gemini-cli]: https://google-gemini.github.io/gemini-cli/
18 | 
19 | Below are a list of Gemini CLI Extensions powered by MCP Toolbox:
20 | 
21 | * [alloydb](https://github.com/gemini-cli-extensions/alloydb)
22 | * [alloydb-observability](https://github.com/gemini-cli-extensions/alloydb-observability)
23 | * [bigquery-conversational-analytics](https://github.com/gemini-cli-extensions/bigquery-conversational-analytics)
24 | * [bigquery-data-analytics](https://github.com/gemini-cli-extensions/bigquery-data-analytics)
25 | * [cloud-sql-mysql](https://github.com/gemini-cli-extensions/cloud-sql-mysql)
26 | * [cloud-sql-mysql-observability](https://github.com/gemini-cli-extensions/cloud-sql-mysql-observability)
27 | * [cloud-sql-postgresql](https://github.com/gemini-cli-extensions/cloud-sql-postgresql)
28 | * [cloud-sql-postgresql-observability](https://github.com/gemini-cli-extensions/cloud-sql-postgresql-observability)
29 | * [cloud-sql-sqlserver](https://github.com/gemini-cli-extensions/cloud-sql-sqlserver)
30 | * [cloud-sql-sqlserver-observability](https://github.com/gemini-cli-extensions/cloud-sql-sqlserver-observability)
31 | * [dataplex](https://github.com/gemini-cli-extensions/dataplex)
32 | * [firestore-native](https://github.com/gemini-cli-extensions/firestore-native)
33 | * [looker](https://github.com/gemini-cli-extensions/looker)
34 | * [mcp-toolbox](https://github.com/gemini-cli-extensions/mcp-toolbox)
35 | * [mysql](https://github.com/gemini-cli-extensions/mysql)
36 | * [postgres](https://github.com/gemini-cli-extensions/postgres)
37 | * [spanner](https://github.com/gemini-cli-extensions/spanner)
38 | * [sql-server](https://github.com/gemini-cli-extensions/sql-server)
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/looker/looker-get-dimensions.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "looker-get-dimensions"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   A "looker-get-dimensions" tool returns all the dimensions from a given explore
 7 |   in a given model in the source.
 8 | aliases:
 9 | - /resources/tools/looker-get-dimensions
10 | ---
11 | 
12 | ## About
13 | 
14 | A `looker-get-dimensions` tool returns all the dimensions from a given explore
15 | in a given model in the source.
16 | 
17 | It's compatible with the following sources:
18 | 
19 | - [looker](../../sources/looker.md)
20 | 
21 | `looker-get-dimensions` accepts two parameters, the `model` and the `explore`.
22 | 
23 | ## Example
24 | 
25 | ```yaml
26 | tools:
27 |     get_dimensions:
28 |         kind: looker-get-dimensions
29 |         source: looker-source
30 |         description: |
31 |           The get_dimensions tool retrieves the list of dimensions defined in
32 |           an explore.
33 | 
34 |           It takes two parameters, the model_name looked up from get_models and the
35 |           explore_name looked up from get_explores.
36 | 
37 |           If this returns a suggestions field for a dimension, the contents of suggestions
38 |           can be used as filters for this field. If this returns a suggest_explore and
39 |           suggest_dimension, a query against that explore and dimension can be used to find
40 |           valid filters for this field.
41 | 
42 | ```
43 | 
44 | The response is a json array with the following elements:
45 | 
46 | ```json
47 | {
48 |   "name": "field name",
49 |   "description": "field description",
50 |   "type": "field type",
51 |   "label": "field label",
52 |   "label_short": "field short label",
53 |   "tags": ["tags", ...],
54 |   "synonyms": ["synonyms", ...],
55 |   "suggestions": ["suggestion", ...],
56 |   "suggest_explore": "explore",
57 |   "suggest_dimension": "dimension"
58 | }
59 | ```
60 | 
61 | ## Reference
62 | 
63 | | **field**   |                  **type**                  | **required** | **description**                                                                                  |
64 | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------|
65 | | kind        |                   string                   |     true     | Must be "looker-get-dimensions".                                                                 |
66 | | source      |                   string                   |     true     | Name of the source the SQL should execute on.                                                    |
67 | | description |                   string                   |     true     | Description of the tool that is passed to the LLM.                                               |
68 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/mysql/mysql-list-tables.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "mysql-list-tables"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   The "mysql-list-tables" tool lists schema information for all or specified tables in a MySQL database.
 7 | aliases:
 8 | - /resources/tools/mysql-list-tables
 9 | ---
10 | 
11 | ## About
12 | 
13 | The `mysql-list-tables` tool retrieves schema information for all or specified
14 | tables in a MySQL database. It is compatible with any of the following sources:
15 | 
16 | - [cloud-sql-mysql](../../sources/cloud-sql-mysql.md)
17 | - [mysql](../../sources/mysql.md)
18 | 
19 | `mysql-list-tables` lists detailed schema information (object type, columns,
20 | constraints, indexes, triggers, owner, comment) as JSON for user-created tables
21 | (ordinary or partitioned). Filters by a comma-separated list of names. If names
22 | are omitted, it lists all tables in user schemas. The output format can be set
23 | to `simple` which will return only the table names or `detailed` which is the
24 | default.
25 | 
26 | The tool takes the following input parameters:
27 | 
28 | | Parameter       | Type   | Description                                                                                                                                                    | Required |
29 | |:----------------|:-------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------|
30 | | `table_names`   | string | Filters by a comma-separated list of names. By default, it lists all tables in user schemas. Default: `""`                                                     | No       |
31 | | `output_format` | string | Indicate the output format of table schema. `simple` will return only the table names, `detailed` will return the full table information. Default: `detailed`. | No       |
32 | 
33 | ## Example
34 | 
35 | ```yaml
36 | tools:
37 |   mysql_list_tables:
38 |     kind: mysql-list-tables
39 |     source: mysql-source
40 |     description: Use this tool to retrieve schema information for all or specified tables. Output format can be simple (only table names) or detailed.
41 | ```
42 | 
43 | ## Reference
44 | 
45 | | **field**   | **type** | **required** | **description**                                      |
46 | |-------------|:--------:|:------------:|------------------------------------------------------|
47 | | kind        |  string  |     true     | Must be "mysql-list-tables".                         |
48 | | source      |  string  |     true     | Name of the source the SQL should execute on.        |
49 | | description |  string  |     true     | Description of the tool that is passed to the agent. |
50 | 
```

--------------------------------------------------------------------------------
/internal/tools/spanner/spannerexecutesql/spannerexecutesql_test.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 spannerexecutesql_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/spannerexecutesql"
25 | )
26 | 
27 | func TestParseFromYamlExecuteSql(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-execute-sql
43 | 					source: my-spanner-instance
44 | 					description: some description
45 | 			`,
46 | 			want: server.ToolConfigs{
47 | 				"example_tool": spannerexecutesql.Config{
48 | 					Name:         "example_tool",
49 | 					Kind:         "spanner-execute-sql",
50 | 					Source:       "my-spanner-instance",
51 | 					Description:  "some description",
52 | 					AuthRequired: []string{},
53 | 					ReadOnly:     false,
54 | 				},
55 | 			},
56 | 		},
57 | 		{
58 | 			desc: "read only set to true",
59 | 			in: `
60 | 			tools:
61 | 				example_tool:
62 | 					kind: spanner-execute-sql
63 | 					source: my-spanner-instance
64 | 					description: some description
65 | 					readOnly: true
66 | 			`,
67 | 			want: server.ToolConfigs{
68 | 				"example_tool": spannerexecutesql.Config{
69 | 					Name:         "example_tool",
70 | 					Kind:         "spanner-execute-sql",
71 | 					Source:       "my-spanner-instance",
72 | 					Description:  "some description",
73 | 					AuthRequired: []string{},
74 | 					ReadOnly:     true,
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 | }
96 | 
```

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

```markdown
 1 | ---
 2 | title: "mongodb-insert-many"
 3 | type: docs
 4 | weight: 1
 5 | description: > 
 6 |   A "mongodb-insert-many" tool inserts multiple new documents into a MongoDB collection.
 7 | aliases:
 8 | - /resources/tools/mongodb-insert-many
 9 | ---
10 | 
11 | ## About
12 | 
13 | The `mongodb-insert-many` tool inserts **multiple new documents** into a
14 | specified MongoDB collection in a single bulk operation. This is highly
15 | efficient for adding large amounts of data at once.
16 | 
17 | This tool takes one required parameter named `data`. This `data` parameter must
18 | be a string containing a **JSON array of document objects**. Upon successful
19 | insertion, the tool returns a JSON array containing the unique `_id` of **each**
20 | new document that was created.
21 | 
22 | This tool is compatible with the following source kind:
23 | 
24 | * [`mongodb`](../../sources/mongodb.md)
25 | 
26 | ---
27 | 
28 | ## Example
29 | 
30 | Here is an example configuration for a tool that logs multiple events at once.
31 | 
32 | ```yaml
33 | tools:
34 |   log_batch_events:
35 |     kind: mongodb-insert-many
36 |     source: my-mongo-source
37 |     description: Inserts a batch of event logs into the database.
38 |     database: logging
39 |     collection: events
40 |     canonical: true
41 | ```
42 | 
43 | An LLM would call this tool by providing an array of documents as a JSON string
44 | in the `data` parameter, like this:
45 | `tool_code: log_batch_events(data='[{"event": "login", "user": "user1"}, {"event": "click", "user": "user2"}, {"event": "logout", "user": "user1"}]')`
46 | 
47 | ---
48 | 
49 | ## Reference
50 | 
51 | | **field**   | **type** | **required** | **description**                                                                                    |
52 | |:------------|:---------|:-------------|:---------------------------------------------------------------------------------------------------|
53 | | kind        | string   | true         | Must be `mongodb-insert-many`.                                                                     |
54 | | source      | string   | true         | The name of the `mongodb` source to use.                                                           |
55 | | description | string   | true         | A description of the tool that is passed to the LLM.                                               |
56 | | database    | string   | true         | The name of the MongoDB database containing the collection.                                        |
57 | | collection  | string   | true         | The name of the MongoDB collection into which the documents will be inserted.                      |
58 | | canonical   | bool     | true         | Determines if the data string is parsed using MongoDB's Canonical or Relaxed Extended JSON format. |
59 | 
```

--------------------------------------------------------------------------------
/internal/sources/sources.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 sources
16 | 
17 | import (
18 | 	"context"
19 | 
20 | 	"fmt"
21 | 
22 | 	"github.com/goccy/go-yaml"
23 | 	"go.opentelemetry.io/otel/attribute"
24 | 	"go.opentelemetry.io/otel/trace"
25 | )
26 | 
27 | // SourceConfigFactory defines the function signature for creating a SourceConfig.
28 | type SourceConfigFactory func(ctx context.Context, name string, decoder *yaml.Decoder) (SourceConfig, error)
29 | 
30 | var sourceRegistry = make(map[string]SourceConfigFactory)
31 | 
32 | // Register registers a new source kind with its factory.
33 | // It returns false if the kind is already registered.
34 | func Register(kind string, factory SourceConfigFactory) bool {
35 | 	if _, exists := sourceRegistry[kind]; exists {
36 | 		// Source with this kind already exists, do not overwrite.
37 | 		return false
38 | 	}
39 | 	sourceRegistry[kind] = factory
40 | 	return true
41 | }
42 | 
43 | // DecodeConfig decodes a source configuration using the registered factory for the given kind.
44 | func DecodeConfig(ctx context.Context, kind string, name string, decoder *yaml.Decoder) (SourceConfig, error) {
45 | 	factory, found := sourceRegistry[kind]
46 | 	if !found {
47 | 		return nil, fmt.Errorf("unknown source kind: %q", kind)
48 | 	}
49 | 	sourceConfig, err := factory(ctx, name, decoder)
50 | 	if err != nil {
51 | 		return nil, fmt.Errorf("unable to parse source %q as %q: %w", name, kind, err)
52 | 	}
53 | 	return sourceConfig, err
54 | }
55 | 
56 | // SourceConfig is the interface for configuring a source.
57 | type SourceConfig interface {
58 | 	SourceConfigKind() string
59 | 	Initialize(ctx context.Context, tracer trace.Tracer) (Source, error)
60 | }
61 | 
62 | // Source is the interface for the source itself.
63 | type Source interface {
64 | 	SourceKind() string
65 | }
66 | 
67 | // InitConnectionSpan adds a span for database pool connection initialization
68 | func InitConnectionSpan(ctx context.Context, tracer trace.Tracer, sourceKind, sourceName string) (context.Context, trace.Span) {
69 | 	ctx, span := tracer.Start(
70 | 		ctx,
71 | 		"toolbox/server/source/connect",
72 | 		trace.WithAttributes(attribute.String("source_kind", sourceKind)),
73 | 		trace.WithAttributes(attribute.String("source_name", sourceName)),
74 | 	)
75 | 	return ctx, span
76 | }
77 | 
```

--------------------------------------------------------------------------------
/docs/en/getting-started/quickstart/python/adk/quickstart.py:
--------------------------------------------------------------------------------

```python
 1 | from google.adk.agents import Agent
 2 | from google.adk.runners import Runner
 3 | from google.adk.sessions import InMemorySessionService
 4 | from google.adk.artifacts.in_memory_artifact_service import InMemoryArtifactService
 5 | from google.genai import types
 6 | from toolbox_core import ToolboxSyncClient
 7 | 
 8 | import asyncio
 9 | import os
10 | 
11 | # TODO(developer): replace this with your Google API key
12 | 
13 | api_key = os.environ.get("GOOGLE_API_KEY") or "your-api-key" # Set your API key here
14 | os.environ["GOOGLE_API_KEY"] = api_key
15 | 
16 | async def main():
17 |   with ToolboxSyncClient("http://127.0.0.1:5000") as toolbox_client:
18 | 
19 |       prompt = """
20 |         You're a helpful hotel assistant. You handle hotel searching, booking and
21 |         cancellations. When the user searches for a hotel, mention it's name, id,
22 |         location and price tier. Always mention hotel ids while performing any
23 |         searches. This is very important for any operations. For any bookings or
24 |         cancellations, please provide the appropriate confirmation. Be sure to
25 |         update checkin or checkout dates if mentioned by the user.
26 |         Don't ask for confirmations from the user.
27 |       """
28 | 
29 |       root_agent = Agent(
30 |           model='gemini-2.0-flash-001',
31 |           name='hotel_agent',
32 |           description='A helpful AI assistant.',
33 |           instruction=prompt,
34 |           tools=toolbox_client.load_toolset("my-toolset"),
35 |       )
36 | 
37 |       session_service = InMemorySessionService()
38 |       artifacts_service = InMemoryArtifactService()
39 |       session = await session_service.create_session(
40 |           state={}, app_name='hotel_agent', user_id='123'
41 |       )
42 |       runner = Runner(
43 |           app_name='hotel_agent',
44 |           agent=root_agent,
45 |           artifact_service=artifacts_service,
46 |           session_service=session_service,
47 |       )
48 | 
49 |       queries = [
50 |           "Find hotels in Basel with Basel in its name.",
51 |           "Can you book the Hilton Basel for me?",
52 |           "Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
53 |           "My check in dates would be from April 10, 2024 to April 19, 2024.",
54 |       ]
55 | 
56 |       for query in queries:
57 |           content = types.Content(role='user', parts=[types.Part(text=query)])
58 |           events = runner.run(session_id=session.id,
59 |                               user_id='123', new_message=content)
60 | 
61 |           responses = (
62 |             part.text
63 |             for event in events
64 |             for part in event.content.parts
65 |             if part.text is not None
66 |           )
67 | 
68 |           for text in responses:
69 |             print(text)
70 | 
71 | asyncio.run(main())
72 | 
```

--------------------------------------------------------------------------------
/internal/tools/alloydb/alloydbgetuser/alloydbgetuser_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 alloydbgetuser_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 | 	alloydbgetuser "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydbgetuser"
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 | 				get-my-user:
42 | 					kind: alloydb-get-user
43 | 					source: my-alloydb-admin-source
44 | 					description: some description
45 | 			`,
46 | 			want: server.ToolConfigs{
47 | 				"get-my-user": alloydbgetuser.Config{
48 | 					Name:         "get-my-user",
49 | 					Kind:         "alloydb-get-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 | 				get-my-user-auth:
61 | 					kind: alloydb-get-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 | 				"get-my-user-auth": alloydbgetuser.Config{
70 | 					Name:         "get-my-user-auth",
71 | 					Kind:         "alloydb-get-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 | 
```

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

```markdown
 1 | ---
 2 | title: "HTTP"
 3 | linkTitle: "HTTP"
 4 | type: docs
 5 | weight: 1
 6 | description: >
 7 |   The HTTP source enables the Toolbox to retrieve data from a remote server using HTTP requests.
 8 | ---
 9 | 
10 | ## About
11 | 
12 | The HTTP Source allows Toolbox to retrieve data from arbitrary HTTP
13 | endpoints. This enables Generative AI applications to access data from web APIs
14 | and other HTTP-accessible resources.
15 | 
16 | ## Available Tools
17 | 
18 | - [`http`](../tools/http/http.md)  
19 |   Make HTTP requests to REST APIs or other web services.
20 | 
21 | ## Example
22 | 
23 | ```yaml
24 | sources:
25 |   my-http-source:
26 |     kind: http
27 |     baseUrl: https://api.example.com/data
28 |     timeout: 10s # default to 30s
29 |     headers:
30 |       Authorization: Bearer ${API_KEY}
31 |       Content-Type: application/json
32 |     queryParams:
33 |       param1: value1
34 |       param2: value2
35 |     # disableSslVerification: false
36 | ```
37 | 
38 | {{< notice tip >}}
39 | Use environment variable replacement with the format ${ENV_NAME}
40 | instead of hardcoding your secrets into the configuration file.
41 | {{< /notice >}}
42 | 
43 | ## Reference
44 | 
45 | | **field**              |     **type**      | **required** | **description**                                                                                                                    |
46 | |------------------------|:-----------------:|:------------:|------------------------------------------------------------------------------------------------------------------------------------|
47 | | kind                   |      string       |     true     | Must be "http".                                                                                                                    |
48 | | baseUrl                |      string       |     true     | The base URL for the HTTP requests (e.g., `https://api.example.com`).                                                              |
49 | | timeout                |      string       |    false     | The timeout for HTTP requests (e.g., "5s", "1m", refer to [ParseDuration][parse-duration-doc] for more examples). Defaults to 30s. |
50 | | headers                | map[string]string |    false     | Default headers to include in the HTTP requests.                                                                                   |
51 | | queryParams            | map[string]string |    false     | Default query parameters to include in the HTTP requests.                                                                          |
52 | | disableSslVerification |       bool        |    false     | Disable SSL certificate verification. This should only be used for local development. Defaults to `false`.                         |
53 | 
54 | [parse-duration-doc]: https://pkg.go.dev/time#ParseDuration
55 | 
```

--------------------------------------------------------------------------------
/.github/workflows/deploy_dev_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 In-development docs"
16 | 
17 | permissions:
18 |   contents: write
19 | 
20 | on:
21 |   push:
22 |     branches:
23 |       - main
24 |     paths:
25 |       - 'docs/**'
26 |       - 'github/workflows/docs**'
27 |       - '.hugo/**'
28 | 
29 |   # Allow triggering manually.
30 |   workflow_dispatch:
31 | 
32 | jobs:
33 |   deploy:
34 |     runs-on: ubuntu-24.04
35 |     defaults:
36 |       run:
37 |         working-directory: .hugo
38 |     # This shared concurrency group ensures only one docs deployment runs at a time.
39 |     concurrency:
40 |       group: docs-deployment
41 |       cancel-in-progress: false
42 |     steps:
43 |       - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
44 |         with:
45 |           fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
46 | 
47 |       - name: Setup Hugo
48 |         uses: peaceiris/actions-hugo@75d2e84710de30f6ff7268e08f310b60ef14033f # v3
49 |         with:
50 |           hugo-version: "0.145.0"
51 |           extended: true
52 | 
53 |       - name: Setup Node
54 |         uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
55 |         with:
56 |           node-version: "22"
57 | 
58 |       - name: Cache dependencies
59 |         uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
60 |         with:
61 |           path: ~/.npm
62 |           key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
63 |           restore-keys: |
64 |             ${{ runner.os }}-node-
65 | 
66 |       - run: npm ci
67 |       - run: hugo --minify
68 |         env:
69 |           HUGO_BASEURL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/dev
70 |           HUGO_RELATIVEURLS: false
71 | 
72 |       - name: Create Staging Directory
73 |         run: |
74 |           mkdir staging
75 |           mv public staging/dev
76 |           mv staging/dev/releases.releases staging/releases.releases
77 | 
78 |       - name: Deploy
79 |         uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4
80 |         with:
81 |           github_token: ${{ secrets.GITHUB_TOKEN }}
82 |           publish_dir: ./.hugo/staging
83 |           publish_branch: versioned-gh-pages
84 |           keep_files: true
85 |           commit_message: "deploy: ${{ github.event.head_commit.message }}"
86 | 
```

--------------------------------------------------------------------------------
/docs/en/resources/tools/dataplex/dataplex-search-entries.md:
--------------------------------------------------------------------------------

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

--------------------------------------------------------------------------------
/internal/tools/alloydb/alloydblistusers/alloydblistusers_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 alloydblistusers_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 | 	alloydblistusers "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydblistusers"
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 | 				list-my-users:
42 | 					kind: alloydb-list-users
43 | 					source: my-alloydb-admin-source
44 | 					description: some description
45 | 			`,
46 | 			want: server.ToolConfigs{
47 | 				"list-my-users": alloydblistusers.Config{
48 | 					Name:         "list-my-users",
49 | 					Kind:         "alloydb-list-users",
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 | 				list-my-users-auth:
61 | 					kind: alloydb-list-users
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 | 				"list-my-users-auth": alloydblistusers.Config{
70 | 					Name:         "list-my-users-auth",
71 | 					Kind:         "alloydb-list-users",
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/alloydb/alloydbgetcluster/alloydbgetcluster_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 alloydbgetcluster_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 | 	alloydbgetcluster "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydbgetcluster"
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 | 				get-my-cluster:
42 | 					kind: alloydb-get-cluster
43 | 					source: my-alloydb-admin-source
44 | 					description: some description
45 | 			`,
46 | 			want: server.ToolConfigs{
47 | 				"get-my-cluster": alloydbgetcluster.Config{
48 | 					Name:         "get-my-cluster",
49 | 					Kind:         "alloydb-get-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 | 				get-my-cluster-auth:
61 | 					kind: alloydb-get-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 | 				"get-my-cluster-auth": alloydbgetcluster.Config{
70 | 					Name:         "get-my-cluster-auth",
71 | 					Kind:         "alloydb-get-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 | 
```

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

--------------------------------------------------------------------------------
/.github/workflows/lint.yaml:
--------------------------------------------------------------------------------

```yaml
 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 | name: lint
16 | on:
17 |   pull_request:
18 |   pull_request_target:
19 |     types: [labeled]
20 | 
21 | # Declare default permissions as read only.
22 | permissions: read-all
23 | 
24 | jobs:
25 |   lint:
26 |     if: "${{ github.event.action != 'labeled' || github.event.label.name == 'tests: run' }}"
27 |     name: lint
28 |     runs-on: ubuntu-latest
29 |     concurrency:
30 |       group: ${{ github.workflow }}-${{ github.ref }}
31 |       cancel-in-progress: true
32 |     permissions:
33 |       contents: 'read'
34 |       issues: 'write'
35 |       pull-requests: 'write'
36 |     steps:
37 |       - name: Remove PR Label
38 |         if: "${{ github.event.action == 'labeled' && github.event.label.name == 'tests: run' }}"
39 |         uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
40 |         with:
41 |           github-token: ${{ secrets.GITHUB_TOKEN }}
42 |           script: |
43 |             try {
44 |               await github.rest.issues.removeLabel({
45 |                 name: 'tests: run',
46 |                 owner: context.repo.owner,
47 |                 repo: context.repo.repo,
48 |                 issue_number: context.payload.pull_request.number
49 |               });
50 |             } catch (e) {
51 |               console.log('Failed to remove label. Another job may have already removed it!');
52 |             }
53 |       - name: Setup Go
54 |         uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
55 |         with:
56 |           go-version: "1.25"
57 |       - name: Checkout code
58 |         uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
59 |         with:
60 |           ref: ${{ github.event.pull_request.head.sha }}
61 |           repository: ${{ github.event.pull_request.head.repo.full_name }}
62 |           token: ${{ secrets.GITHUB_TOKEN }}
63 |       - name: >
64 |           Verify go mod tidy. If you're reading this and the check has
65 |           failed, run `goimports -w . && go mod tidy && golangci-lint run`
66 |         run: |
67 |           go mod tidy && git diff --exit-code
68 |       - name: golangci-lint
69 |         uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
70 |         with:
71 |           version: latest
72 |           args: --timeout 3m
73 | 
```

--------------------------------------------------------------------------------
/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance_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 alloydbgetinstance_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 | 	alloydbgetinstance "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydbgetinstance"
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 | 				get-my-instance:
42 | 					kind: alloydb-get-instance
43 | 					source: my-alloydb-admin-source
44 | 					description: some description
45 | 			`,
46 | 			want: server.ToolConfigs{
47 | 				"get-my-instance": alloydbgetinstance.Config{
48 | 					Name:         "get-my-instance",
49 | 					Kind:         "alloydb-get-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 | 				get-my-instance-auth:
61 | 					kind: alloydb-get-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 | 				"get-my-instance-auth": alloydbgetinstance.Config{
70 | 					Name:         "get-my-instance-auth",
71 | 					Kind:         "alloydb-get-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/postgres/postgreslistactivequeries/postgreslistactivequeries_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 postgreslistactivequeries_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/postgres/postgreslistactivequeries"
25 | )
26 | 
27 | func TestParseFromYamlPostgresListTables(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: postgres-list-active-queries
43 | 					source: my-postgres-instance
44 | 					description: some description
45 | 					authRequired:
46 | 						- my-google-auth-service
47 | 						- other-auth-service
48 | 			`,
49 | 			want: server.ToolConfigs{
50 | 				"example_tool": postgreslistactivequeries.Config{
51 | 					Name:         "example_tool",
52 | 					Kind:         "postgres-list-active-queries",
53 | 					Source:       "my-postgres-instance",
54 | 					Description:  "some description",
55 | 					AuthRequired: []string{"my-google-auth-service", "other-auth-service"},
56 | 				},
57 | 			},
58 | 		},
59 | 		{
60 | 			desc: "basic example",
61 | 			in: `
62 | 			tools:
63 | 				example_tool:
64 | 					kind: postgres-list-active-queries
65 | 					source: my-postgres-instance
66 | 					description: some description
67 | 			`,
68 | 			want: server.ToolConfigs{
69 | 				"example_tool": postgreslistactivequeries.Config{
70 | 					Name:         "example_tool",
71 | 					Kind:         "postgres-list-active-queries",
72 | 					Source:       "my-postgres-instance",
73 | 					Description:  "some description",
74 | 					AuthRequired: []string{},
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 | }
96 | 
```

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

```markdown
 1 | ---
 2 | title: "looker-health-analyze"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   "looker-health-analyze" provides a set of analytical commands for a Looker instance, allowing users to analyze projects, models, and explores.
 7 | aliases:
 8 | - /resources/tools/looker-health-analyze
 9 | ---
10 | 
11 | ## About
12 | 
13 | The `looker-health-analyze` tool performs various analysis tasks on a Looker instance. The `action` parameter selects the type of analysis to perform:
14 | 
15 | - `projects`: Analyzes all projects or a specified project, reporting on the number of models and view files, as well as Git connection and validation status.
16 | - `models`: Analyzes all models or a specified model, providing a count of explores, unused explores, and total query counts.
17 | - `explores`: Analyzes all explores or a specified explore, reporting on the number of joins, unused joins, fields, unused fields, and query counts. Being classified as **Unused** is determined by whether a field has been used as a field or filter within the past 90 days in production.
18 | 
19 | ## Parameters
20 | 
21 | | **field** | **type** | **required** | **description** |
22 | | :--- | :--- | :--- | :--- |
23 | | kind | string | true | Must be "looker-health-analyze" |
24 | | source | string | true | Looker source name |
25 | | action | string | true | The analysis to perform: `projects`, `models`, or `explores`. |
26 | | project | string | false | The name of the Looker project to analyze. |
27 | | model | string | false | The name of the Looker model to analyze. Required for `explores` actions. |
28 | | explore | string | false | The name of the Looker explore to analyze. Required for the `explores` action. |
29 | | timeframe | int | false | The timeframe in days to analyze. Defaults to 90. |
30 | | min_queries | int | false | The minimum number of queries for a model or explore to be considered used. Defaults to 1. |
31 | 
32 | ## Example
33 | 
34 | Analyze all models in `thelook` project.
35 | 
36 | ```yaml
37 | tools:
38 |   analyze-tool:
39 |     kind: looker-health-analyze
40 |     source: looker-source
41 |     description: |
42 |       Analyzes Looker projects, models, and explores.
43 |       Specify the `action` parameter to select the type of analysis.
44 |     parameters:
45 |       action: models
46 |       project: "thelook"
47 | 
48 | Analyze all the explores in the `ecomm` model of `thelook` project. Specifically look at usage within the past 20 days. Usage minimum should be at least 10 queries.
49 | 
50 | ```yaml
51 | tools:
52 |   analyze-tool:
53 |     kind: looker-health-analyze
54 |     source: looker-source
55 |     description: |
56 |       Analyzes Looker projects, models, and explores.
57 |       Specify the `action` parameter to select the type of analysis.
58 |     parameters:
59 |       action: explores
60 |       project: "thelook"
61 |       model: "ecomm"
62 |       timeframe: 20
63 |       min_queries: 10
```

--------------------------------------------------------------------------------
/internal/tools/alloydb/alloydblistclusters/alloydblistclusters_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 alloydblistclusters_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 | 	alloydblistclusters "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydblistclusters"
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 | 				list-my-clusters:
42 | 					kind: alloydb-list-clusters
43 | 					source: my-alloydb-admin-source
44 | 					description: some description
45 | 			`,
46 | 			want: server.ToolConfigs{
47 | 				"list-my-clusters": alloydblistclusters.Config{
48 | 					Name:         "list-my-clusters",
49 | 					Kind:         "alloydb-list-clusters",
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 | 				list-my-clusters-auth:
61 | 					kind: alloydb-list-clusters
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 | 				"list-my-clusters-auth": alloydblistclusters.Config{
70 | 					Name:         "list-my-clusters-auth",
71 | 					Kind:         "alloydb-list-clusters",
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/resources/tools/dataplex/dataplex-search-aspect-types.md:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: "dataplex-search-aspect-types"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |   A "dataplex-search-aspect-types" tool allows to to find aspect types relevant to the query.
 7 | aliases:
 8 | - /resources/tools/dataplex-search-aspect-types
 9 | ---
10 | 
11 | ## About
12 | 
13 | A `dataplex-search-aspect-types` tool allows to fetch the metadata template of
14 | aspect types based on search query.
15 | It's compatible with the following sources:
16 | 
17 | - [dataplex](../../sources/dataplex.md)
18 | 
19 | `dataplex-search-aspect-types` accepts following parameters optionally:
20 | 
21 | - `query` - Narrows down the search of aspect types to value of this parameter.
22 |   If not provided, it fetches all aspect types available to the user.
23 | - `pageSize` - Number of returned aspect types in the search page. Defaults to `5`.
24 | - `orderBy` - Specifies the ordering of results. Supported values are: relevance
25 |   (default), last_modified_timestamp, last_modified_timestamp asc.
26 | 
27 | ## Requirements
28 | 
29 | ### IAM Permissions
30 | 
31 | Dataplex uses [Identity and Access Management (IAM)][iam-overview] to control
32 | user and group access to Dataplex resources. Toolbox will use your
33 | [Application Default Credentials (ADC)][adc] to authorize and authenticate when
34 | interacting with [Dataplex][dataplex-docs].
35 | 
36 | In addition to [setting the ADC for your server][set-adc], you need to ensure
37 | the IAM identity has been given the correct IAM permissions for the tasks you
38 | intend to perform. See [Dataplex Universal Catalog IAM permissions][iam-permissions]
39 | and [Dataplex Universal Catalog IAM roles][iam-roles] for more information on
40 | applying IAM permissions and roles to an identity.
41 | 
42 | [iam-overview]: https://cloud.google.com/dataplex/docs/iam-and-access-control
43 | [adc]: https://cloud.google.com/docs/authentication#adc
44 | [set-adc]: https://cloud.google.com/docs/authentication/provide-credentials-adc
45 | [iam-permissions]: https://cloud.google.com/dataplex/docs/iam-permissions
46 | [iam-roles]: https://cloud.google.com/dataplex/docs/iam-roles
47 | [dataplex-docs]: https://cloud.google.com/dataplex
48 | 
49 | ## Example
50 | 
51 | ```yaml
52 | tools:
53 |   dataplex-search-aspect-types:
54 |     kind: dataplex-search-aspect-types
55 |     source: my-dataplex-source
56 |     description: Use this tool to find aspect types relevant to the query.
57 | ```
58 | 
59 | ## Reference
60 | 
61 | | **field**   | **type** | **required** | **description**                                    |
62 | |-------------|:--------:|:------------:|----------------------------------------------------|
63 | | kind        |  string  |     true     | Must be "dataplex-search-aspect-types".            |
64 | | source      |  string  |     true     | Name of the source the tool should execute on.     |
65 | | description |  string  |     true     | Description of the tool that is passed to the LLM. |
66 | 
```

--------------------------------------------------------------------------------
/internal/tools/alloydb/alloydblistinstances/alloydblistinstances_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 alloydblistinstances_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 | 	alloydblistinstances "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydblistinstances"
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 | 				list-my-instances:
42 | 					kind: alloydb-list-instances
43 | 					source: my-alloydb-admin-source
44 | 					description: some description
45 | 			`,
46 | 			want: server.ToolConfigs{
47 | 				"list-my-instances": alloydblistinstances.Config{
48 | 					Name:         "list-my-instances",
49 | 					Kind:         "alloydb-list-instances",
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 | 				list-my-instances-auth:
61 | 					kind: alloydb-list-instances
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 | 				"list-my-instances-auth": alloydblistinstances.Config{
70 | 					Name:         "list-my-instances-auth",
71 | 					Kind:         "alloydb-list-instances",
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/postgres/postgreslistavailableextensions/postgreslistavailableextensions_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 postgreslistavailableextensions_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/postgres/postgreslistavailableextensions"
25 | )
26 | 
27 | func TestParseFromYamlPostgres(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: postgres-list-available-extensions
43 | 					source: my-pg-instance
44 | 					description: "some description"
45 | 					authRequired:
46 | 						- my-google-auth-service
47 | 						- other-auth-service
48 | 			`,
49 | 			want: server.ToolConfigs{
50 | 				"example_tool": postgreslistavailableextensions.Config{
51 | 					Name:         "example_tool",
52 | 					Kind:         "postgres-list-available-extensions",
53 | 					Source:       "my-pg-instance",
54 | 					Description:  "some description",
55 | 					AuthRequired: []string{"my-google-auth-service", "other-auth-service"},
56 | 				},
57 | 			},
58 | 		},
59 | 		{
60 | 			desc: "basic example without authRequired",
61 | 			in: `
62 | 			tools:
63 | 				example_tool:
64 | 					kind: postgres-list-available-extensions
65 | 					source: my-pg-instance
66 | 					description: "some description"
67 | 			`,
68 | 			want: server.ToolConfigs{
69 | 				"example_tool": postgreslistavailableextensions.Config{
70 | 					Name:         "example_tool",
71 | 					Kind:         "postgres-list-available-extensions",
72 | 					Source:       "my-pg-instance",
73 | 					Description:  "some description",
74 | 					AuthRequired: []string{},
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 | }
96 | 
```

--------------------------------------------------------------------------------
/internal/tools/postgres/postgreslistinstalledextensions/postgreslistinstalledextensions_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 postgreslistinstalledextensions_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/postgres/postgreslistinstalledextensions"
25 | )
26 | 
27 | func TestParseFromYamlPostgres(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: postgres-list-installed-extensions
43 | 					source: my-pg-instance
44 | 					description: "some description"
45 | 					authRequired:
46 | 						- my-google-auth-service
47 | 						- other-auth-service
48 | 			`,
49 | 			want: server.ToolConfigs{
50 | 				"example_tool": postgreslistinstalledextensions.Config{
51 | 					Name:         "example_tool",
52 | 					Kind:         "postgres-list-installed-extensions",
53 | 					Source:       "my-pg-instance",
54 | 					Description:  "some description",
55 | 					AuthRequired: []string{"my-google-auth-service", "other-auth-service"},
56 | 				},
57 | 			},
58 | 		},
59 | 		{
60 | 			desc: "basic example without authRequired",
61 | 			in: `
62 | 			tools:
63 | 				example_tool:
64 | 					kind: postgres-list-installed-extensions
65 | 					source: my-pg-instance
66 | 					description: "some description"
67 | 			`,
68 | 			want: server.ToolConfigs{
69 | 				"example_tool": postgreslistinstalledextensions.Config{
70 | 					Name:         "example_tool",
71 | 					Kind:         "postgres-list-installed-extensions",
72 | 					Source:       "my-pg-instance",
73 | 					Description:  "some description",
74 | 					AuthRequired: []string{},
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 | }
96 | 
```

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

```markdown
 1 | ---
 2 | title: "Dgraph"
 3 | type: docs
 4 | weight: 1
 5 | description: >
 6 |  Dgraph is fully open-source, built-for-scale graph database for Gen AI workloads
 7 | 
 8 | ---
 9 | 
10 | ## About
11 | 
12 | [Dgraph][dgraph-docs] is an open-source graph database. It is designed for
13 | real-time workloads, horizontal scalability, and data flexibility. Implemented
14 | as a distributed system, Dgraph processes queries in parallel to deliver the
15 | fastest result.
16 | 
17 | This source can connect to either a self-managed Dgraph cluster or one hosted on
18 | Dgraph Cloud. If you're new to Dgraph, the fastest way to get started is to
19 | [sign up for Dgraph Cloud][dgraph-login].
20 | 
21 | [dgraph-docs]: https://dgraph.io/docs
22 | [dgraph-login]: https://cloud.dgraph.io/login
23 | 
24 | ## Available Tools
25 | 
26 | - [`dgraph-dql`](../tools/dgraph/dgraph-dql.md)  
27 |   Run DQL (Dgraph Query Language) queries.
28 | 
29 | ## Requirements
30 | 
31 | ### Database User
32 | 
33 | When **connecting to a hosted Dgraph database**, this source uses the API key
34 | for access. If you are using a dedicated environment, you will additionally need
35 | the namespace and user credentials for that namespace.
36 | 
37 | For **connecting to a local or self-hosted Dgraph database**, use the namespace
38 | and user credentials for that namespace.
39 | 
40 | ## Example
41 | 
42 | ```yaml
43 | sources:
44 |     my-dgraph-source:
45 |         kind: dgraph
46 |         dgraphUrl: https://xxxx.cloud.dgraph.io
47 |         user: ${USER_NAME}
48 |         password: ${PASSWORD}
49 |         apiKey: ${API_KEY}
50 |         namespace : 0
51 | ```
52 | 
53 | {{< notice tip >}}
54 | Use environment variable replacement with the format ${ENV_NAME}
55 | instead of hardcoding your secrets into the configuration file.
56 | {{< /notice >}}
57 | 
58 | ## Reference
59 | 
60 | | **Field**   | **Type** | **Required** | **Description**                                                                                  |
61 | |-------------|:--------:|:------------:|--------------------------------------------------------------------------------------------------|
62 | | kind        |  string  |     true     | Must be "dgraph".                                                                                |
63 | | dgraphUrl   |  string  |     true     | Connection URI (e.g. "<https://xxx.cloud.dgraph.io>", "<https://localhost:8080>").               |
64 | | user        |  string  |     false    | Name of the Dgraph user to connect as (e.g., "groot").                                           |
65 | | password    |  string  |     false    | Password of the Dgraph user (e.g., "password").                                                  |
66 | | apiKey      |  string  |     false    | API key to connect to a Dgraph Cloud instance.                                                   |
67 | | namespace   |  uint64  |     false    | Dgraph namespace (not required for Dgraph Cloud Shared Clusters).                                |
68 | 
```

--------------------------------------------------------------------------------
/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 | 
```
Page 4/45FirstPrevNextLast