mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-01-11 16:38:15 -05:00
Compare commits
85 Commits
kurtisvg-p
...
sample
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7e4c12915 | ||
|
|
5530b08f34 | ||
|
|
e515d9254f | ||
|
|
d661f5343f | ||
|
|
6c8460b0e5 | ||
|
|
71f360d315 | ||
|
|
33beb7187d | ||
|
|
4f46782927 | ||
|
|
bf6831fdbe | ||
|
|
bd195d2fe2 | ||
|
|
ec0d3a6eb3 | ||
|
|
81d239b053 | ||
|
|
0cd3f16f87 | ||
|
|
aa3972470f | ||
|
|
36d79ef147 | ||
|
|
302faf2513 | ||
|
|
22cf228b88 | ||
|
|
794ad91885 | ||
|
|
b5f9780a59 | ||
|
|
cce602f280 | ||
|
|
70e832bd08 | ||
|
|
05b14a8824 | ||
|
|
664711f4b3 | ||
|
|
f819e26443 | ||
|
|
ec9af0a215 | ||
|
|
3d622b18be | ||
|
|
0c3a268475 | ||
|
|
8eda284070 | ||
|
|
ad53fb4460 | ||
|
|
28333e5faf | ||
|
|
4b32c2a770 | ||
|
|
d6c55195d7 | ||
|
|
4f022b6700 | ||
|
|
181a077bef | ||
|
|
430a97d697 | ||
|
|
77411ae8ab | ||
|
|
166d7b197c | ||
|
|
0b2121ea72 | ||
|
|
be30c1c08f | ||
|
|
36225aa6db | ||
|
|
e86a3823b0 | ||
|
|
afba7a57cd | ||
|
|
88f4b3028d | ||
|
|
19a7fe2928 | ||
|
|
54d33fbd90 | ||
|
|
e929942b74 | ||
|
|
0a8351c32d | ||
|
|
e2ddec9675 | ||
|
|
2cad82e510 | ||
|
|
3ae2526e0f | ||
|
|
8755e3db34 | ||
|
|
ade9a2515b | ||
|
|
d2978d5395 | ||
|
|
14c224939a | ||
|
|
7430f318a2 | ||
|
|
21085ef422 | ||
|
|
d16f89fbb6 | ||
|
|
4da2fcc055 | ||
|
|
27381ed9c0 | ||
|
|
670da6e451 | ||
|
|
2f1ed3aaf5 | ||
|
|
8d20a48f13 | ||
|
|
89af3a4ca3 | ||
|
|
6029e129bc | ||
|
|
8628f7190b | ||
|
|
f544e676ea | ||
|
|
a21e68022b | ||
|
|
08397cf398 | ||
|
|
75a04a55dd | ||
|
|
a5e74af104 | ||
|
|
58d7b3e5f8 | ||
|
|
ca353e0b66 | ||
|
|
fc707fb561 | ||
|
|
03aa9fabac | ||
|
|
1a6dfe8d37 | ||
|
|
297f240955 | ||
|
|
6ad6d39084 | ||
|
|
f8929e3396 | ||
|
|
bc91559cc4 | ||
|
|
650e2e26f5 | ||
|
|
00866bc7fc | ||
|
|
5bcd52e7dc | ||
|
|
7651357d42 | ||
|
|
b94a021ca1 | ||
|
|
81c36354cb |
@@ -152,25 +152,25 @@ steps:
|
||||
bigquery \
|
||||
bigquery
|
||||
|
||||
# - id: "dataplex"
|
||||
# name: golang:1
|
||||
# waitFor: ["compile-test-binary"]
|
||||
# entrypoint: /bin/bash
|
||||
# env:
|
||||
# - "GOPATH=/gopath"
|
||||
# - "DATAPLEX_PROJECT=$PROJECT_ID"
|
||||
# - "SERVICE_ACCOUNT_EMAIL=$SERVICE_ACCOUNT_EMAIL"
|
||||
# secretEnv: ["CLIENT_ID"]
|
||||
# volumes:
|
||||
# - name: "go"
|
||||
# path: "/gopath"
|
||||
# args:
|
||||
# - -c
|
||||
# - |
|
||||
# .ci/test_with_coverage.sh \
|
||||
# "Dataplex" \
|
||||
# dataplex \
|
||||
# dataplex
|
||||
- id: "dataplex"
|
||||
name: golang:1
|
||||
waitFor: ["compile-test-binary"]
|
||||
entrypoint: /bin/bash
|
||||
env:
|
||||
- "GOPATH=/gopath"
|
||||
- "DATAPLEX_PROJECT=$PROJECT_ID"
|
||||
- "SERVICE_ACCOUNT_EMAIL=$SERVICE_ACCOUNT_EMAIL"
|
||||
secretEnv: ["CLIENT_ID"]
|
||||
volumes:
|
||||
- name: "go"
|
||||
path: "/gopath"
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
.ci/test_with_coverage.sh \
|
||||
"Dataplex" \
|
||||
dataplex \
|
||||
dataplex
|
||||
|
||||
- id: "postgres"
|
||||
name: golang:1
|
||||
@@ -328,23 +328,23 @@ steps:
|
||||
mssql \
|
||||
mssql
|
||||
|
||||
- id: "dgraph"
|
||||
name: golang:1
|
||||
waitFor: ["compile-test-binary"]
|
||||
entrypoint: /bin/bash
|
||||
env:
|
||||
- "GOPATH=/gopath"
|
||||
- "DGRAPH_URL=$_DGRAPHURL"
|
||||
volumes:
|
||||
- name: "go"
|
||||
path: "/gopath"
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
.ci/test_with_coverage.sh \
|
||||
"Dgraph" \
|
||||
dgraph \
|
||||
dgraph
|
||||
# - id: "dgraph"
|
||||
# name: golang:1
|
||||
# waitFor: ["compile-test-binary"]
|
||||
# entrypoint: /bin/bash
|
||||
# env:
|
||||
# - "GOPATH=/gopath"
|
||||
# - "DGRAPH_URL=$_DGRAPHURL"
|
||||
# volumes:
|
||||
# - name: "go"
|
||||
# path: "/gopath"
|
||||
# args:
|
||||
# - -c
|
||||
# - |
|
||||
# .ci/test_with_coverage.sh \
|
||||
# "Dgraph" \
|
||||
# dgraph \
|
||||
# dgraph
|
||||
|
||||
- id: "http"
|
||||
name: golang:1
|
||||
@@ -464,7 +464,7 @@ steps:
|
||||
"OceanBase" \
|
||||
oceanbase \
|
||||
oceanbase
|
||||
|
||||
|
||||
- id: "firestore"
|
||||
name: golang:1
|
||||
waitFor: ["compile-test-binary"]
|
||||
@@ -575,6 +575,28 @@ steps:
|
||||
firebird \
|
||||
firebirdsql firebirdexecutesql
|
||||
|
||||
- id: "clickhouse"
|
||||
name : golang:1
|
||||
waitFor: ["compile-test-binary"]
|
||||
entrypoint: /bin/bash
|
||||
env:
|
||||
- "GOPATH=/gopath"
|
||||
- "CLICKHOUSE_DATABASE=$_CLICKHOUSE_DATABASE"
|
||||
- "CLICKHOUSE_PORT=$_CLICKHOUSE_PORT"
|
||||
- "CLICKHOUSE_PROTOCOL=$_CLICKHOUSE_PROTOCOL"
|
||||
- "SERVICE_ACCOUNT_EMAIL=$SERVICE_ACCOUNT_EMAIL"
|
||||
secretEnv: ["CLICKHOUSE_HOST", "CLICKHOUSE_USER", "CLIENT_ID"]
|
||||
volumes:
|
||||
- name: "go"
|
||||
path: "/gopath"
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
.ci/test_with_coverage.sh \
|
||||
"ClickHouse" \
|
||||
clickhouse \
|
||||
clickhouse
|
||||
|
||||
- id: "trino"
|
||||
name: golang:1
|
||||
waitFor: ["compile-test-binary"]
|
||||
@@ -598,6 +620,25 @@ steps:
|
||||
trino \
|
||||
trinosql trinoexecutesql
|
||||
|
||||
- id: "yugabytedb"
|
||||
name: golang:1
|
||||
waitFor: ["compile-test-binary"]
|
||||
entrypoint: /bin/bash
|
||||
env:
|
||||
- "GOPATH=/gopath"
|
||||
- "YUGABYTEDB_DATABASE=$_YUGABYTEDB_DATABASE"
|
||||
- "YUGABYTEDB_PORT=$_YUGABYTEDB_PORT"
|
||||
- "YUGABYTEDB_LOADBALANCE=$_YUGABYTEDB_LOADBALANCE"
|
||||
- "SERVICE_ACCOUNT_EMAIL=$SERVICE_ACCOUNT_EMAIL"
|
||||
secretEnv: ["YUGABYTEDB_USER", "YUGABYTEDB_PASS", "YUGABYTEDB_HOST", "CLIENT_ID"]
|
||||
volumes:
|
||||
- name: "go"
|
||||
path: "/gopath"
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
./yugabytedb.test -test.v
|
||||
|
||||
availableSecrets:
|
||||
secretManager:
|
||||
- versionName: projects/$PROJECT_ID/secrets/cloud_sql_pg_user/versions/latest
|
||||
@@ -660,6 +701,10 @@ availableSecrets:
|
||||
env: TIDB_USER
|
||||
- versionName: projects/$PROJECT_ID/secrets/tidb_pass/versions/latest
|
||||
env: TIDB_PASS
|
||||
- versionName: projects/$PROJECT_ID/secrets/clickhouse_host/versions/latest
|
||||
env: CLICKHOUSE_HOST
|
||||
- versionName: projects/$PROJECT_ID/secrets/clickhouse_user/versions/latest
|
||||
env: CLICKHOUSE_USER
|
||||
- versionName: projects/$PROJECT_ID/secrets/firebird_user/versions/latest
|
||||
env: FIREBIRD_USER
|
||||
- versionName: projects/$PROJECT_ID/secrets/firebird_pass/versions/latest
|
||||
@@ -672,6 +717,13 @@ availableSecrets:
|
||||
env: OCEANBASE_USER
|
||||
- versionName: projects/$PROJECT_ID/secrets/oceanbase_pass/versions/latest
|
||||
env: OCEANBASE_PASSWORD
|
||||
- versionName: projects/$PROJECT_ID/secrets/yugabytedb_host/versions/latest
|
||||
env: YUGABYTEDB_HOST
|
||||
- versionName: projects/$PROJECT_ID/secrets/yugabytedb_user/versions/latest
|
||||
env: YUGABYTEDB_USER
|
||||
- versionName: projects/$PROJECT_ID/secrets/yugabytedb_pass/versions/latest
|
||||
env: YUGABYTEDB_PASS
|
||||
|
||||
|
||||
options:
|
||||
logging: CLOUD_LOGGING_ONLY
|
||||
@@ -707,6 +759,9 @@ substitutions:
|
||||
_LOOKER_VERIFY_SSL: "true"
|
||||
_TIDB_HOST: 127.0.0.1
|
||||
_TIDB_PORT: "4000"
|
||||
_CLICKHOUSE_DATABASE: "default"
|
||||
_CLICKHOUSE_PORT: "8123"
|
||||
_CLICKHOUSE_PROTOCOL: "http"
|
||||
_FIREBIRD_HOST: 127.0.0.1
|
||||
_FIREBIRD_PORT: "3050"
|
||||
_TRINO_HOST: 127.0.0.1
|
||||
@@ -715,3 +770,6 @@ substitutions:
|
||||
_TRINO_SCHEMA: "default"
|
||||
_OCEANBASE_PORT: "2883"
|
||||
_OCEANBASE_DATABASE: "oceanbase"
|
||||
_YUGABYTEDB_DATABASE: "yugabyte"
|
||||
_YUGABYTEDB_PORT: "5433"
|
||||
_YUGABYTEDB_LOADBALANCE: "false"
|
||||
|
||||
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,16 +1,19 @@
|
||||
## Description
|
||||
|
||||
---
|
||||
> Should include a concise description of the changes (bug or feature), it's
|
||||
> impact, along with a summary of the solution
|
||||
|
||||
## PR Checklist
|
||||
|
||||
---
|
||||
> Thank you for opening a Pull Request! Before submitting your PR, there are a
|
||||
> few things you can do to make sure it goes smoothly:
|
||||
|
||||
- [ ] Make sure you reviewed
|
||||
[CONTRIBUTING.md](https://github.com/googleapis/genai-toolbox/blob/main/CONTRIBUTING.md)
|
||||
- [ ] Make sure to open an issue as a
|
||||
[bug/issue](https://github.com/googleapis/langchain-google-alloydb-pg-python/issues/new/choose)
|
||||
[bug/issue](https://github.com/googleapis/genai-toolbox/issues/new/choose)
|
||||
before writing your code! That way we can discuss the change, evaluate
|
||||
designs, and agree on the general idea
|
||||
- [ ] Ensure the tests and linter pass
|
||||
@@ -18,4 +21,4 @@
|
||||
- [ ] Appropriate docs were updated (if necessary)
|
||||
- [ ] Make sure to add `!` if this involve a breaking change
|
||||
|
||||
🛠️ Fixes #<issue_number_goes_here>
|
||||
🛠️ Fixes #<issue_number_goes_here>
|
||||
|
||||
17
.github/blunderbuss.yml
vendored
17
.github/blunderbuss.yml
vendored
@@ -1,7 +1,24 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
assign_issues:
|
||||
- Yuan325
|
||||
- duwenxin99
|
||||
- averikitsch
|
||||
- anubhav756
|
||||
- dishaprakash
|
||||
- twishabansal
|
||||
assign_issues_by:
|
||||
- labels:
|
||||
- 'product: bigquery'
|
||||
|
||||
@@ -20,3 +20,5 @@ sourceFileExtensions:
|
||||
- 'go'
|
||||
- 'yaml'
|
||||
- 'yml'
|
||||
ignoreFiles:
|
||||
- 'docs/en/getting-started/quickstart/**'
|
||||
4
.github/labels.yaml
vendored
4
.github/labels.yaml
vendored
@@ -88,6 +88,10 @@
|
||||
color: 8befd7
|
||||
description: 'Status: reviewer is awaiting feedback or responses from the author before proceeding.'
|
||||
|
||||
- name: 'release candidate'
|
||||
color: 32CD32
|
||||
description: 'Use label to signal PR should be included in the next release.'
|
||||
|
||||
# Product Labels
|
||||
- name: 'product: bigquery'
|
||||
color: 5065c7
|
||||
|
||||
18
.github/release-please.yml
vendored
18
.github/release-please.yml
vendored
@@ -20,26 +20,20 @@ extraFiles: [
|
||||
"README.md",
|
||||
"docs/en/getting-started/colab_quickstart.ipynb",
|
||||
"docs/en/getting-started/introduction/_index.md",
|
||||
"docs/en/getting-started/local_quickstart.md",
|
||||
"docs/en/getting-started/local_quickstart_js.md",
|
||||
"docs/en/getting-started/local_quickstart_go.md",
|
||||
"docs/en/getting-started/mcp_quickstart/_index.md",
|
||||
"docs/en/getting-started/quickstart/shared/configure_toolbox.md",
|
||||
"docs/en/samples/alloydb/_index.md",
|
||||
"docs/en/samples/alloydb/mcp_quickstart.md",
|
||||
"docs/en/samples/alloydb/ai-nl/alloydb_ai_nl.ipynb",
|
||||
"docs/en/samples/bigquery/local_quickstart.md",
|
||||
"docs/en/samples/bigquery/mcp_quickstart/_index.md",
|
||||
"docs/en/samples/bigquery/colab_quickstart_bigquery.ipynb",
|
||||
"docs/en/samples/looker/looker_gemini.md",
|
||||
"docs/en/samples/looker/looker_mcp_inspector.md",
|
||||
"docs/en/how-to/connect-ide/alloydb_pg_mcp.md",
|
||||
"docs/en/how-to/connect-ide/alloydb_pg_admin_mcp.md",
|
||||
"docs/en/how-to/connect-ide/bigquery_mcp.md",
|
||||
"docs/en/how-to/connect-ide/cloud_sql_pg_mcp.md",
|
||||
"docs/en/how-to/connect-ide/cloud_sql_mssql_mcp.md",
|
||||
"docs/en/how-to/connect-ide/cloud_sql_mysql_mcp.md",
|
||||
"docs/en/how-to/connect-ide/firestore_mcp.md",
|
||||
"docs/en/samples/looker/looker_gemini_oauth/_index.md",
|
||||
"docs/en/samples/looker/looker_mcp_inspector/_index.md",
|
||||
"docs/en/how-to/connect-ide/looker_mcp.md",
|
||||
"docs/en/how-to/connect-ide/mysql_mcp.md",
|
||||
"docs/en/how-to/connect-ide/mssql_mcp.md",
|
||||
"docs/en/how-to/connect-ide/postgres_mcp.md",
|
||||
"docs/en/how-to/connect-ide/spanner_mcp.md",
|
||||
"docs/en/how-to/connect-ide/neo4j_mcp.md",
|
||||
]
|
||||
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
steps:
|
||||
- uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' # v7
|
||||
- uses: 'actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b' # v7
|
||||
with:
|
||||
script: |-
|
||||
// parse test names
|
||||
|
||||
2
.github/workflows/docs_preview_clean.yaml
vendored
2
.github/workflows/docs_preview_clean.yaml
vendored
@@ -48,7 +48,7 @@ jobs:
|
||||
git push
|
||||
|
||||
- name: Comment
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
|
||||
2
.github/workflows/docs_preview_deploy.yaml
vendored
2
.github/workflows/docs_preview_deploy.yaml
vendored
@@ -90,7 +90,7 @@ jobs:
|
||||
commit_message: "stage: PR-${{ github.event.number }}: ${{ github.event.head_commit.message }}"
|
||||
|
||||
- name: Comment
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
|
||||
2
.github/workflows/lint.yaml
vendored
2
.github/workflows/lint.yaml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
steps:
|
||||
- name: Remove PR Label
|
||||
if: "${{ github.event.action == 'labeled' && github.event.label.name == 'tests: run' }}"
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
|
||||
2
.github/workflows/tests.yaml
vendored
2
.github/workflows/tests.yaml
vendored
@@ -41,7 +41,7 @@ jobs:
|
||||
steps:
|
||||
- name: Remove PR label
|
||||
if: "${{ github.event.action == 'labeled' && github.event.label.name == 'tests: run' }}"
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
|
||||
59
CHANGELOG.md
59
CHANGELOG.md
@@ -1,5 +1,64 @@
|
||||
# Changelog
|
||||
|
||||
## [0.14.0](https://github.com/googleapis/genai-toolbox/compare/v0.13.0...v0.14.0) (2025-09-05)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **bigquery:** Move `useClientOAuth` config from tool to source ([#1279](https://github.com/googleapis/genai-toolbox/issues/1279)) ([8d20a48](https://github.com/googleapis/genai-toolbox/commit/8d20a48f13bcda853d41bdf80a162de12b076d1b))
|
||||
* **tools/bigquerysql:** remove `useClientOAuth` from tools config ([#1312](https://github.com/googleapis/genai-toolbox/issues/1312))
|
||||
|
||||
### Features
|
||||
|
||||
* **clickhouse:** Add ClickHouse Source and Tools ([#1088](https://github.com/googleapis/genai-toolbox/issues/1088)) ([75a04a5](https://github.com/googleapis/genai-toolbox/commit/75a04a55dd2259bed72fe95119a7a51a906c0b21))
|
||||
* **prebuilt/alloydb-postgres:** Support ipType and IAM users ([#1324](https://github.com/googleapis/genai-toolbox/issues/1324)) ([0b2121e](https://github.com/googleapis/genai-toolbox/commit/0b2121ea72eb81348dcd9c740a62ccd32e71fe37))
|
||||
* **server/mcp:** Support toolbox auth in mcp ([#1140](https://github.com/googleapis/genai-toolbox/issues/1140)) ([ca353e0](https://github.com/googleapis/genai-toolbox/commit/ca353e0b66fedc00e9110df57db18632aef49018))
|
||||
* **source/mysql:** Support `queryParams` in MySQL source ([#1299](https://github.com/googleapis/genai-toolbox/issues/1299)) ([3ae2526](https://github.com/googleapis/genai-toolbox/commit/3ae2526e0fe36b57b05a9b54f1d99f3fc68d9657))
|
||||
* **tools/bigquery:** Support end-user credential passthrough on multiple BQ tools ([#1314](https://github.com/googleapis/genai-toolbox/issues/1314)) ([88f4b30](https://github.com/googleapis/genai-toolbox/commit/88f4b3028df3b6a400936cdf8a035bf55021924c))
|
||||
* **tools/looker:** Add description for looker-get-models tool ([#1266](https://github.com/googleapis/genai-toolbox/issues/1266)) ([89af3a4](https://github.com/googleapis/genai-toolbox/commit/89af3a4ca332f029615b2a739d1f6cd50519638d))
|
||||
* **tools/looker:** Authenticate via end user credentials ([#1257](https://github.com/googleapis/genai-toolbox/issues/1257)) ([8755e3d](https://github.com/googleapis/genai-toolbox/commit/8755e3db3476abb35629b3cca9c78db7366757a4))
|
||||
* **tools/looker:** Report field suggestions to agent ([#1267](https://github.com/googleapis/genai-toolbox/issues/1267)) ([2cad82e](https://github.com/googleapis/genai-toolbox/commit/2cad82e5107566dd6c9b75e34e9976af63af0bb5))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Do not print usage on runtime error ([#1315](https://github.com/googleapis/genai-toolbox/issues/1315)) ([afba7a5](https://github.com/googleapis/genai-toolbox/commit/afba7a57cdd4fe7c1b0741dbf8f8c78b14a68089))
|
||||
* Update env var to allow empty string ([#1260](https://github.com/googleapis/genai-toolbox/issues/1260)) ([03aa9fa](https://github.com/googleapis/genai-toolbox/commit/03aa9fabacda06f860c9f178485126bddb7d5782))
|
||||
* **tools/firestore:** Add document/collection path validation ([#1229](https://github.com/googleapis/genai-toolbox/issues/1229)) ([14c2249](https://github.com/googleapis/genai-toolbox/commit/14c224939a2f9bb349fa00a7d5227877198530c2))
|
||||
* **tools/looker-get-dashboards:** Fix Looker client OAuth check ([#1338](https://github.com/googleapis/genai-toolbox/issues/1338)) ([36225aa](https://github.com/googleapis/genai-toolbox/commit/36225aa6db7f8426ad87930866530fde4e9bf0cd))
|
||||
* **tools/oceanbase:** Fix encoded text with mysql driver ([#1283](https://github.com/googleapis/genai-toolbox/issues/1283)) ([d16f89f](https://github.com/googleapis/genai-toolbox/commit/d16f89fbb6e49c03998f114ef7dc2b584b5e4967)), closes [#1161](https://github.com/googleapis/genai-toolbox/issues/1161)
|
||||
|
||||
## [0.13.0](https://github.com/googleapis/genai-toolbox/compare/v0.12.0...v0.13.0) (2025-08-27)
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **prebuilt/alloydb:** Add bearer token support for alloydb-wait-for-operation ([#1183](https://github.com/googleapis/genai-toolbox/issues/1183))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add capability to set default for environment variable in config ([#1248](https://github.com/googleapis/genai-toolbox/issues/1248)) ([5bcd52e](https://github.com/googleapis/genai-toolbox/commit/5bcd52e7dcd0773ded723585f4abe29d044e1540))
|
||||
* **firebird:** Add Firebird SQL 2.5+ source and tool ([#1011](https://github.com/googleapis/genai-toolbox/issues/1011)) ([4f6b806](https://github.com/googleapis/genai-toolbox/commit/4f6b806de947efc4e12bdb50dff7781aedb7b966))
|
||||
* **oceanbase:** Add Oceanbase source and tool ([#895](https://github.com/googleapis/genai-toolbox/issues/895)) ([6fc4982](https://github.com/googleapis/genai-toolbox/commit/6fc49826d43f46c84028e752ebebddf3d94b3d13))
|
||||
* **server/mcp:** Support `ping` mechanism ([#1178](https://github.com/googleapis/genai-toolbox/issues/1178)) ([5dcc66c](https://github.com/googleapis/genai-toolbox/commit/5dcc66c84fa72c75ec50a9ac5198018212ec2979))
|
||||
* **server:** Fail-fast on environment variable substitution ([#1177](https://github.com/googleapis/genai-toolbox/issues/1177)) ([212aaba](https://github.com/googleapis/genai-toolbox/commit/212aaba74c8b431de8a5f7b9822a0af4afcaaa0e))
|
||||
* **server:** Implement Tool call auth error propagation ([#1235](https://github.com/googleapis/genai-toolbox/issues/1235)) ([b94a021](https://github.com/googleapis/genai-toolbox/commit/b94a021ca11c6637cf8038449483b5e75f2012b3))
|
||||
* **sources/bigquery:** Add support for user-credential passthrough ([#1067](https://github.com/googleapis/genai-toolbox/issues/1067)) ([650e2e2](https://github.com/googleapis/genai-toolbox/commit/650e2e26f51bff75ce66343f64944d0a89a58b69))
|
||||
* **tool/looker:** Add support for `description` field in looker tool ([#1199](https://github.com/googleapis/genai-toolbox/issues/1199)) ([97f0dd2](https://github.com/googleapis/genai-toolbox/commit/97f0dd2acf26caf28ecad65abea8779c196a27f1))
|
||||
* **tools/bigquery-ask-data-insights:** Add bigquery `ask-data-insights` tool ([#932](https://github.com/googleapis/genai-toolbox/issues/932)) ([7651357](https://github.com/googleapis/genai-toolbox/commit/7651357d424a2b6656d8b6818cebc5c8a86ed053))
|
||||
* **tools/bigquery-forecast:** Add bigqueryforecast tool ([#1148](https://github.com/googleapis/genai-toolbox/issues/1148)) ([2ad0ccf](https://github.com/googleapis/genai-toolbox/commit/2ad0ccf83df542340087742468d6762f81eedee6))
|
||||
* **tools/firestore-add-documents:** Add firestore-add-documents tool ([#1107](https://github.com/googleapis/genai-toolbox/issues/1107)) ([ee4a70a](https://github.com/googleapis/genai-toolbox/commit/ee4a70a0e82b346b07b5b4c60dfa060da2273f50))
|
||||
* **tools/firestore-update-document:** Add firestore-update-document tool ([#1191](https://github.com/googleapis/genai-toolbox/issues/1191)) ([0010123](https://github.com/googleapis/genai-toolbox/commit/00101232a39c70288aac5715649c184858d351e3))
|
||||
* **tools/looker:** Control over whether hidden objects are surfaced ([#1222](https://github.com/googleapis/genai-toolbox/issues/1222)) ([bc91559](https://github.com/googleapis/genai-toolbox/commit/bc91559cc4e5b20385b84cc562b624fabf7e47a8))
|
||||
* **trino:** Add Trino source and tools ([#948](https://github.com/googleapis/genai-toolbox/issues/948)) ([7dd123b](https://github.com/googleapis/genai-toolbox/commit/7dd123b3d76b8eb2b74b5d960959c1f90684b37e))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **tools/looker:** Lookergetdashboards uses proper Authorized helper func ([#1255](https://github.com/googleapis/genai-toolbox/issues/1255)) ([00866bc](https://github.com/googleapis/genai-toolbox/commit/00866bc7fc33115c547213e60316ae889735fdbb))
|
||||
* **tools/mongodb-find-one:** ProjectPayload unmarshaling ([#1167](https://github.com/googleapis/genai-toolbox/issues/1167)) ([8ea6a98](https://github.com/googleapis/genai-toolbox/commit/8ea6a98bd9096ba97722e5f807366887e864004f))
|
||||
* **tools/mysql:** Fix encoded text for mysql ([#1161](https://github.com/googleapis/genai-toolbox/issues/1161)) ([a37cfa8](https://github.com/googleapis/genai-toolbox/commit/a37cfa841d151b9995d4fab73cfc5e4d30d2cc57)), closes [#840](https://github.com/googleapis/genai-toolbox/issues/840)
|
||||
|
||||
## [0.12.0](https://github.com/googleapis/genai-toolbox/compare/v0.11.0...v0.12.0) (2025-08-14)
|
||||
|
||||
|
||||
|
||||
@@ -25,33 +25,42 @@ This project follows
|
||||
|
||||
## Contribution process
|
||||
|
||||
### Code reviews
|
||||
> [!NOTE]
|
||||
> New contributions should always include both unit and integration tests.
|
||||
|
||||
|
||||
All submissions, including submissions by project members, require review. We
|
||||
use GitHub pull requests for this purpose. Consult
|
||||
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
|
||||
information on using pull requests.
|
||||
|
||||
Within 2-5 days, a reviewer will review your PR. They may approve it, or request
|
||||
changes. When requesting changes, reviewers should self-assign the PR to ensure
|
||||
### Code reviews
|
||||
|
||||
* Within 2-5 days, a reviewer will review your PR. They may approve it, or request
|
||||
changes.
|
||||
* When requesting changes, reviewers should self-assign the PR to ensure
|
||||
they are aware of any updates.
|
||||
If additional changes are needed, push additional commits to your PR branch -
|
||||
this helps the reviewer know which parts of the PR have changed. Commits will be
|
||||
* If additional changes are needed, push additional commits to your PR branch -
|
||||
this helps the reviewer know which parts of the PR have changed.
|
||||
* Commits will be
|
||||
squashed when merged.
|
||||
Please follow up with changes promptly. If a PR is awaiting changes by the
|
||||
* Please follow up with changes promptly.
|
||||
* If a PR is awaiting changes by the
|
||||
author for more than 10 days, maintainers may mark that PR as Draft. PRs that
|
||||
are inactive for more than 30 days may be closed.
|
||||
|
||||
### Adding a New Database Source and Tool
|
||||
## Adding a New Database Source or Tool
|
||||
|
||||
We recommend creating an
|
||||
Please create an
|
||||
[issue](https://github.com/googleapis/genai-toolbox/issues) before
|
||||
implementation to ensure we can accept the contribution and no duplicated work.
|
||||
If you have any questions, reach out on our
|
||||
[Discord](https://discord.gg/Dmm69peqjh) to chat directly with the team. New
|
||||
contributions should be added with both unit tests and integration tests.
|
||||
implementation to ensure we can accept the contribution and no duplicated work. This issue
|
||||
should include an overview of the API design. If you have any questions, reach out on our
|
||||
[Discord](https://discord.gg/Dmm69peqjh) to chat directly with the team.
|
||||
|
||||
#### 1. Implement the New Data Source
|
||||
> [!NOTE]
|
||||
> New tools can be added for [pre-existing data sources](https://github.com/googleapis/genai-toolbox/tree/main/internal/sources). However, any new database source should also include at least one new tool type.
|
||||
|
||||
### Adding a New Database Source
|
||||
|
||||
We recommend looking at an [example source
|
||||
implementation](https://github.com/googleapis/genai-toolbox/blob/main/internal/sources/postgres/postgres.go).
|
||||
@@ -78,7 +87,10 @@ implementation](https://github.com/googleapis/genai-toolbox/blob/main/internal/s
|
||||
* **Implement `init()`** to register the new Source.
|
||||
* **Implement Unit Tests** in a file named `newdb_test.go`.
|
||||
|
||||
#### 2. Implement the New Tool
|
||||
### Adding a New Tool
|
||||
|
||||
> [!NOTE]
|
||||
> Please follow the tool naming convention detailed [here](./DEVELOPER.md#tool-naming-conventions).
|
||||
|
||||
We recommend looking at an [example tool
|
||||
implementation](https://github.com/googleapis/genai-toolbox/tree/main/internal/tools/postgres/postgressql).
|
||||
@@ -111,7 +123,7 @@ tools.
|
||||
* **Implement `init()`** to register the new Tool.
|
||||
* **Implement Unit Tests** in a file named `newdb_test.go`.
|
||||
|
||||
#### 3. Add Integration Tests
|
||||
### Adding Integration Tests
|
||||
|
||||
* **Add a test file** under a new directory `tests/newdb`.
|
||||
* **Add pre-defined integration test suites** in the
|
||||
@@ -153,7 +165,7 @@ tools.
|
||||
[temp-param-doc]:
|
||||
https://googleapis.github.io/genai-toolbox/resources/tools/#template-parameters
|
||||
|
||||
#### 4. Add Documentation
|
||||
### Adding Documentation
|
||||
|
||||
* **Update the documentation** to include information about your new data source
|
||||
and tool. This includes:
|
||||
@@ -163,7 +175,7 @@ tools.
|
||||
|
||||
* **(Optional) Add samples** to the `docs/en/samples/<newdb>` directory.
|
||||
|
||||
#### (Optional) 5. Add Prebuilt Tools
|
||||
### (Optional) Adding Prebuilt Tools
|
||||
|
||||
You can provide developers with a set of "build-time" tools to aid common
|
||||
software development user journeys like viewing and creating tables/collections
|
||||
@@ -177,7 +189,7 @@ and data.
|
||||
[internal/prebuiltconfigs/prebuiltconfigs_test.go](internal/prebuiltconfigs/prebuiltconfigs_test.go)
|
||||
and [cmd/root_test.go](cmd/root_test.go).
|
||||
|
||||
#### 6. Submit a Pull Request
|
||||
## Submitting a Pull Request
|
||||
|
||||
Submit a pull request to the repository with your changes. Be sure to include a
|
||||
detailed description of your changes and any requests for long term testing
|
||||
@@ -218,4 +230,4 @@ resources.
|
||||
* **PR Description:** PR description should **always** be included. It should
|
||||
include a concise description of the changes, it's impact, along with a
|
||||
summary of the solution. If the PR is related to a specific issue, the issue
|
||||
number should be mentioned in the PR description (e.g. `Fixes #1`).
|
||||
number should be mentioned in the PR description (e.g. `Fixes #1`).
|
||||
|
||||
41
DEVELOPER.md
41
DEVELOPER.md
@@ -44,6 +44,47 @@ Before you begin, ensure you have the following:
|
||||
curl http://127.0.0.1:5000
|
||||
```
|
||||
|
||||
### Tool Naming Conventions
|
||||
|
||||
This section details the purpose and conventions for MCP Toolbox's tools naming
|
||||
properties, **tool name** and **tool kind**.
|
||||
|
||||
```
|
||||
cancel_hotel: <- tool name
|
||||
kind: postgres-sql <- tool kind
|
||||
source: my_pg_source
|
||||
```
|
||||
|
||||
#### Tool Name
|
||||
|
||||
Tool name is the identifier used by a Large Language Model (LLM) to invoke a
|
||||
specific tool.
|
||||
* Custom tools: The user can define any name they want. The below guidelines
|
||||
do not apply.
|
||||
* Pre-built tools: The tool name is predefined and cannot be changed. It
|
||||
should follow the guidelines.
|
||||
|
||||
The following guidelines apply to tool names:
|
||||
* Should use underscores over hyphens (e.g., `list_collections` instead of
|
||||
`list-collections`).
|
||||
* Should not have the product name in the name (e.g., `list_collections` instead
|
||||
of `firestore_list_collections`).
|
||||
* Superficial changes are NOT considered as breaking (e.g., changing tool name).
|
||||
* Non-superficial changes MAY be considered breaking (e.g. adding new parameters
|
||||
to a function) until they can be validated through extensive testing to ensure
|
||||
they do not negatively impact agent's performances.
|
||||
|
||||
#### Tool Kind
|
||||
|
||||
Tool kind serves as a category or type that a user can assign to a tool.
|
||||
|
||||
The following guidelines apply to tool kinds:
|
||||
* Should user hyphens over underscores (e.g. `firestore-list-collections` or
|
||||
`firestore_list_colelctions`).
|
||||
* Should use product name in name (e.g. `firestore-list-collections` over
|
||||
`list-collections`).
|
||||
* Changes to tool kind are breaking changes and should be avoided.
|
||||
|
||||
## Testing
|
||||
|
||||
### Infrastructure
|
||||
|
||||
61
README.md
61
README.md
@@ -117,7 +117,7 @@ To install Toolbox as a binary:
|
||||
<!-- {x-release-please-start-version} -->
|
||||
```sh
|
||||
# see releases page for other versions
|
||||
export VERSION=0.12.0
|
||||
export VERSION=0.14.0
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v$VERSION/linux/amd64/toolbox
|
||||
chmod +x toolbox
|
||||
```
|
||||
@@ -130,7 +130,7 @@ You can also install Toolbox as a container:
|
||||
|
||||
```sh
|
||||
# see releases page for other versions
|
||||
export VERSION=0.12.0
|
||||
export VERSION=0.14.0
|
||||
docker pull us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:$VERSION
|
||||
```
|
||||
|
||||
@@ -154,7 +154,7 @@ To install from source, ensure you have the latest version of
|
||||
[Go installed](https://go.dev/doc/install), and then run the following command:
|
||||
|
||||
```sh
|
||||
go install github.com/googleapis/genai-toolbox@v0.12.0
|
||||
go install github.com/googleapis/genai-toolbox@v0.14.0
|
||||
```
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
@@ -165,22 +165,66 @@ go install github.com/googleapis/genai-toolbox@v0.12.0
|
||||
[Configure](#configuration) a `tools.yaml` to define your tools, and then
|
||||
execute `toolbox` to start the server:
|
||||
|
||||
<details open>
|
||||
<summary>Binary</summary>
|
||||
|
||||
To run Toolbox from binary:
|
||||
|
||||
```sh
|
||||
./toolbox --tools-file "tools.yaml"
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Toolbox enables dynamic reloading by default. To disable, use the
|
||||
> `--disable-reload` flag.
|
||||
ⓘ **NOTE:**
|
||||
Toolbox enables dynamic reloading by default. To disable, use the `--disable-reload` flag.
|
||||
|
||||
#### Homebrew Users
|
||||
</details>
|
||||
|
||||
If you installed Toolbox using Homebrew, the `toolbox` binary is available in your system path. You can start the server with the same command:
|
||||
<details>
|
||||
|
||||
<summary>Container image</summary>
|
||||
|
||||
To run the server after pulling the [container image](#installing-the-server):
|
||||
|
||||
```sh
|
||||
export VERSION=0.11.0 # Use the version you pulled
|
||||
docker run -p 5000:5000 \
|
||||
-v $(pwd)/tools.yaml:/app/tools.yaml \
|
||||
us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:$VERSION \
|
||||
--tools-file "/app/tools.yaml"
|
||||
```
|
||||
|
||||
ⓘ **NOTE:**
|
||||
The `-v` flag mounts your local `tools.yaml` into the container, and `-p` maps the container's port `5000` to your host's port `5000`.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Source</summary>
|
||||
|
||||
To run the server directly from source, navigate to the project root directory and run:
|
||||
|
||||
```sh
|
||||
go run .
|
||||
```
|
||||
|
||||
ⓘ **NOTE:**
|
||||
This command runs the project from source, and is more suitable for development and testing. It does **not** compile a binary into your `$GOPATH`. If you want to compile a binary instead, refer the [Developer Documentation](./DEVELOPER.md#building-the-binary).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Homebrew</summary>
|
||||
|
||||
If you installed Toolbox using [Homebrew](https://brew.sh/), the `toolbox` binary is available in your system path. You can start the server with the same command:
|
||||
|
||||
```sh
|
||||
toolbox --tools-file "tools.yaml"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
You can use `toolbox help` for a full list of flags! To stop the server, send a
|
||||
terminate signal (`ctrl+c` on most platforms).
|
||||
|
||||
@@ -188,6 +232,7 @@ For more detailed documentation on deploying to different environments, check
|
||||
out the resources in the [How-to
|
||||
section](https://googleapis.github.io/genai-toolbox/how-to/)
|
||||
|
||||
|
||||
### Integrating your application
|
||||
|
||||
Once your server is up and running, you can load the tools into your
|
||||
|
||||
26
cmd/root.go
26
cmd/root.go
@@ -43,6 +43,8 @@ import (
|
||||
|
||||
// Import tool packages for side effect of registration
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/alloydbainl"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigqueryanalyzecontribution"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigqueryconversationalanalytics"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigqueryexecutesql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigqueryforecast"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerygetdatasetinfo"
|
||||
@@ -51,6 +53,10 @@ import (
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerylisttableids"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerysql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/bigtable"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/clickhouse/clickhouseexecutesql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/clickhouse/clickhouselistdatabases"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/clickhouse/clickhousesql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/cloudmonitoring"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/couchbase"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/dataplex/dataplexlookupentry"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/dataplex/dataplexsearchaspecttypes"
|
||||
@@ -63,6 +69,7 @@ import (
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/firestore/firestoregetdocuments"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/firestore/firestoregetrules"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/firestore/firestorelistcollections"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/firestore/firestorequery"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/firestore/firestorequerycollection"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/firestore/firestoreupdatedocument"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/firestore/firestorevalidaterules"
|
||||
@@ -94,6 +101,7 @@ import (
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mssql/mssqlexecutesql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mssql/mssqlsql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mysql/mysqlexecutesql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mysql/mysqllisttables"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/mysql/mysqlsql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/neo4j/neo4jcypher"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/neo4j/neo4jexecutecypher"
|
||||
@@ -101,6 +109,7 @@ import (
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/oceanbase/oceanbaseexecutesql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/oceanbase/oceanbasesql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/postgres/postgresexecutesql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/postgres/postgreslisttables"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/postgres/postgressql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/redis"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/spanner/spannerexecutesql"
|
||||
@@ -113,12 +122,17 @@ import (
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/utility/alloydbwaitforoperation"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/utility/wait"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/valkey"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/yugabytedbsql"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/alloydbadmin"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/alloydbpg"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/bigquery"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/bigtable"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/clickhouse"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/cloudmonitoring"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/cloudsqladmin"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/cloudsqlmssql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/cloudsqlmysql"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/cloudsqlpg"
|
||||
@@ -141,6 +155,7 @@ import (
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/tidb"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/trino"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/valkey"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/sources/yugabytedb"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -215,6 +230,9 @@ func NewCommand(opts ...Option) *Command {
|
||||
o(cmd)
|
||||
}
|
||||
|
||||
// Do not print Usage on runtime error
|
||||
cmd.SilenceUsage = true
|
||||
|
||||
// Set server version
|
||||
cmd.cfg.Version = versionString
|
||||
|
||||
@@ -264,8 +282,9 @@ type ToolsFile struct {
|
||||
}
|
||||
|
||||
// parseEnv replaces environment variables ${ENV_NAME} with their values.
|
||||
// also support ${ENV_NAME:default_value}.
|
||||
func parseEnv(input string) (string, error) {
|
||||
re := regexp.MustCompile(`\$\{(\w+)\}`)
|
||||
re := regexp.MustCompile(`\$\{(\w+)(:(\w*))?\}`)
|
||||
|
||||
var err error
|
||||
output := re.ReplaceAllStringFunc(input, func(match string) string {
|
||||
@@ -276,6 +295,9 @@ func parseEnv(input string) (string, error) {
|
||||
if value, found := os.LookupEnv(variableName); found {
|
||||
return value
|
||||
}
|
||||
if parts[2] != "" {
|
||||
return parts[3]
|
||||
}
|
||||
err = fmt.Errorf("environment variable not found: %q", variableName)
|
||||
return ""
|
||||
})
|
||||
@@ -829,7 +851,7 @@ func run(cmd *Command) error {
|
||||
}
|
||||
cmd.logger.InfoContext(ctx, "Server ready to serve!")
|
||||
if cmd.cfg.UI {
|
||||
cmd.logger.InfoContext(ctx, fmt.Sprintf("Toolbox UI is up and running at: http://localhost:%d/ui", cmd.cfg.Port))
|
||||
cmd.logger.InfoContext(ctx, fmt.Sprintf("Toolbox UI is up and running at: http://%s:%d/ui", cmd.cfg.Address, cmd.cfg.Port))
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
||||
102
cmd/root_test.go
102
cmd/root_test.go
@@ -206,6 +206,72 @@ func TestServerConfigFlags(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseEnv(t *testing.T) {
|
||||
tcs := []struct {
|
||||
desc string
|
||||
env map[string]string
|
||||
in string
|
||||
want string
|
||||
err bool
|
||||
errString string
|
||||
}{
|
||||
{
|
||||
desc: "without default without env",
|
||||
in: "${FOO}",
|
||||
want: "",
|
||||
err: true,
|
||||
errString: `environment variable not found: "FOO"`,
|
||||
},
|
||||
{
|
||||
desc: "without default with env",
|
||||
env: map[string]string{
|
||||
"FOO": "bar",
|
||||
},
|
||||
in: "${FOO}",
|
||||
want: "bar",
|
||||
},
|
||||
{
|
||||
desc: "with empty default",
|
||||
in: "${FOO:}",
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
desc: "with default",
|
||||
in: "${FOO:bar}",
|
||||
want: "bar",
|
||||
},
|
||||
{
|
||||
desc: "with default with env",
|
||||
env: map[string]string{
|
||||
"FOO": "hello",
|
||||
},
|
||||
in: "${FOO:bar}",
|
||||
want: "hello",
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.env != nil {
|
||||
for k, v := range tc.env {
|
||||
t.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
got, err := parseEnv(tc.in)
|
||||
if tc.err {
|
||||
if err == nil {
|
||||
t.Fatalf("expected error not found")
|
||||
}
|
||||
if tc.errString != err.Error() {
|
||||
t.Fatalf("incorrect error string: got %s, want %s", err, tc.errString)
|
||||
}
|
||||
}
|
||||
if tc.want != got {
|
||||
t.Fatalf("unexpected want: got %s, want %s", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolFileFlag(t *testing.T) {
|
||||
tcs := []struct {
|
||||
desc string
|
||||
@@ -1166,6 +1232,7 @@ func TestPrebuiltTools(t *testing.T) {
|
||||
alloydb_admin_config, _ := prebuiltconfigs.Get("alloydb-postgres-admin")
|
||||
alloydb_config, _ := prebuiltconfigs.Get("alloydb-postgres")
|
||||
bigquery_config, _ := prebuiltconfigs.Get("bigquery")
|
||||
clickhouse_config, _ := prebuiltconfigs.Get("clickhouse")
|
||||
cloudsqlpg_config, _ := prebuiltconfigs.Get("cloud-sql-postgres")
|
||||
cloudsqlmysql_config, _ := prebuiltconfigs.Get("cloud-sql-mysql")
|
||||
cloudsqlmssql_config, _ := prebuiltconfigs.Get("cloud-sql-mssql")
|
||||
@@ -1177,6 +1244,7 @@ func TestPrebuiltTools(t *testing.T) {
|
||||
postgresconfig, _ := prebuiltconfigs.Get("postgres")
|
||||
spanner_config, _ := prebuiltconfigs.Get("spanner")
|
||||
spannerpg_config, _ := prebuiltconfigs.Get("spanner-postgres")
|
||||
neo4jconfig, _ := prebuiltconfigs.Get("neo4j")
|
||||
|
||||
// Set environment variables
|
||||
t.Setenv("API_KEY", "your_api_key")
|
||||
@@ -1198,6 +1266,13 @@ func TestPrebuiltTools(t *testing.T) {
|
||||
t.Setenv("ALLOYDB_POSTGRES_USER", "your_alloydb_user")
|
||||
t.Setenv("ALLOYDB_POSTGRES_PASSWORD", "your_alloydb_password")
|
||||
|
||||
t.Setenv("CLICKHOUSE_PROTOCOL", "your_clickhouse_protocol")
|
||||
t.Setenv("CLICKHOUSE_DATABASE", "your_clickhouse_database")
|
||||
t.Setenv("CLICKHOUSE_PASSWORD", "your_clickhouse_password")
|
||||
t.Setenv("CLICKHOUSE_USER", "your_clickhouse_user")
|
||||
t.Setenv("CLICKHOUSE_HOST", "your_clickhosue_host")
|
||||
t.Setenv("CLICKHOUSE_PORT", "8123")
|
||||
|
||||
t.Setenv("CLOUD_SQL_POSTGRES_PROJECT", "your_pg_project")
|
||||
t.Setenv("CLOUD_SQL_POSTGRES_INSTANCE", "your_pg_instance")
|
||||
t.Setenv("CLOUD_SQL_POSTGRES_DATABASE", "your_pg_db")
|
||||
@@ -1244,6 +1319,11 @@ func TestPrebuiltTools(t *testing.T) {
|
||||
t.Setenv("LOOKER_CLIENT_SECRET", "your_looker_client_secret")
|
||||
t.Setenv("LOOKER_VERIFY_SSL", "true")
|
||||
|
||||
t.Setenv("NEO4J_URI", "bolt://localhost:7687")
|
||||
t.Setenv("NEO4J_DATABASE", "neo4j")
|
||||
t.Setenv("NEO4J_USERNAME", "your_neo4j_user")
|
||||
t.Setenv("NEO4J_PASSWORD", "your_neo4j_password")
|
||||
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
@@ -1279,7 +1359,17 @@ func TestPrebuiltTools(t *testing.T) {
|
||||
wantToolset: server.ToolsetConfigs{
|
||||
"bigquery-database-tools": tools.ToolsetConfig{
|
||||
Name: "bigquery-database-tools",
|
||||
ToolNames: []string{"execute_sql", "forecast", "get_dataset_info", "get_table_info", "list_dataset_ids", "list_table_ids"},
|
||||
ToolNames: []string{"analyze_contribution", "ask_data_insights", "execute_sql", "forecast", "get_dataset_info", "get_table_info", "list_dataset_ids", "list_table_ids"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "clickhouse prebuilt tools",
|
||||
in: clickhouse_config,
|
||||
wantToolset: server.ToolsetConfigs{
|
||||
"clickhouse-database-tools": tools.ToolsetConfig{
|
||||
Name: "clickhouse-database-tools",
|
||||
ToolNames: []string{"execute_sql", "list_databases"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1393,6 +1483,16 @@ func TestPrebuiltTools(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "neo4j prebuilt tools",
|
||||
in: neo4jconfig,
|
||||
wantToolset: server.ToolsetConfigs{
|
||||
"neo4j-database-tools": tools.ToolsetConfig{
|
||||
Name: "neo4j-database-tools",
|
||||
ToolNames: []string{"execute_cypher", "get_schema"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.12.0
|
||||
0.14.0
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"version = \"0.12.0\" # x-release-please-version\n",
|
||||
"version = \"0.14.0\" # x-release-please-version\n",
|
||||
"! curl -O https://storage.googleapis.com/genai-toolbox/v{version}/linux/amd64/toolbox\n",
|
||||
"\n",
|
||||
"# Make the binary executable\n",
|
||||
|
||||
@@ -22,6 +22,11 @@ etc., you could use environment variables instead with the format `${ENV_NAME}`.
|
||||
user: ${USER_NAME}
|
||||
password: ${PASSWORD}
|
||||
```
|
||||
A default value can be specified like `${ENV_NAME:default}`.
|
||||
|
||||
```yaml
|
||||
port: ${DB_PORT:3306}
|
||||
```
|
||||
|
||||
### Sources
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ To install Toolbox as a binary:
|
||||
|
||||
```sh
|
||||
# see releases page for other versions
|
||||
export VERSION=0.12.0
|
||||
export VERSION=0.14.0
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v$VERSION/linux/amd64/toolbox
|
||||
chmod +x toolbox
|
||||
```
|
||||
@@ -97,7 +97,7 @@ You can also install Toolbox as a container:
|
||||
|
||||
```sh
|
||||
# see releases page for other versions
|
||||
export VERSION=0.12.0
|
||||
export VERSION=0.14.0
|
||||
docker pull us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:$VERSION
|
||||
```
|
||||
|
||||
@@ -115,7 +115,7 @@ To install from source, ensure you have the latest version of
|
||||
[Go installed](https://go.dev/doc/install), and then run the following command:
|
||||
|
||||
```sh
|
||||
go install github.com/googleapis/genai-toolbox@v0.12.0
|
||||
go install github.com/googleapis/genai-toolbox@v0.14.0
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
|
||||
@@ -94,305 +94,23 @@ pip install google-genai
|
||||
code to create an agent:
|
||||
{{< tabpane persist=header >}}
|
||||
{{< tab header="ADK" lang="python" >}}
|
||||
from google.adk.agents import Agent
|
||||
from google.adk.runners import Runner
|
||||
from google.adk.sessions import InMemorySessionService
|
||||
from google.adk.artifacts.in_memory_artifact_service import InMemoryArtifactService
|
||||
from google.genai import types
|
||||
from toolbox_core import ToolboxSyncClient
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
{{< include "quickstart/python/adk/quickstart.py" >}}
|
||||
|
||||
# TODO(developer): replace this with your Google API key
|
||||
|
||||
os.environ['GOOGLE_API_KEY'] = 'your-api-key'
|
||||
|
||||
async def main():
|
||||
with ToolboxSyncClient("<http://127.0.0.1:5000>") as toolbox_client:
|
||||
|
||||
prompt = """
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking and
|
||||
cancellations. When the user searches for a hotel, mention it's name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
"""
|
||||
|
||||
root_agent = Agent(
|
||||
model='gemini-2.0-flash-001',
|
||||
name='hotel_agent',
|
||||
description='A helpful AI assistant.',
|
||||
instruction=prompt,
|
||||
tools=toolbox_client.load_toolset("my-toolset"),
|
||||
)
|
||||
|
||||
session_service = InMemorySessionService()
|
||||
artifacts_service = InMemoryArtifactService()
|
||||
session = await session_service.create_session(
|
||||
state={}, app_name='hotel_agent', user_id='123'
|
||||
)
|
||||
runner = Runner(
|
||||
app_name='hotel_agent',
|
||||
agent=root_agent,
|
||||
artifact_service=artifacts_service,
|
||||
session_service=session_service,
|
||||
)
|
||||
|
||||
queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
]
|
||||
|
||||
for query in queries:
|
||||
content = types.Content(role='user', parts=[types.Part(text=query)])
|
||||
events = runner.run(session_id=session.id,
|
||||
user_id='123', new_message=content)
|
||||
|
||||
responses = (
|
||||
part.text
|
||||
for event in events
|
||||
for part in event.content.parts
|
||||
if part.text is not None
|
||||
)
|
||||
|
||||
for text in responses:
|
||||
print(text)
|
||||
|
||||
asyncio.run(main())
|
||||
{{< /tab >}}
|
||||
{{< tab header="LangChain" lang="python" >}}
|
||||
import asyncio
|
||||
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
{{< include "quickstart/python/langchain/quickstart.py" >}}
|
||||
|
||||
# TODO(developer): replace this with another import if needed
|
||||
|
||||
from langchain_google_vertexai import ChatVertexAI
|
||||
|
||||
# from langchain_google_genai import ChatGoogleGenerativeAI
|
||||
|
||||
# from langchain_anthropic import ChatAnthropic
|
||||
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
|
||||
from toolbox_langchain import ToolboxClient
|
||||
|
||||
prompt = """
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking and
|
||||
cancellations. When the user searches for a hotel, mention it's name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
"""
|
||||
|
||||
queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
]
|
||||
|
||||
async def run_application():
|
||||
# TODO(developer): replace this with another model if needed
|
||||
model = ChatVertexAI(model_name="gemini-2.0-flash-001")
|
||||
# model = ChatGoogleGenerativeAI(model="gemini-2.0-flash-001")
|
||||
# model = ChatAnthropic(model="claude-3-5-sonnet-20240620")
|
||||
|
||||
# Load the tools from the Toolbox server
|
||||
async with ToolboxClient("http://127.0.0.1:5000") as client:
|
||||
tools = await client.aload_toolset()
|
||||
|
||||
agent = create_react_agent(model, tools, checkpointer=MemorySaver())
|
||||
|
||||
config = {"configurable": {"thread_id": "thread-1"}}
|
||||
for query in queries:
|
||||
inputs = {"messages": [("user", prompt + query)]}
|
||||
response = agent.invoke(inputs, stream_mode="values", config=config)
|
||||
print(response["messages"][-1].content)
|
||||
|
||||
asyncio.run(run_application())
|
||||
{{< /tab >}}
|
||||
{{< tab header="LlamaIndex" lang="python" >}}
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from llama_index.core.agent.workflow import AgentWorkflow
|
||||
{{< include "quickstart/python/llamaindex/quickstart.py" >}}
|
||||
|
||||
from llama_index.core.workflow import Context
|
||||
|
||||
# TODO(developer): replace this with another import if needed
|
||||
|
||||
from llama_index.llms.google_genai import GoogleGenAI
|
||||
|
||||
# from llama_index.llms.anthropic import Anthropic
|
||||
|
||||
from toolbox_llamaindex import ToolboxClient
|
||||
|
||||
prompt = """
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking and
|
||||
cancellations. When the user searches for a hotel, mention it's name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
"""
|
||||
|
||||
queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
]
|
||||
|
||||
async def run_application():
|
||||
# TODO(developer): replace this with another model if needed
|
||||
llm = GoogleGenAI(
|
||||
model="gemini-2.0-flash-001",
|
||||
vertexai_config={"project": "project-id", "location": "us-central1"},
|
||||
)
|
||||
# llm = GoogleGenAI(
|
||||
# api_key=os.getenv("GOOGLE_API_KEY"),
|
||||
# model="gemini-2.0-flash-001",
|
||||
# )
|
||||
# llm = Anthropic(
|
||||
# model="claude-3-7-sonnet-latest",
|
||||
# api_key=os.getenv("ANTHROPIC_API_KEY")
|
||||
# )
|
||||
|
||||
# Load the tools from the Toolbox server
|
||||
async with ToolboxClient("http://127.0.0.1:5000") as client:
|
||||
tools = await client.aload_toolset()
|
||||
|
||||
agent = AgentWorkflow.from_tools_or_functions(
|
||||
tools,
|
||||
llm=llm,
|
||||
system_prompt=prompt,
|
||||
)
|
||||
ctx = Context(agent)
|
||||
for query in queries:
|
||||
response = await agent.run(user_msg=query, ctx=ctx)
|
||||
print(f"---- {query} ----")
|
||||
print(str(response))
|
||||
|
||||
asyncio.run(run_application())
|
||||
{{< /tab >}}
|
||||
{{< tab header="Core" lang="python" >}}
|
||||
import asyncio
|
||||
|
||||
from google import genai
|
||||
from google.genai.types import (
|
||||
Content,
|
||||
FunctionDeclaration,
|
||||
GenerateContentConfig,
|
||||
Part,
|
||||
Tool,
|
||||
)
|
||||
|
||||
from toolbox_core import ToolboxClient
|
||||
|
||||
prompt = """
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking and
|
||||
cancellations. When the user searches for a hotel, mention it's name, id,
|
||||
location and price tier. Always mention hotel id while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
"""
|
||||
|
||||
queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Please book the hotel Hilton Basel for me.",
|
||||
"This is too expensive. Please cancel it.",
|
||||
"Please book Hyatt Regency for me",
|
||||
"My check in dates for my booking would be from April 10, 2024 to April 19, 2024.",
|
||||
]
|
||||
|
||||
async def run_application():
|
||||
async with ToolboxClient("<http://127.0.0.1:5000>") as toolbox_client:
|
||||
|
||||
# The toolbox_tools list contains Python callables (functions/methods) designed for LLM tool-use
|
||||
# integration. While this example uses Google's genai client, these callables can be adapted for
|
||||
# various function-calling or agent frameworks. For easier integration with supported frameworks
|
||||
# (https://github.com/googleapis/mcp-toolbox-python-sdk/tree/main/packages), use the
|
||||
# provided wrapper packages, which handle framework-specific boilerplate.
|
||||
toolbox_tools = await toolbox_client.load_toolset("my-toolset")
|
||||
genai_client = genai.Client(
|
||||
vertexai=True, project="project-id", location="us-central1"
|
||||
)
|
||||
|
||||
genai_tools = [
|
||||
Tool(
|
||||
function_declarations=[
|
||||
FunctionDeclaration.from_callable_with_api_option(callable=tool)
|
||||
]
|
||||
)
|
||||
for tool in toolbox_tools
|
||||
]
|
||||
history = []
|
||||
for query in queries:
|
||||
user_prompt_content = Content(
|
||||
role="user",
|
||||
parts=[Part.from_text(text=query)],
|
||||
)
|
||||
history.append(user_prompt_content)
|
||||
|
||||
response = genai_client.models.generate_content(
|
||||
model="gemini-2.0-flash-001",
|
||||
contents=history,
|
||||
config=GenerateContentConfig(
|
||||
system_instruction=prompt,
|
||||
tools=genai_tools,
|
||||
),
|
||||
)
|
||||
history.append(response.candidates[0].content)
|
||||
function_response_parts = []
|
||||
for function_call in response.function_calls:
|
||||
fn_name = function_call.name
|
||||
# The tools are sorted alphabetically
|
||||
if fn_name == "search-hotels-by-name":
|
||||
function_result = await toolbox_tools[3](**function_call.args)
|
||||
elif fn_name == "search-hotels-by-location":
|
||||
function_result = await toolbox_tools[2](**function_call.args)
|
||||
elif fn_name == "book-hotel":
|
||||
function_result = await toolbox_tools[0](**function_call.args)
|
||||
elif fn_name == "update-hotel":
|
||||
function_result = await toolbox_tools[4](**function_call.args)
|
||||
elif fn_name == "cancel-hotel":
|
||||
function_result = await toolbox_tools[1](**function_call.args)
|
||||
else:
|
||||
raise ValueError("Function name not present.")
|
||||
function_response = {"result": function_result}
|
||||
function_response_part = Part.from_function_response(
|
||||
name=function_call.name,
|
||||
response=function_response,
|
||||
)
|
||||
function_response_parts.append(function_response_part)
|
||||
|
||||
if function_response_parts:
|
||||
tool_response_content = Content(role="tool", parts=function_response_parts)
|
||||
history.append(tool_response_content)
|
||||
|
||||
response2 = genai_client.models.generate_content(
|
||||
model="gemini-2.0-flash-001",
|
||||
contents=history,
|
||||
config=GenerateContentConfig(
|
||||
tools=genai_tools,
|
||||
),
|
||||
)
|
||||
final_model_response_content = response2.candidates[0].content
|
||||
history.append(final_model_response_content)
|
||||
print(response2.text)
|
||||
|
||||
asyncio.run(run_application())
|
||||
{{< include "quickstart/python/core/quickstart.py" >}}
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabpane >}}
|
||||
|
||||
@@ -49,614 +49,28 @@ from Toolbox.
|
||||
{{< tabpane persist=header >}}
|
||||
{{< tab header="LangChain Go" lang="go" >}}
|
||||
|
||||
package main
|
||||
{{< include "quickstart/go/langchain/quickstart.go" >}}
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"github.com/tmc/langchaingo/llms"
|
||||
"github.com/tmc/langchaingo/llms/googleai"
|
||||
)
|
||||
|
||||
// ConvertToLangchainTool converts a generic core.ToolboxTool into a LangChainGo llms.Tool.
|
||||
func ConvertToLangchainTool(toolboxTool *core.ToolboxTool) llms.Tool {
|
||||
|
||||
// Fetch the tool's input schema
|
||||
inputschema, err := toolboxTool.InputSchema()
|
||||
if err != nil {
|
||||
return llms.Tool{}
|
||||
}
|
||||
|
||||
var paramsSchema map[string]any
|
||||
_ = json.Unmarshal(inputschema, ¶msSchema)
|
||||
|
||||
// Convert into LangChain's llms.Tool
|
||||
return llms.Tool{
|
||||
Type: "function",
|
||||
Function: &llms.FunctionDefinition{
|
||||
Name: toolboxTool.Name(),
|
||||
Description: toolboxTool.Description(),
|
||||
Parameters: paramsSchema,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const systemPrompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`
|
||||
|
||||
var queries = []string{
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the hotel Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it.",
|
||||
"Please book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
}
|
||||
|
||||
func main() {
|
||||
genaiKey := os.Getenv("GOOGLE_API_KEY")
|
||||
toolboxURL := "http://localhost:5000"
|
||||
ctx := context.Background()
|
||||
|
||||
// Initialize the Google AI client (LLM).
|
||||
llm, err := googleai.New(ctx, googleai.WithAPIKey(genaiKey), googleai.WithDefaultModel("gemini-1.5-flash"))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Google AI client: %v", err)
|
||||
}
|
||||
|
||||
// Initialize the MCP Toolbox client.
|
||||
toolboxClient, err := core.NewToolboxClient(toolboxURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tool using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tools: %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
toolsMap := make(map[string]*core.ToolboxTool, len(tools))
|
||||
|
||||
langchainTools := make([]llms.Tool, len(tools))
|
||||
// Convert the loaded ToolboxTools into the format LangChainGo requires.
|
||||
for i, tool := range tools {
|
||||
langchainTools[i] = ConvertToLangchainTool(tool)
|
||||
toolsMap[tool.Name()] = tool
|
||||
}
|
||||
|
||||
// Start the conversation history.
|
||||
messageHistory := []llms.MessageContent{
|
||||
llms.TextParts(llms.ChatMessageTypeSystem, systemPrompt),
|
||||
}
|
||||
|
||||
for _, query := range queries {
|
||||
messageHistory = append(messageHistory, llms.TextParts(llms.ChatMessageTypeHuman, query))
|
||||
|
||||
// Make the first call to the LLM, making it aware of the tool.
|
||||
resp, err := llm.GenerateContent(ctx, messageHistory, llms.WithTools(langchainTools))
|
||||
if err != nil {
|
||||
log.Fatalf("LLM call failed: %v", err)
|
||||
}
|
||||
respChoice := resp.Choices[0]
|
||||
|
||||
assistantResponse := llms.TextParts(llms.ChatMessageTypeAI, respChoice.Content)
|
||||
for _, tc := range respChoice.ToolCalls {
|
||||
assistantResponse.Parts = append(assistantResponse.Parts, tc)
|
||||
}
|
||||
messageHistory = append(messageHistory, assistantResponse)
|
||||
|
||||
// Process each tool call requested by the model.
|
||||
for _, tc := range respChoice.ToolCalls {
|
||||
toolName := tc.FunctionCall.Name
|
||||
tool := toolsMap[toolName]
|
||||
var args map[string]any
|
||||
if err := json.Unmarshal([]byte(tc.FunctionCall.Arguments), &args); err != nil {
|
||||
log.Fatalf("Failed to unmarshal arguments for tool '%s': %v", toolName, err)
|
||||
}
|
||||
toolResult, err := tool.Invoke(ctx, args)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to execute tool '%s': %v", toolName, err)
|
||||
}
|
||||
if toolResult == "" || toolResult == nil {
|
||||
toolResult = "Operation completed successfully with no specific return value."
|
||||
}
|
||||
|
||||
// Create the tool call response message and add it to the history.
|
||||
toolResponse := llms.MessageContent{
|
||||
Role: llms.ChatMessageTypeTool,
|
||||
Parts: []llms.ContentPart{
|
||||
llms.ToolCallResponse{
|
||||
Name: toolName,
|
||||
Content: fmt.Sprintf("%v", toolResult),
|
||||
},
|
||||
},
|
||||
}
|
||||
messageHistory = append(messageHistory, toolResponse)
|
||||
}
|
||||
finalResp, err := llm.GenerateContent(ctx, messageHistory)
|
||||
if err != nil {
|
||||
log.Fatalf("Final LLM call failed after tool execution: %v", err)
|
||||
}
|
||||
|
||||
// Add the final textual response from the LLM to the history
|
||||
messageHistory = append(messageHistory, llms.TextParts(llms.ChatMessageTypeAI, finalResp.Choices[0].Content))
|
||||
|
||||
fmt.Println(finalResp.Choices[0].Content)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="Genkit Go" lang="go" >}}
|
||||
|
||||
package main
|
||||
{{< include "quickstart/go/genkit/quickstart.go" >}}
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/tbgenkit"
|
||||
|
||||
"github.com/firebase/genkit/go/ai"
|
||||
"github.com/firebase/genkit/go/genkit"
|
||||
"github.com/firebase/genkit/go/plugins/googlegenai"
|
||||
)
|
||||
|
||||
const systemPrompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`
|
||||
|
||||
var queries = []string{
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the hotel Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create Toolbox Client
|
||||
toolboxClient, err := core.NewToolboxClient("http://127.0.0.1:5000")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tools using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tools: %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
// Initialize Genkit
|
||||
g, err := genkit.Init(ctx,
|
||||
genkit.WithPlugins(&googlegenai.GoogleAI{}),
|
||||
genkit.WithDefaultModel("googleai/gemini-1.5-flash"),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to init genkit: %v\n", err)
|
||||
}
|
||||
|
||||
// Create a conversation history
|
||||
conversationHistory := []*ai.Message{
|
||||
ai.NewSystemTextMessage(systemPrompt),
|
||||
}
|
||||
|
||||
// Convert your tool to a Genkit tool.
|
||||
genkitTools := make([]ai.Tool, len(tools))
|
||||
for i, tool := range tools {
|
||||
newTool, err := tbgenkit.ToGenkitTool(tool, g)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to convert tool: %v\n", err)
|
||||
}
|
||||
genkitTools[i] = newTool
|
||||
}
|
||||
|
||||
toolRefs := make([]ai.ToolRef, len(genkitTools))
|
||||
|
||||
for i, tool := range genkitTools {
|
||||
toolRefs[i] = tool
|
||||
}
|
||||
|
||||
for _, query := range queries {
|
||||
conversationHistory = append(conversationHistory, ai.NewUserTextMessage(query))
|
||||
response, err := genkit.Generate(ctx, g,
|
||||
ai.WithMessages(conversationHistory...),
|
||||
ai.WithTools(toolRefs...),
|
||||
ai.WithReturnToolRequests(true),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("%v\n", err)
|
||||
}
|
||||
conversationHistory = append(conversationHistory, response.Message)
|
||||
|
||||
parts := []*ai.Part{}
|
||||
|
||||
for _, req := range response.ToolRequests() {
|
||||
tool := genkit.LookupTool(g, req.Name)
|
||||
if tool == nil {
|
||||
log.Fatalf("tool %q not found", req.Name)
|
||||
}
|
||||
|
||||
output, err := tool.RunRaw(ctx, req.Input)
|
||||
if err != nil {
|
||||
log.Fatalf("tool %q execution failed: %v", tool.Name(), err)
|
||||
}
|
||||
|
||||
parts = append(parts,
|
||||
ai.NewToolResponsePart(&ai.ToolResponse{
|
||||
Name: req.Name,
|
||||
Ref: req.Ref,
|
||||
Output: output,
|
||||
}))
|
||||
|
||||
}
|
||||
|
||||
if len(parts) > 0 {
|
||||
resp, err := genkit.Generate(ctx, g,
|
||||
ai.WithMessages(append(response.History(), ai.NewMessage(ai.RoleTool, nil, parts...))...),
|
||||
ai.WithTools(toolRefs...),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println("\n", resp.Text())
|
||||
conversationHistory = append(conversationHistory, resp.Message)
|
||||
} else {
|
||||
fmt.Println("\n", response.Text())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="Go GenAI" lang="go" >}}
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"google.golang.org/genai"
|
||||
)
|
||||
|
||||
// ConvertToGenaiTool translates a ToolboxTool into the genai.FunctionDeclaration format.
|
||||
func ConvertToGenaiTool(toolboxTool *core.ToolboxTool) *genai.Tool {
|
||||
|
||||
inputschema, err := toolboxTool.InputSchema()
|
||||
if err != nil {
|
||||
return &genai.Tool{}
|
||||
}
|
||||
|
||||
var paramsSchema *genai.Schema
|
||||
_ = json.Unmarshal(inputschema, ¶msSchema)
|
||||
// First, create the function declaration.
|
||||
funcDeclaration := &genai.FunctionDeclaration{
|
||||
Name: toolboxTool.Name(),
|
||||
Description: toolboxTool.Description(),
|
||||
Parameters: paramsSchema,
|
||||
}
|
||||
|
||||
// Then, wrap the function declaration in a genai.Tool struct.
|
||||
return &genai.Tool{
|
||||
FunctionDeclarations: []*genai.FunctionDeclaration{funcDeclaration},
|
||||
}
|
||||
}
|
||||
|
||||
func printResponse(resp *genai.GenerateContentResponse) {
|
||||
for _, cand := range resp.Candidates {
|
||||
if cand.Content != nil {
|
||||
for _, part := range cand.Content.Parts {
|
||||
fmt.Println(part.Text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const systemPrompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`
|
||||
|
||||
var queries = []string{
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the hotel Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it.",
|
||||
"Please book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Setup
|
||||
ctx := context.Background()
|
||||
apiKey := os.Getenv("GOOGLE_API_KEY")
|
||||
toolboxURL := "http://localhost:5000"
|
||||
|
||||
// Initialize the Google GenAI client using the explicit ClientConfig.
|
||||
client, err := genai.NewClient(ctx, &genai.ClientConfig{
|
||||
APIKey: apiKey,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Google GenAI client: %v", err)
|
||||
}
|
||||
|
||||
// Initialize the MCP Toolbox client.
|
||||
toolboxClient, err := core.NewToolboxClient(toolboxURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tool using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tools: %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
genAITools := make([]*genai.Tool, len(tools))
|
||||
toolsMap := make(map[string]*core.ToolboxTool, len(tools))
|
||||
|
||||
for i, tool := range tools {
|
||||
genAITools[i] = ConvertToGenaiTool(tool)
|
||||
toolsMap[tool.Name()] = tool
|
||||
}
|
||||
|
||||
// Set up the generative model with the available tool.
|
||||
modelName := "gemini-2.0-flash"
|
||||
|
||||
// Create the initial content prompt for the model.
|
||||
messageHistory := []*genai.Content{
|
||||
genai.NewContentFromText(systemPrompt, genai.RoleUser),
|
||||
}
|
||||
config := &genai.GenerateContentConfig{
|
||||
Tools: genAITools,
|
||||
ToolConfig: &genai.ToolConfig{
|
||||
FunctionCallingConfig: &genai.FunctionCallingConfig{
|
||||
Mode: genai.FunctionCallingConfigModeAny,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, query := range queries {
|
||||
|
||||
messageHistory = append(messageHistory, genai.NewContentFromText(query, genai.RoleUser))
|
||||
|
||||
genContentResp, err := client.Models.GenerateContent(ctx, modelName, messageHistory, config)
|
||||
if err != nil {
|
||||
log.Fatalf("LLM call failed for query '%s': %v", query, err)
|
||||
}
|
||||
|
||||
if len(genContentResp.Candidates) > 0 && genContentResp.Candidates[0].Content != nil {
|
||||
messageHistory = append(messageHistory, genContentResp.Candidates[0].Content)
|
||||
}
|
||||
|
||||
functionCalls := genContentResp.FunctionCalls()
|
||||
|
||||
toolResponseParts := []*genai.Part{}
|
||||
|
||||
for _, fc := range functionCalls {
|
||||
|
||||
toolToInvoke, found := toolsMap[fc.Name]
|
||||
if !found {
|
||||
log.Fatalf("Tool '%s' not found in loaded tools map. Check toolset configuration.", fc.Name)
|
||||
}
|
||||
|
||||
toolResult, invokeErr := toolToInvoke.Invoke(ctx, fc.Args)
|
||||
if invokeErr != nil {
|
||||
log.Fatalf("Failed to execute tool '%s': %v", fc.Name, invokeErr)
|
||||
}
|
||||
|
||||
// Enhanced Tool Result Handling (retained to prevent nil issues)
|
||||
toolResultString := ""
|
||||
if toolResult != nil {
|
||||
jsonBytes, marshalErr := json.Marshal(toolResult)
|
||||
if marshalErr == nil {
|
||||
toolResultString = string(jsonBytes)
|
||||
} else {
|
||||
toolResultString = fmt.Sprintf("%v", toolResult)
|
||||
}
|
||||
}
|
||||
|
||||
responseMap := map[string]any{"result": toolResultString}
|
||||
|
||||
toolResponseParts = append(toolResponseParts, genai.NewPartFromFunctionResponse(fc.Name, responseMap))
|
||||
}
|
||||
// Add all accumulated tool responses for this turn to the message history.
|
||||
toolResponseContent := genai.NewContentFromParts(toolResponseParts, "function")
|
||||
messageHistory = append(messageHistory, toolResponseContent)
|
||||
|
||||
finalResponse, err := client.Models.GenerateContent(ctx, modelName, messageHistory, &genai.GenerateContentConfig{})
|
||||
if err != nil {
|
||||
log.Fatalf("Error calling GenerateContent (with function result): %v", err)
|
||||
}
|
||||
|
||||
printResponse(finalResponse)
|
||||
// Add the final textual response from the LLM to the history
|
||||
if len(finalResponse.Candidates) > 0 && finalResponse.Candidates[0].Content != nil {
|
||||
messageHistory = append(messageHistory, finalResponse.Candidates[0].Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
{{< include "quickstart/go/genAI/quickstart.go" >}}
|
||||
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="OpenAI Go" lang="go" >}}
|
||||
|
||||
package main
|
||||
{{< include "quickstart/go/openAI/quickstart.go" >}}
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"fmt
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
openai "github.com/openai/openai-go"
|
||||
)
|
||||
|
||||
// ConvertToOpenAITool converts a ToolboxTool into the go-openai library's Tool format.
|
||||
func ConvertToOpenAITool(toolboxTool *core.ToolboxTool) openai.ChatCompletionToolParam {
|
||||
// Get the input schema
|
||||
jsonSchemaBytes, err := toolboxTool.InputSchema()
|
||||
if err != nil {
|
||||
return openai.ChatCompletionToolParam{}
|
||||
}
|
||||
|
||||
// Unmarshal the JSON bytes into FunctionParameters
|
||||
var paramsSchema openai.FunctionParameters
|
||||
if err := json.Unmarshal(jsonSchemaBytes, ¶msSchema); err != nil {
|
||||
return openai.ChatCompletionToolParam{}
|
||||
}
|
||||
|
||||
// Create and return the final tool parameter struct.
|
||||
return openai.ChatCompletionToolParam{
|
||||
Function: openai.FunctionDefinitionParam{
|
||||
Name: toolboxTool.Name(),
|
||||
Description: openai.String(toolboxTool.Description()),
|
||||
Parameters: paramsSchema,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const systemPrompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`
|
||||
|
||||
var queries = []string{
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the hotel Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Setup
|
||||
ctx := context.Background()
|
||||
toolboxURL := "http://localhost:5000"
|
||||
openAIClient := openai.NewClient()
|
||||
|
||||
// Initialize the MCP Toolbox client.
|
||||
toolboxClient, err := core.NewToolboxClient(toolboxURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tools using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tool : %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
openAITools := make([]openai.ChatCompletionToolParam, len(tools))
|
||||
toolsMap := make(map[string]*core.ToolboxTool, len(tools))
|
||||
|
||||
for i, tool := range tools {
|
||||
// Convert the Toolbox tool into the openAI FunctionDeclaration format.
|
||||
openAITools[i] = ConvertToOpenAITool(tool)
|
||||
// Add tool to a map for lookup later
|
||||
toolsMap[tool.Name()] = tool
|
||||
|
||||
}
|
||||
|
||||
params := openai.ChatCompletionNewParams{
|
||||
Messages: []openai.ChatCompletionMessageParamUnion{
|
||||
openai.SystemMessage(systemPrompt),
|
||||
},
|
||||
Tools: openAITools,
|
||||
Seed: openai.Int(0),
|
||||
Model: openai.ChatModelGPT4o,
|
||||
}
|
||||
|
||||
for _, query := range queries {
|
||||
|
||||
params.Messages = append(params.Messages, openai.UserMessage(query))
|
||||
|
||||
// Make initial chat completion request
|
||||
completion, err := openAIClient.Chat.Completions.New(ctx, params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
toolCalls := completion.Choices[0].Message.ToolCalls
|
||||
|
||||
// Return early if there are no tool calls
|
||||
if len(toolCalls) == 0 {
|
||||
log.Println("No function call")
|
||||
}
|
||||
|
||||
// If there was a function call, continue the conversation
|
||||
params.Messages = append(params.Messages, completion.Choices[0].Message.ToParam())
|
||||
for _, toolCall := range toolCalls {
|
||||
|
||||
toolName := toolCall.Function.Name
|
||||
toolToInvoke := toolsMap[toolName]
|
||||
|
||||
var args map[string]any
|
||||
err := json.Unmarshal([]byte(toolCall.Function.Arguments), &args)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
result, err := toolToInvoke.Invoke(ctx, args)
|
||||
if err != nil {
|
||||
log.Fatal("Could not invoke tool", err)
|
||||
}
|
||||
|
||||
params.Messages = append(params.Messages, openai.ToolMessage(result.(string), toolCall.ID))
|
||||
}
|
||||
|
||||
completion, err = openAIClient.Chat.Completions.New(ctx, params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
params.Messages = append(params.Messages, openai.AssistantMessage(query))
|
||||
|
||||
fmt.println("\n", completion.Choices[0].Message.Content)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabpane >}}
|
||||
|
||||
@@ -64,384 +64,26 @@ npm install @google/genai
|
||||
{{< tabpane persist=header >}}
|
||||
{{< tab header="LangChain" lang="js" >}}
|
||||
|
||||
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
|
||||
import { ToolboxClient } from "@toolbox-sdk/core";
|
||||
import { tool } from "@langchain/core/tools";
|
||||
import { createReactAgent } from "@langchain/langgraph/prebuilt";
|
||||
import { MemorySaver } from "@langchain/langgraph";
|
||||
|
||||
// Replace it with your API key
|
||||
process.env.GOOGLE_API_KEY = 'your-api-key';
|
||||
|
||||
const prompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`;
|
||||
|
||||
const queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
];
|
||||
|
||||
async function runApplication() {
|
||||
const model = new ChatGoogleGenerativeAI({
|
||||
model: "gemini-2.0-flash",
|
||||
});
|
||||
|
||||
const client = new ToolboxClient("http://127.0.0.1:5000");
|
||||
const toolboxTools = await client.loadToolset("my-toolset");
|
||||
|
||||
// Define the basics of the tool: name, description, schema and core logic
|
||||
const getTool = (toolboxTool) => tool(toolboxTool, {
|
||||
name: toolboxTool.getName(),
|
||||
description: toolboxTool.getDescription(),
|
||||
schema: toolboxTool.getParamSchema()
|
||||
});
|
||||
const tools = toolboxTools.map(getTool);
|
||||
|
||||
const agent = createReactAgent({
|
||||
llm: model,
|
||||
tools: tools,
|
||||
checkpointer: new MemorySaver(),
|
||||
systemPrompt: prompt,
|
||||
});
|
||||
|
||||
const langGraphConfig = {
|
||||
configurable: {
|
||||
thread_id: "test-thread",
|
||||
},
|
||||
};
|
||||
|
||||
for (const query of queries) {
|
||||
const agentOutput = await agent.invoke(
|
||||
{
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: query,
|
||||
},
|
||||
],
|
||||
verbose: true,
|
||||
},
|
||||
langGraphConfig
|
||||
);
|
||||
const response = agentOutput.messages[agentOutput.messages.length - 1].content;
|
||||
console.log(response);
|
||||
}
|
||||
}
|
||||
|
||||
runApplication()
|
||||
.catch(console.error)
|
||||
.finally(() => console.log("\nApplication finished."));
|
||||
{{< include "quickstart/js/langchain/quickstart.js" >}}
|
||||
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="GenkitJS" lang="js" >}}
|
||||
|
||||
import { ToolboxClient } from "@toolbox-sdk/core";
|
||||
import { genkit } from "genkit";
|
||||
import { googleAI } from '@genkit-ai/googleai';
|
||||
{{< include "quickstart/js/genkit/quickstart.js" >}}
|
||||
|
||||
// Replace it with your API key
|
||||
process.env.GOOGLE_API_KEY = 'your-api-key';
|
||||
|
||||
const systemPrompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`;
|
||||
|
||||
const queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
];
|
||||
|
||||
async function run() {
|
||||
const toolboxClient = new ToolboxClient("http://127.0.0.1:5000");
|
||||
|
||||
const ai = genkit({
|
||||
plugins: [
|
||||
googleAI({
|
||||
apiKey: process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY
|
||||
})
|
||||
],
|
||||
model: googleAI.model('gemini-2.0-flash'),
|
||||
});
|
||||
|
||||
const toolboxTools = await toolboxClient.loadToolset("my-toolset");
|
||||
const toolMap = Object.fromEntries(
|
||||
toolboxTools.map((tool) => {
|
||||
const definedTool = ai.defineTool(
|
||||
{
|
||||
name: tool.getName(),
|
||||
description: tool.getDescription(),
|
||||
inputSchema: tool.getParamSchema(),
|
||||
},
|
||||
tool
|
||||
);
|
||||
return [tool.getName(), definedTool];
|
||||
})
|
||||
);
|
||||
const tools = Object.values(toolMap);
|
||||
|
||||
let conversationHistory = [{ role: "system", content: [{ text: systemPrompt }] }];
|
||||
|
||||
for (const query of queries) {
|
||||
conversationHistory.push({ role: "user", content: [{ text: query }] });
|
||||
const response = await ai.generate({
|
||||
messages: conversationHistory,
|
||||
tools: tools,
|
||||
});
|
||||
conversationHistory.push(response.message);
|
||||
|
||||
const toolRequests = response.toolRequests;
|
||||
if (toolRequests?.length > 0) {
|
||||
// Execute tools concurrently and collect their responses.
|
||||
const toolResponses = await Promise.all(
|
||||
toolRequests.map(async (call) => {
|
||||
try {
|
||||
const toolOutput = await toolMap[call.name].invoke(call.input);
|
||||
return { role: "tool", content: [{ toolResponse: { name: call.name, output: toolOutput } }] };
|
||||
} catch (e) {
|
||||
console.error(`Error executing tool ${call.name}:`, e);
|
||||
return { role: "tool", content: [{ toolResponse: { name: call.name, output: { error: e.message } } }] };
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
conversationHistory.push(...toolResponses);
|
||||
|
||||
// Call the AI again with the tool results.
|
||||
response = await ai.generate({ messages: conversationHistory, tools });
|
||||
conversationHistory.push(response.message);
|
||||
}
|
||||
|
||||
console.log(response.text);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="LlamaIndex" lang="js" >}}
|
||||
|
||||
import { gemini, GEMINI_MODEL } from "@llamaindex/google";
|
||||
import { agent } from "@llamaindex/workflow";
|
||||
import { createMemory, staticBlock, tool } from "llamaindex";
|
||||
import { ToolboxClient } from "@toolbox-sdk/core";
|
||||
|
||||
const TOOLBOX_URL = "http://127.0.0.1:5000"; // Update if needed
|
||||
process.env.GOOGLE_API_KEY = 'your-api-key'; // Replace it with your API key
|
||||
|
||||
const prompt = `
|
||||
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking and cancellations.
|
||||
When the user searches for a hotel, mention its name, id, location and price tier.
|
||||
Always mention hotel ids while performing any searches — this is very important for operations.
|
||||
For any bookings or cancellations, please provide the appropriate confirmation.
|
||||
Update check-in or check-out dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
|
||||
`;
|
||||
|
||||
const queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
];
|
||||
|
||||
async function main() {
|
||||
// Connect to MCP Toolbox
|
||||
const client = new ToolboxClient(TOOLBOX_URL);
|
||||
const toolboxTools = await client.loadToolset("my-toolset");
|
||||
const tools = toolboxTools.map((toolboxTool) => {
|
||||
return tool({
|
||||
name: toolboxTool.getName(),
|
||||
description: toolboxTool.getDescription(),
|
||||
parameters: toolboxTool.getParamSchema(),
|
||||
execute: toolboxTool,
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize LLM
|
||||
const llm = gemini({
|
||||
model: GEMINI_MODEL.GEMINI_2_0_FLASH,
|
||||
apiKey: process.env.GOOGLE_API_KEY,
|
||||
});
|
||||
|
||||
const memory = createMemory({
|
||||
memoryBlocks: [
|
||||
staticBlock({
|
||||
content: prompt,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
// Create the Agent
|
||||
const myAgent = agent({
|
||||
tools: tools,
|
||||
llm,
|
||||
memory,
|
||||
systemPrompt: prompt,
|
||||
});
|
||||
|
||||
for (const query of queries) {
|
||||
const result = await myAgent.run(query);
|
||||
const output = result.data.result;
|
||||
|
||||
console.log(`\nUser: ${query}`);
|
||||
if (typeof output === "string") {
|
||||
console.log(output.trim());
|
||||
} else if (typeof output === "object" && "text" in output) {
|
||||
console.log(output.text.trim());
|
||||
} else {
|
||||
console.log(JSON.stringify(output));
|
||||
}
|
||||
}
|
||||
//You may observe some extra logs during execution due to the run method provided by Llama.
|
||||
console.log("Agent run finished.");
|
||||
}
|
||||
|
||||
main();
|
||||
{{< include "quickstart/js/llamaindex/quickstart.js" >}}
|
||||
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="GoogleGenAI" lang="js" >}}
|
||||
import { GoogleGenAI } from "@google/genai";
|
||||
import { ToolboxClient } from "@toolbox-sdk/core";
|
||||
|
||||
{{< include "quickstart/js/genAI/quickstart.js" >}}
|
||||
|
||||
const TOOLBOX_URL = "http://127.0.0.1:5000"; // Update if needed
|
||||
const GOOGLE_API_KEY = 'enter your api here'; // Replace it with your API key
|
||||
|
||||
const prompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, you MUST use the available tools to find information. Mention its name, id,
|
||||
location and price tier. Always mention hotel id while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`;
|
||||
|
||||
const queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
];
|
||||
|
||||
function mapZodTypeToOpenAPIType(zodTypeName) {
|
||||
|
||||
console.log(zodTypeName)
|
||||
const typeMap = {
|
||||
'ZodString': 'string',
|
||||
'ZodNumber': 'number',
|
||||
'ZodBoolean': 'boolean',
|
||||
'ZodArray': 'array',
|
||||
'ZodObject': 'object',
|
||||
};
|
||||
return typeMap[zodTypeName] || 'string';
|
||||
}
|
||||
|
||||
async function runApplication() {
|
||||
|
||||
const toolboxClient = new ToolboxClient(TOOLBOX_URL);
|
||||
const toolboxTools = await toolboxClient.loadToolset("my-toolset");
|
||||
|
||||
const geminiTools = [{
|
||||
functionDeclarations: toolboxTools.map(tool => {
|
||||
|
||||
const schema = tool.getParamSchema();
|
||||
const properties = {};
|
||||
const required = [];
|
||||
|
||||
|
||||
for (const [key, param] of Object.entries(schema.shape)) {
|
||||
properties[key] = {
|
||||
type: mapZodTypeToOpenAPIType(param.constructor.name),
|
||||
description: param.description || '',
|
||||
};
|
||||
required.push(key)
|
||||
}
|
||||
|
||||
return {
|
||||
name: tool.getName(),
|
||||
description: tool.getDescription(),
|
||||
parameters: { type: 'object', properties, required },
|
||||
};
|
||||
})
|
||||
}];
|
||||
|
||||
|
||||
const genAI = new GoogleGenAI({ apiKey: GOOGLE_API_KEY });
|
||||
|
||||
const chat = genAI.chats.create({
|
||||
model: "gemini-2.5-flash",
|
||||
config: {
|
||||
systemInstruction: prompt,
|
||||
tools: geminiTools,
|
||||
}
|
||||
});
|
||||
|
||||
for (const query of queries) {
|
||||
|
||||
let currentResult = await chat.sendMessage({ message: query });
|
||||
|
||||
let finalResponseGiven = false
|
||||
while (!finalResponseGiven) {
|
||||
|
||||
const response = currentResult;
|
||||
const functionCalls = response.functionCalls || [];
|
||||
|
||||
if (functionCalls.length === 0) {
|
||||
console.log(response.text)
|
||||
finalResponseGiven = true;
|
||||
} else {
|
||||
const toolResponses = [];
|
||||
for (const call of functionCalls) {
|
||||
const toolName = call.name
|
||||
const toolToExecute = toolboxTools.find(t => t.getName() === toolName);
|
||||
|
||||
if (toolToExecute) {
|
||||
try {
|
||||
const functionResult = await toolToExecute(call.args);
|
||||
toolResponses.push({
|
||||
functionResponse: { name: call.name, response: { result: functionResult } }
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error executing tool '${toolName}':`, e);
|
||||
toolResponses.push({
|
||||
functionResponse: { name: call.name, response: { error: e.message } }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentResult = await chat.sendMessage({ message: toolResponses });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
runApplication()
|
||||
.catch(console.error)
|
||||
.finally(() => console.log("\nApplication finished."));
|
||||
{{< /tab >}}
|
||||
|
||||
{{< /tabpane >}}
|
||||
|
||||
@@ -105,7 +105,7 @@ In this section, we will download Toolbox, configure our tools in a
|
||||
<!-- {x-release-please-start-version} -->
|
||||
```bash
|
||||
export OS="linux/amd64" # one of linux/amd64, darwin/arm64, darwin/amd64, or windows/amd64
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/$OS/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/$OS/toolbox
|
||||
```
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
|
||||
37
docs/en/getting-started/quickstart/go/genAI/go.mod
Normal file
37
docs/en/getting-started/quickstart/go/genAI/go.mod
Normal file
@@ -0,0 +1,37 @@
|
||||
module genai-quickstart
|
||||
|
||||
go 1.24.6
|
||||
|
||||
require (
|
||||
github.com/googleapis/mcp-toolbox-sdk-go v0.3.0
|
||||
google.golang.org/genai v1.23.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.121.1 // indirect
|
||||
cloud.google.com/go/auth v0.16.2 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.7.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||
golang.org/x/crypto v0.39.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
google.golang.org/api v0.242.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/grpc v1.73.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
)
|
||||
174
docs/en/getting-started/quickstart/go/genAI/quickstart.go
Normal file
174
docs/en/getting-started/quickstart/go/genAI/quickstart.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"google.golang.org/genai"
|
||||
)
|
||||
|
||||
// ConvertToGenaiTool translates a ToolboxTool into the genai.FunctionDeclaration format.
|
||||
func ConvertToGenaiTool(toolboxTool *core.ToolboxTool) *genai.Tool {
|
||||
|
||||
inputschema, err := toolboxTool.InputSchema()
|
||||
if err != nil {
|
||||
return &genai.Tool{}
|
||||
}
|
||||
|
||||
var paramsSchema *genai.Schema
|
||||
_ = json.Unmarshal(inputschema, ¶msSchema)
|
||||
// First, create the function declaration.
|
||||
funcDeclaration := &genai.FunctionDeclaration{
|
||||
Name: toolboxTool.Name(),
|
||||
Description: toolboxTool.Description(),
|
||||
Parameters: paramsSchema,
|
||||
}
|
||||
|
||||
// Then, wrap the function declaration in a genai.Tool struct.
|
||||
return &genai.Tool{
|
||||
FunctionDeclarations: []*genai.FunctionDeclaration{funcDeclaration},
|
||||
}
|
||||
}
|
||||
|
||||
func printResponse(resp *genai.GenerateContentResponse) {
|
||||
for _, cand := range resp.Candidates {
|
||||
if cand.Content != nil {
|
||||
for _, part := range cand.Content.Parts {
|
||||
fmt.Println(part.Text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const systemPrompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`
|
||||
|
||||
var queries = []string{
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the hotel Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it.",
|
||||
"Please book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Setup
|
||||
ctx := context.Background()
|
||||
apiKey := os.Getenv("GOOGLE_API_KEY")
|
||||
toolboxURL := "http://localhost:5000"
|
||||
|
||||
// Initialize the Google GenAI client using the explicit ClientConfig.
|
||||
client, err := genai.NewClient(ctx, &genai.ClientConfig{
|
||||
APIKey: apiKey,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Google GenAI client: %v", err)
|
||||
}
|
||||
|
||||
// Initialize the MCP Toolbox client.
|
||||
toolboxClient, err := core.NewToolboxClient(toolboxURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tool using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tools: %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
genAITools := make([]*genai.Tool, len(tools))
|
||||
toolsMap := make(map[string]*core.ToolboxTool, len(tools))
|
||||
|
||||
for i, tool := range tools {
|
||||
genAITools[i] = ConvertToGenaiTool(tool)
|
||||
toolsMap[tool.Name()] = tool
|
||||
}
|
||||
|
||||
// Set up the generative model with the available tool.
|
||||
modelName := "gemini-2.0-flash"
|
||||
|
||||
// Create the initial content prompt for the model.
|
||||
messageHistory := []*genai.Content{
|
||||
genai.NewContentFromText(systemPrompt, genai.RoleUser),
|
||||
}
|
||||
config := &genai.GenerateContentConfig{
|
||||
Tools: genAITools,
|
||||
ToolConfig: &genai.ToolConfig{
|
||||
FunctionCallingConfig: &genai.FunctionCallingConfig{
|
||||
Mode: genai.FunctionCallingConfigModeAny,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, query := range queries {
|
||||
|
||||
messageHistory = append(messageHistory, genai.NewContentFromText(query, genai.RoleUser))
|
||||
|
||||
genContentResp, err := client.Models.GenerateContent(ctx, modelName, messageHistory, config)
|
||||
if err != nil {
|
||||
log.Fatalf("LLM call failed for query '%s': %v", query, err)
|
||||
}
|
||||
|
||||
if len(genContentResp.Candidates) > 0 && genContentResp.Candidates[0].Content != nil {
|
||||
messageHistory = append(messageHistory, genContentResp.Candidates[0].Content)
|
||||
}
|
||||
|
||||
functionCalls := genContentResp.FunctionCalls()
|
||||
|
||||
toolResponseParts := []*genai.Part{}
|
||||
|
||||
for _, fc := range functionCalls {
|
||||
|
||||
toolToInvoke, found := toolsMap[fc.Name]
|
||||
if !found {
|
||||
log.Fatalf("Tool '%s' not found in loaded tools map. Check toolset configuration.", fc.Name)
|
||||
}
|
||||
|
||||
toolResult, invokeErr := toolToInvoke.Invoke(ctx, fc.Args)
|
||||
if invokeErr != nil {
|
||||
log.Fatalf("Failed to execute tool '%s': %v", fc.Name, invokeErr)
|
||||
}
|
||||
|
||||
// Enhanced Tool Result Handling (retained to prevent nil issues)
|
||||
toolResultString := ""
|
||||
if toolResult != nil {
|
||||
jsonBytes, marshalErr := json.Marshal(toolResult)
|
||||
if marshalErr == nil {
|
||||
toolResultString = string(jsonBytes)
|
||||
} else {
|
||||
toolResultString = fmt.Sprintf("%v", toolResult)
|
||||
}
|
||||
}
|
||||
|
||||
responseMap := map[string]any{"result": toolResultString}
|
||||
|
||||
toolResponseParts = append(toolResponseParts, genai.NewPartFromFunctionResponse(fc.Name, responseMap))
|
||||
}
|
||||
// Add all accumulated tool responses for this turn to the message history.
|
||||
toolResponseContent := genai.NewContentFromParts(toolResponseParts, "function")
|
||||
messageHistory = append(messageHistory, toolResponseContent)
|
||||
|
||||
finalResponse, err := client.Models.GenerateContent(ctx, modelName, messageHistory, &genai.GenerateContentConfig{})
|
||||
if err != nil {
|
||||
log.Fatalf("Error calling GenerateContent (with function result): %v", err)
|
||||
}
|
||||
|
||||
printResponse(finalResponse)
|
||||
// Add the final textual response from the LLM to the history
|
||||
if len(finalResponse.Candidates) > 0 && finalResponse.Candidates[0].Content != nil {
|
||||
messageHistory = append(messageHistory, finalResponse.Candidates[0].Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
52
docs/en/getting-started/quickstart/go/genkit/go.mod
Normal file
52
docs/en/getting-started/quickstart/go/genkit/go.mod
Normal file
@@ -0,0 +1,52 @@
|
||||
module genkit-quickstart
|
||||
|
||||
go 1.24.6
|
||||
|
||||
require (
|
||||
github.com/firebase/genkit/go v0.6.2
|
||||
github.com/googleapis/mcp-toolbox-sdk-go v0.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.121.1 // indirect
|
||||
cloud.google.com/go/auth v0.16.2 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.7.0 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/goccy/go-yaml v1.17.1 // indirect
|
||||
github.com/google/dotprompt/go v0.0.0-20250611200215-bb73406b05ca // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/invopop/jsonschema v0.13.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mbleigh/raymond v0.0.0-20250414171441-6b3a58ab9e0a // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||
golang.org/x/crypto v0.39.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
google.golang.org/api v0.242.0 // indirect
|
||||
google.golang.org/genai v1.11.1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/grpc v1.73.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
129
docs/en/getting-started/quickstart/go/genkit/quickstart.go
Normal file
129
docs/en/getting-started/quickstart/go/genkit/quickstart.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/tbgenkit"
|
||||
|
||||
"github.com/firebase/genkit/go/ai"
|
||||
"github.com/firebase/genkit/go/genkit"
|
||||
"github.com/firebase/genkit/go/plugins/googlegenai"
|
||||
)
|
||||
|
||||
const systemPrompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`
|
||||
|
||||
var queries = []string{
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the hotel Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create Toolbox Client
|
||||
toolboxClient, err := core.NewToolboxClient("http://127.0.0.1:5000")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tools using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tools: %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
// Initialize Genkit
|
||||
g, err := genkit.Init(ctx,
|
||||
genkit.WithPlugins(&googlegenai.GoogleAI{}),
|
||||
genkit.WithDefaultModel("googleai/gemini-1.5-flash"),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to init genkit: %v\n", err)
|
||||
}
|
||||
|
||||
// Create a conversation history
|
||||
conversationHistory := []*ai.Message{
|
||||
ai.NewSystemTextMessage(systemPrompt),
|
||||
}
|
||||
|
||||
// Convert your tool to a Genkit tool.
|
||||
genkitTools := make([]ai.Tool, len(tools))
|
||||
for i, tool := range tools {
|
||||
newTool, err := tbgenkit.ToGenkitTool(tool, g)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to convert tool: %v\n", err)
|
||||
}
|
||||
genkitTools[i] = newTool
|
||||
}
|
||||
|
||||
toolRefs := make([]ai.ToolRef, len(genkitTools))
|
||||
|
||||
for i, tool := range genkitTools {
|
||||
toolRefs[i] = tool
|
||||
}
|
||||
|
||||
for _, query := range queries {
|
||||
conversationHistory = append(conversationHistory, ai.NewUserTextMessage(query))
|
||||
response, err := genkit.Generate(ctx, g,
|
||||
ai.WithMessages(conversationHistory...),
|
||||
ai.WithTools(toolRefs...),
|
||||
ai.WithReturnToolRequests(true),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("%v\n", err)
|
||||
}
|
||||
conversationHistory = append(conversationHistory, response.Message)
|
||||
|
||||
parts := []*ai.Part{}
|
||||
|
||||
for _, req := range response.ToolRequests() {
|
||||
tool := genkit.LookupTool(g, req.Name)
|
||||
if tool == nil {
|
||||
log.Fatalf("tool %q not found", req.Name)
|
||||
}
|
||||
|
||||
output, err := tool.RunRaw(ctx, req.Input)
|
||||
if err != nil {
|
||||
log.Fatalf("tool %q execution failed: %v", tool.Name(), err)
|
||||
}
|
||||
|
||||
parts = append(parts,
|
||||
ai.NewToolResponsePart(&ai.ToolResponse{
|
||||
Name: req.Name,
|
||||
Ref: req.Ref,
|
||||
Output: output,
|
||||
}))
|
||||
|
||||
}
|
||||
|
||||
if len(parts) > 0 {
|
||||
resp, err := genkit.Generate(ctx, g,
|
||||
ai.WithMessages(append(response.History(), ai.NewMessage(ai.RoleTool, nil, parts...))...),
|
||||
ai.WithTools(toolRefs...),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println("\n", resp.Text())
|
||||
conversationHistory = append(conversationHistory, resp.Message)
|
||||
} else {
|
||||
fmt.Println("\n", response.Text())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
49
docs/en/getting-started/quickstart/go/langchain/go.mod
Normal file
49
docs/en/getting-started/quickstart/go/langchain/go.mod
Normal file
@@ -0,0 +1,49 @@
|
||||
module langchan-quickstart
|
||||
|
||||
go 1.24.6
|
||||
|
||||
require (
|
||||
github.com/googleapis/mcp-toolbox-sdk-go v0.3.0
|
||||
github.com/tmc/langchaingo v0.1.13
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.121.1 // indirect
|
||||
cloud.google.com/go/ai v0.7.0 // indirect
|
||||
cloud.google.com/go/aiplatform v1.85.0 // indirect
|
||||
cloud.google.com/go/auth v0.16.2 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.7.0 // indirect
|
||||
cloud.google.com/go/iam v1.5.2 // indirect
|
||||
cloud.google.com/go/longrunning v0.6.7 // indirect
|
||||
cloud.google.com/go/vertexai v0.12.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/google/generative-ai-go v0.15.1 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
|
||||
github.com/pkoukk/tiktoken-go v0.1.6 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||
golang.org/x/crypto v0.39.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.15.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
google.golang.org/api v0.242.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/grpc v1.73.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
)
|
||||
149
docs/en/getting-started/quickstart/go/langchain/quickstart.go
Normal file
149
docs/en/getting-started/quickstart/go/langchain/quickstart.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
"github.com/tmc/langchaingo/llms"
|
||||
"github.com/tmc/langchaingo/llms/googleai"
|
||||
)
|
||||
|
||||
// ConvertToLangchainTool converts a generic core.ToolboxTool into a LangChainGo llms.Tool.
|
||||
func ConvertToLangchainTool(toolboxTool *core.ToolboxTool) llms.Tool {
|
||||
|
||||
// Fetch the tool's input schema
|
||||
inputschema, err := toolboxTool.InputSchema()
|
||||
if err != nil {
|
||||
return llms.Tool{}
|
||||
}
|
||||
|
||||
var paramsSchema map[string]any
|
||||
_ = json.Unmarshal(inputschema, ¶msSchema)
|
||||
|
||||
// Convert into LangChain's llms.Tool
|
||||
return llms.Tool{
|
||||
Type: "function",
|
||||
Function: &llms.FunctionDefinition{
|
||||
Name: toolboxTool.Name(),
|
||||
Description: toolboxTool.Description(),
|
||||
Parameters: paramsSchema,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const systemPrompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`
|
||||
|
||||
var queries = []string{
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the hotel Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it.",
|
||||
"Please book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
}
|
||||
|
||||
func main() {
|
||||
genaiKey := os.Getenv("GOOGLE_API_KEY")
|
||||
toolboxURL := "http://localhost:5000"
|
||||
ctx := context.Background()
|
||||
|
||||
// Initialize the Google AI client (LLM).
|
||||
llm, err := googleai.New(ctx, googleai.WithAPIKey(genaiKey), googleai.WithDefaultModel("gemini-1.5-flash"))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Google AI client: %v", err)
|
||||
}
|
||||
|
||||
// Initialize the MCP Toolbox client.
|
||||
toolboxClient, err := core.NewToolboxClient(toolboxURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tool using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tools: %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
toolsMap := make(map[string]*core.ToolboxTool, len(tools))
|
||||
|
||||
langchainTools := make([]llms.Tool, len(tools))
|
||||
// Convert the loaded ToolboxTools into the format LangChainGo requires.
|
||||
for i, tool := range tools {
|
||||
langchainTools[i] = ConvertToLangchainTool(tool)
|
||||
toolsMap[tool.Name()] = tool
|
||||
}
|
||||
|
||||
// Start the conversation history.
|
||||
messageHistory := []llms.MessageContent{
|
||||
llms.TextParts(llms.ChatMessageTypeSystem, systemPrompt),
|
||||
}
|
||||
|
||||
for _, query := range queries {
|
||||
messageHistory = append(messageHistory, llms.TextParts(llms.ChatMessageTypeHuman, query))
|
||||
|
||||
// Make the first call to the LLM, making it aware of the tool.
|
||||
resp, err := llm.GenerateContent(ctx, messageHistory, llms.WithTools(langchainTools))
|
||||
if err != nil {
|
||||
log.Fatalf("LLM call failed: %v", err)
|
||||
}
|
||||
respChoice := resp.Choices[0]
|
||||
|
||||
assistantResponse := llms.TextParts(llms.ChatMessageTypeAI, respChoice.Content)
|
||||
for _, tc := range respChoice.ToolCalls {
|
||||
assistantResponse.Parts = append(assistantResponse.Parts, tc)
|
||||
}
|
||||
messageHistory = append(messageHistory, assistantResponse)
|
||||
|
||||
// Process each tool call requested by the model.
|
||||
for _, tc := range respChoice.ToolCalls {
|
||||
toolName := tc.FunctionCall.Name
|
||||
tool := toolsMap[toolName]
|
||||
var args map[string]any
|
||||
if err := json.Unmarshal([]byte(tc.FunctionCall.Arguments), &args); err != nil {
|
||||
log.Fatalf("Failed to unmarshal arguments for tool '%s': %v", toolName, err)
|
||||
}
|
||||
toolResult, err := tool.Invoke(ctx, args)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to execute tool '%s': %v", toolName, err)
|
||||
}
|
||||
if toolResult == "" || toolResult == nil {
|
||||
toolResult = "Operation completed successfully with no specific return value."
|
||||
}
|
||||
|
||||
// Create the tool call response message and add it to the history.
|
||||
toolResponse := llms.MessageContent{
|
||||
Role: llms.ChatMessageTypeTool,
|
||||
Parts: []llms.ContentPart{
|
||||
llms.ToolCallResponse{
|
||||
Name: toolName,
|
||||
Content: fmt.Sprintf("%v", toolResult),
|
||||
},
|
||||
},
|
||||
}
|
||||
messageHistory = append(messageHistory, toolResponse)
|
||||
}
|
||||
finalResp, err := llm.GenerateContent(ctx, messageHistory)
|
||||
if err != nil {
|
||||
log.Fatalf("Final LLM call failed after tool execution: %v", err)
|
||||
}
|
||||
|
||||
// Add the final textual response from the LLM to the history
|
||||
messageHistory = append(messageHistory, llms.TextParts(llms.ChatMessageTypeAI, finalResp.Choices[0].Content))
|
||||
|
||||
fmt.Println(finalResp.Choices[0].Content)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
38
docs/en/getting-started/quickstart/go/openAI/go.mod
Normal file
38
docs/en/getting-started/quickstart/go/openAI/go.mod
Normal file
@@ -0,0 +1,38 @@
|
||||
module openai-quickstart
|
||||
|
||||
go 1.24.6
|
||||
|
||||
require (
|
||||
github.com/googleapis/mcp-toolbox-sdk-go v0.3.0
|
||||
github.com/openai/openai-go v1.12.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/auth v0.16.2 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.7.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
|
||||
github.com/tidwall/gjson v1.14.4 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||
golang.org/x/crypto v0.39.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
google.golang.org/api v0.242.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/grpc v1.73.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
)
|
||||
141
docs/en/getting-started/quickstart/go/openAI/quickstart.go
Normal file
141
docs/en/getting-started/quickstart/go/openAI/quickstart.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/googleapis/mcp-toolbox-sdk-go/core"
|
||||
openai "github.com/openai/openai-go"
|
||||
)
|
||||
|
||||
// ConvertToOpenAITool converts a ToolboxTool into the go-openai library's Tool format.
|
||||
func ConvertToOpenAITool(toolboxTool *core.ToolboxTool) openai.ChatCompletionToolParam {
|
||||
// Get the input schema
|
||||
jsonSchemaBytes, err := toolboxTool.InputSchema()
|
||||
if err != nil {
|
||||
return openai.ChatCompletionToolParam{}
|
||||
}
|
||||
|
||||
// Unmarshal the JSON bytes into FunctionParameters
|
||||
var paramsSchema openai.FunctionParameters
|
||||
if err := json.Unmarshal(jsonSchemaBytes, ¶msSchema); err != nil {
|
||||
return openai.ChatCompletionToolParam{}
|
||||
}
|
||||
|
||||
// Create and return the final tool parameter struct.
|
||||
return openai.ChatCompletionToolParam{
|
||||
Function: openai.FunctionDefinitionParam{
|
||||
Name: toolboxTool.Name(),
|
||||
Description: openai.String(toolboxTool.Description()),
|
||||
Parameters: paramsSchema,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const systemPrompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`
|
||||
|
||||
var queries = []string{
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the hotel Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Setup
|
||||
ctx := context.Background()
|
||||
toolboxURL := "http://localhost:5000"
|
||||
openAIClient := openai.NewClient()
|
||||
|
||||
// Initialize the MCP Toolbox client.
|
||||
toolboxClient, err := core.NewToolboxClient(toolboxURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Toolbox client: %v", err)
|
||||
}
|
||||
|
||||
// Load the tools using the MCP Toolbox SDK.
|
||||
tools, err := toolboxClient.LoadToolset("my-toolset", ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load tool : %v\nMake sure your Toolbox server is running and the tool is configured.", err)
|
||||
}
|
||||
|
||||
openAITools := make([]openai.ChatCompletionToolParam, len(tools))
|
||||
toolsMap := make(map[string]*core.ToolboxTool, len(tools))
|
||||
|
||||
for i, tool := range tools {
|
||||
// Convert the Toolbox tool into the openAI FunctionDeclaration format.
|
||||
openAITools[i] = ConvertToOpenAITool(tool)
|
||||
// Add tool to a map for lookup later
|
||||
toolsMap[tool.Name()] = tool
|
||||
|
||||
}
|
||||
|
||||
params := openai.ChatCompletionNewParams{
|
||||
Messages: []openai.ChatCompletionMessageParamUnion{
|
||||
openai.SystemMessage(systemPrompt),
|
||||
},
|
||||
Tools: openAITools,
|
||||
Seed: openai.Int(0),
|
||||
Model: openai.ChatModelGPT4o,
|
||||
}
|
||||
|
||||
for _, query := range queries {
|
||||
|
||||
params.Messages = append(params.Messages, openai.UserMessage(query))
|
||||
|
||||
// Make initial chat completion request
|
||||
completion, err := openAIClient.Chat.Completions.New(ctx, params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
toolCalls := completion.Choices[0].Message.ToolCalls
|
||||
|
||||
// Return early if there are no tool calls
|
||||
if len(toolCalls) == 0 {
|
||||
log.Println("No function call")
|
||||
}
|
||||
|
||||
// If there was a function call, continue the conversation
|
||||
params.Messages = append(params.Messages, completion.Choices[0].Message.ToParam())
|
||||
for _, toolCall := range toolCalls {
|
||||
|
||||
toolName := toolCall.Function.Name
|
||||
toolToInvoke := toolsMap[toolName]
|
||||
|
||||
var args map[string]any
|
||||
err := json.Unmarshal([]byte(toolCall.Function.Arguments), &args)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
result, err := toolToInvoke.Invoke(ctx, args)
|
||||
if err != nil {
|
||||
log.Fatal("Could not invoke tool", err)
|
||||
}
|
||||
|
||||
params.Messages = append(params.Messages, openai.ToolMessage(result.(string), toolCall.ID))
|
||||
}
|
||||
|
||||
completion, err = openAIClient.Chat.Completions.New(ctx, params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
params.Messages = append(params.Messages, openai.AssistantMessage(query))
|
||||
|
||||
fmt.Println("\n", completion.Choices[0].Message.Content)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
119
docs/en/getting-started/quickstart/js/genAI/quickstart.js
Normal file
119
docs/en/getting-started/quickstart/js/genAI/quickstart.js
Normal file
@@ -0,0 +1,119 @@
|
||||
import { GoogleGenAI } from "@google/genai";
|
||||
import { ToolboxClient } from "@toolbox-sdk/core";
|
||||
|
||||
|
||||
const TOOLBOX_URL = "http://127.0.0.1:5000"; // Update if needed
|
||||
const GOOGLE_API_KEY = process.env.GOOGLE_API_KEY || 'your-api-key'; // Replace it with your API key
|
||||
|
||||
const prompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, you MUST use the available tools to find information. Mention its name, id,
|
||||
location and price tier. Always mention hotel id while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`;
|
||||
|
||||
const queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
];
|
||||
|
||||
function mapZodTypeToOpenAPIType(zodTypeName) {
|
||||
|
||||
console.log(zodTypeName)
|
||||
const typeMap = {
|
||||
'ZodString': 'string',
|
||||
'ZodNumber': 'number',
|
||||
'ZodBoolean': 'boolean',
|
||||
'ZodArray': 'array',
|
||||
'ZodObject': 'object',
|
||||
};
|
||||
return typeMap[zodTypeName] || 'string';
|
||||
}
|
||||
|
||||
async function main() {
|
||||
|
||||
const toolboxClient = new ToolboxClient(TOOLBOX_URL);
|
||||
const toolboxTools = await toolboxClient.loadToolset("my-toolset");
|
||||
|
||||
const geminiTools = [{
|
||||
functionDeclarations: toolboxTools.map(tool => {
|
||||
|
||||
const schema = tool.getParamSchema();
|
||||
const properties = {};
|
||||
const required = [];
|
||||
|
||||
|
||||
for (const [key, param] of Object.entries(schema.shape)) {
|
||||
properties[key] = {
|
||||
type: mapZodTypeToOpenAPIType(param.constructor.name),
|
||||
description: param.description || '',
|
||||
};
|
||||
required.push(key)
|
||||
}
|
||||
|
||||
return {
|
||||
name: tool.getName(),
|
||||
description: tool.getDescription(),
|
||||
parameters: { type: 'object', properties, required },
|
||||
};
|
||||
})
|
||||
}];
|
||||
|
||||
|
||||
const genAI = new GoogleGenAI({ apiKey: GOOGLE_API_KEY });
|
||||
|
||||
const chat = genAI.chats.create({
|
||||
model: "gemini-2.5-flash",
|
||||
config: {
|
||||
systemInstruction: prompt,
|
||||
tools: geminiTools,
|
||||
}
|
||||
});
|
||||
|
||||
for (const query of queries) {
|
||||
|
||||
let currentResult = await chat.sendMessage({ message: query });
|
||||
|
||||
let finalResponseGiven = false
|
||||
while (!finalResponseGiven) {
|
||||
|
||||
const response = currentResult;
|
||||
const functionCalls = response.functionCalls || [];
|
||||
|
||||
if (functionCalls.length === 0) {
|
||||
console.log(response.text)
|
||||
finalResponseGiven = true;
|
||||
} else {
|
||||
const toolResponses = [];
|
||||
for (const call of functionCalls) {
|
||||
const toolName = call.name
|
||||
const toolToExecute = toolboxTools.find(t => t.getName() === toolName);
|
||||
|
||||
if (toolToExecute) {
|
||||
try {
|
||||
const functionResult = await toolToExecute(call.args);
|
||||
toolResponses.push({
|
||||
functionResponse: { name: call.name, response: { result: functionResult } }
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error executing tool '${toolName}':`, e);
|
||||
toolResponses.push({
|
||||
functionResponse: { name: call.name, response: { error: e.message } }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentResult = await chat.sendMessage({ message: toolResponses });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
88
docs/en/getting-started/quickstart/js/genkit/quickstart.js
Normal file
88
docs/en/getting-started/quickstart/js/genkit/quickstart.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import { ToolboxClient } from "@toolbox-sdk/core";
|
||||
import { genkit } from "genkit";
|
||||
import { googleAI } from '@genkit-ai/googleai';
|
||||
|
||||
const GOOGLE_API_KEY = process.env.GOOGLE_API_KEY || 'your-api-key'; // Replace it with your API key
|
||||
|
||||
const systemPrompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`;
|
||||
|
||||
const queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
];
|
||||
|
||||
async function main() {
|
||||
const toolboxClient = new ToolboxClient("http://127.0.0.1:5000");
|
||||
|
||||
const ai = genkit({
|
||||
plugins: [
|
||||
googleAI({
|
||||
apiKey: process.env.GEMINI_API_KEY || GOOGLE_API_KEY
|
||||
})
|
||||
],
|
||||
model: googleAI.model('gemini-2.0-flash'),
|
||||
});
|
||||
|
||||
const toolboxTools = await toolboxClient.loadToolset("my-toolset");
|
||||
const toolMap = Object.fromEntries(
|
||||
toolboxTools.map((tool) => {
|
||||
const definedTool = ai.defineTool(
|
||||
{
|
||||
name: tool.getName(),
|
||||
description: tool.getDescription(),
|
||||
inputSchema: tool.getParamSchema(),
|
||||
},
|
||||
tool
|
||||
);
|
||||
return [tool.getName(), definedTool];
|
||||
})
|
||||
);
|
||||
const tools = Object.values(toolMap);
|
||||
|
||||
let conversationHistory = [{ role: "system", content: [{ text: systemPrompt }] }];
|
||||
|
||||
for (const query of queries) {
|
||||
conversationHistory.push({ role: "user", content: [{ text: query }] });
|
||||
const response = await ai.generate({
|
||||
messages: conversationHistory,
|
||||
tools: tools,
|
||||
});
|
||||
conversationHistory.push(response.message);
|
||||
|
||||
const toolRequests = response.toolRequests;
|
||||
if (toolRequests?.length > 0) {
|
||||
// Execute tools concurrently and collect their responses.
|
||||
const toolResponses = await Promise.all(
|
||||
toolRequests.map(async (call) => {
|
||||
try {
|
||||
const toolOutput = await toolMap[call.name].invoke(call.input);
|
||||
return { role: "tool", content: [{ toolResponse: { name: call.name, output: toolOutput } }] };
|
||||
} catch (e) {
|
||||
console.error(`Error executing tool ${call.name}:`, e);
|
||||
return { role: "tool", content: [{ toolResponse: { name: call.name, output: { error: e.message } } }] };
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
conversationHistory.push(...toolResponses);
|
||||
|
||||
// Call the AI again with the tool results.
|
||||
response = await ai.generate({ messages: conversationHistory, tools });
|
||||
conversationHistory.push(response.message);
|
||||
}
|
||||
|
||||
console.log(response.text);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,73 @@
|
||||
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
|
||||
import { ToolboxClient } from "@toolbox-sdk/core";
|
||||
import { tool } from "@langchain/core/tools";
|
||||
import { createReactAgent } from "@langchain/langgraph/prebuilt";
|
||||
import { MemorySaver } from "@langchain/langgraph";
|
||||
|
||||
const GOOGLE_API_KEY = process.env.GOOGLE_API_KEY || 'your-api-key'; // Replace it with your API key
|
||||
|
||||
const prompt = `
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking, and
|
||||
cancellations. When the user searches for a hotel, mention its name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
`;
|
||||
|
||||
const queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
];
|
||||
|
||||
async function main() {
|
||||
const model = new ChatGoogleGenerativeAI({
|
||||
model: "gemini-2.0-flash",
|
||||
});
|
||||
|
||||
const client = new ToolboxClient("http://127.0.0.1:5000");
|
||||
const toolboxTools = await client.loadToolset("my-toolset");
|
||||
|
||||
// Define the basics of the tool: name, description, schema and core logic
|
||||
const getTool = (toolboxTool) => tool(toolboxTool, {
|
||||
name: toolboxTool.getName(),
|
||||
description: toolboxTool.getDescription(),
|
||||
schema: toolboxTool.getParamSchema()
|
||||
});
|
||||
const tools = toolboxTools.map(getTool);
|
||||
|
||||
const agent = createReactAgent({
|
||||
llm: model,
|
||||
tools: tools,
|
||||
checkpointer: new MemorySaver(),
|
||||
systemPrompt: prompt,
|
||||
});
|
||||
|
||||
const langGraphConfig = {
|
||||
configurable: {
|
||||
thread_id: "test-thread",
|
||||
},
|
||||
};
|
||||
|
||||
for (const query of queries) {
|
||||
const agentOutput = await agent.invoke(
|
||||
{
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: query,
|
||||
},
|
||||
],
|
||||
verbose: true,
|
||||
},
|
||||
langGraphConfig
|
||||
);
|
||||
const response = agentOutput.messages[agentOutput.messages.length - 1].content;
|
||||
console.log(response);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,79 @@
|
||||
import { gemini, GEMINI_MODEL } from "@llamaindex/google";
|
||||
import { agent } from "@llamaindex/workflow";
|
||||
import { createMemory, staticBlock, tool } from "llamaindex";
|
||||
import { ToolboxClient } from "@toolbox-sdk/core";
|
||||
|
||||
const TOOLBOX_URL = "http://127.0.0.1:5000"; // Update if needed
|
||||
const GOOGLE_API_KEY = process.env.GOOGLE_API_KEY || 'your-api-key'; // Replace it with your API key
|
||||
|
||||
const prompt = `
|
||||
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking and cancellations.
|
||||
When the user searches for a hotel, mention its name, id, location and price tier.
|
||||
Always mention hotel ids while performing any searches — this is very important for operations.
|
||||
For any bookings or cancellations, please provide the appropriate confirmation.
|
||||
Update check-in or check-out dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
|
||||
`;
|
||||
|
||||
const queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
];
|
||||
|
||||
async function main() {
|
||||
// Connect to MCP Toolbox
|
||||
const client = new ToolboxClient(TOOLBOX_URL);
|
||||
const toolboxTools = await client.loadToolset("my-toolset");
|
||||
const tools = toolboxTools.map((toolboxTool) => {
|
||||
return tool({
|
||||
name: toolboxTool.getName(),
|
||||
description: toolboxTool.getDescription(),
|
||||
parameters: toolboxTool.getParamSchema(),
|
||||
execute: toolboxTool,
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize LLM
|
||||
const llm = gemini({
|
||||
model: GEMINI_MODEL.GEMINI_2_0_FLASH,
|
||||
apiKey: GOOGLE_API_KEY,
|
||||
});
|
||||
|
||||
const memory = createMemory({
|
||||
memoryBlocks: [
|
||||
staticBlock({
|
||||
content: prompt,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
// Create the Agent
|
||||
const myAgent = agent({
|
||||
tools: tools,
|
||||
llm,
|
||||
memory,
|
||||
systemPrompt: prompt,
|
||||
});
|
||||
|
||||
for (const query of queries) {
|
||||
const result = await myAgent.run(query);
|
||||
const output = result.data.result;
|
||||
|
||||
console.log(`\nUser: ${query}`);
|
||||
if (typeof output === "string") {
|
||||
console.log(output.trim());
|
||||
} else if (typeof output === "object" && "text" in output) {
|
||||
console.log(output.text.trim());
|
||||
} else {
|
||||
console.log(JSON.stringify(output));
|
||||
}
|
||||
}
|
||||
//You may observe some extra logs during execution due to the run method provided by Llama.
|
||||
console.log("Agent run finished.");
|
||||
}
|
||||
|
||||
main();
|
||||
70
docs/en/getting-started/quickstart/python/adk/quickstart.py
Normal file
70
docs/en/getting-started/quickstart/python/adk/quickstart.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from google.adk.agents import Agent
|
||||
from google.adk.runners import Runner
|
||||
from google.adk.sessions import InMemorySessionService
|
||||
from google.adk.artifacts.in_memory_artifact_service import InMemoryArtifactService
|
||||
from google.genai import types
|
||||
from toolbox_core import ToolboxSyncClient
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
# TODO(developer): replace this with your Google API key
|
||||
|
||||
os.environ['GOOGLE_API_KEY'] = 'your-api-key'
|
||||
|
||||
async def main():
|
||||
with ToolboxSyncClient("http://127.0.0.1:5000") as toolbox_client:
|
||||
|
||||
prompt = """
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking and
|
||||
cancellations. When the user searches for a hotel, mention it's name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
"""
|
||||
|
||||
root_agent = Agent(
|
||||
model='gemini-2.0-flash-001',
|
||||
name='hotel_agent',
|
||||
description='A helpful AI assistant.',
|
||||
instruction=prompt,
|
||||
tools=toolbox_client.load_toolset("my-toolset"),
|
||||
)
|
||||
|
||||
session_service = InMemorySessionService()
|
||||
artifacts_service = InMemoryArtifactService()
|
||||
session = await session_service.create_session(
|
||||
state={}, app_name='hotel_agent', user_id='123'
|
||||
)
|
||||
runner = Runner(
|
||||
app_name='hotel_agent',
|
||||
agent=root_agent,
|
||||
artifact_service=artifacts_service,
|
||||
session_service=session_service,
|
||||
)
|
||||
|
||||
queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
]
|
||||
|
||||
for query in queries:
|
||||
content = types.Content(role='user', parts=[types.Part(text=query)])
|
||||
events = runner.run(session_id=session.id,
|
||||
user_id='123', new_message=content)
|
||||
|
||||
responses = (
|
||||
part.text
|
||||
for event in events
|
||||
for part in event.content.parts
|
||||
if part.text is not None
|
||||
)
|
||||
|
||||
for text in responses:
|
||||
print(text)
|
||||
|
||||
asyncio.run(main())
|
||||
108
docs/en/getting-started/quickstart/python/core/quickstart.py
Normal file
108
docs/en/getting-started/quickstart/python/core/quickstart.py
Normal file
@@ -0,0 +1,108 @@
|
||||
import asyncio
|
||||
|
||||
from google import genai
|
||||
from google.genai.types import (
|
||||
Content,
|
||||
FunctionDeclaration,
|
||||
GenerateContentConfig,
|
||||
Part,
|
||||
Tool,
|
||||
)
|
||||
|
||||
from toolbox_core import ToolboxClient
|
||||
|
||||
prompt = """
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking and
|
||||
cancellations. When the user searches for a hotel, mention it's name, id,
|
||||
location and price tier. Always mention hotel id while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
"""
|
||||
|
||||
queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Please book the hotel Hilton Basel for me.",
|
||||
"This is too expensive. Please cancel it.",
|
||||
"Please book Hyatt Regency for me",
|
||||
"My check in dates for my booking would be from April 10, 2024 to April 19, 2024.",
|
||||
]
|
||||
|
||||
async def main():
|
||||
async with ToolboxClient("http://127.0.0.1:5000") as toolbox_client:
|
||||
|
||||
# The toolbox_tools list contains Python callables (functions/methods) designed for LLM tool-use
|
||||
# integration. While this example uses Google's genai client, these callables can be adapted for
|
||||
# various function-calling or agent frameworks. For easier integration with supported frameworks
|
||||
# (https://github.com/googleapis/mcp-toolbox-python-sdk/tree/main/packages), use the
|
||||
# provided wrapper packages, which handle framework-specific boilerplate.
|
||||
toolbox_tools = await toolbox_client.load_toolset("my-toolset")
|
||||
genai_client = genai.Client(
|
||||
vertexai=True, project="project-id", location="us-central1"
|
||||
)
|
||||
|
||||
genai_tools = [
|
||||
Tool(
|
||||
function_declarations=[
|
||||
FunctionDeclaration.from_callable_with_api_option(callable=tool)
|
||||
]
|
||||
)
|
||||
for tool in toolbox_tools
|
||||
]
|
||||
history = []
|
||||
for query in queries:
|
||||
user_prompt_content = Content(
|
||||
role="user",
|
||||
parts=[Part.from_text(text=query)],
|
||||
)
|
||||
history.append(user_prompt_content)
|
||||
|
||||
response = genai_client.models.generate_content(
|
||||
model="gemini-2.0-flash-001",
|
||||
contents=history,
|
||||
config=GenerateContentConfig(
|
||||
system_instruction=prompt,
|
||||
tools=genai_tools,
|
||||
),
|
||||
)
|
||||
history.append(response.candidates[0].content)
|
||||
function_response_parts = []
|
||||
for function_call in response.function_calls:
|
||||
fn_name = function_call.name
|
||||
# The tools are sorted alphabetically
|
||||
if fn_name == "search-hotels-by-name":
|
||||
function_result = await toolbox_tools[3](**function_call.args)
|
||||
elif fn_name == "search-hotels-by-location":
|
||||
function_result = await toolbox_tools[2](**function_call.args)
|
||||
elif fn_name == "book-hotel":
|
||||
function_result = await toolbox_tools[0](**function_call.args)
|
||||
elif fn_name == "update-hotel":
|
||||
function_result = await toolbox_tools[4](**function_call.args)
|
||||
elif fn_name == "cancel-hotel":
|
||||
function_result = await toolbox_tools[1](**function_call.args)
|
||||
else:
|
||||
raise ValueError("Function name not present.")
|
||||
function_response = {"result": function_result}
|
||||
function_response_part = Part.from_function_response(
|
||||
name=function_call.name,
|
||||
response=function_response,
|
||||
)
|
||||
function_response_parts.append(function_response_part)
|
||||
|
||||
if function_response_parts:
|
||||
tool_response_content = Content(role="tool", parts=function_response_parts)
|
||||
history.append(tool_response_content)
|
||||
|
||||
response2 = genai_client.models.generate_content(
|
||||
model="gemini-2.0-flash-001",
|
||||
contents=history,
|
||||
config=GenerateContentConfig(
|
||||
tools=genai_tools,
|
||||
),
|
||||
)
|
||||
final_model_response_content = response2.candidates[0].content
|
||||
history.append(final_model_response_content)
|
||||
print(response2.text)
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,52 @@
|
||||
import asyncio
|
||||
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
|
||||
# TODO(developer): replace this with another import if needed
|
||||
|
||||
from langchain_google_vertexai import ChatVertexAI
|
||||
|
||||
# from langchain_google_genai import ChatGoogleGenerativeAI
|
||||
|
||||
# from langchain_anthropic import ChatAnthropic
|
||||
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
|
||||
from toolbox_langchain import ToolboxClient
|
||||
|
||||
prompt = """
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking and
|
||||
cancellations. When the user searches for a hotel, mention it's name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
"""
|
||||
|
||||
queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
]
|
||||
|
||||
async def main():
|
||||
# TODO(developer): replace this with another model if needed
|
||||
model = ChatVertexAI(model_name="gemini-2.0-flash-001")
|
||||
# model = ChatGoogleGenerativeAI(model="gemini-2.0-flash-001")
|
||||
# model = ChatAnthropic(model="claude-3-5-sonnet-20240620")
|
||||
|
||||
# Load the tools from the Toolbox server
|
||||
async with ToolboxClient("http://127.0.0.1:5000") as client:
|
||||
tools = await client.aload_toolset()
|
||||
|
||||
agent = create_react_agent(model, tools, checkpointer=MemorySaver())
|
||||
|
||||
config = {"configurable": {"thread_id": "thread-1"}}
|
||||
for query in queries:
|
||||
inputs = {"messages": [("user", prompt + query)]}
|
||||
response = agent.invoke(inputs, stream_mode="values", config=config)
|
||||
print(response["messages"][-1].content)
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,63 @@
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from llama_index.core.agent.workflow import AgentWorkflow
|
||||
|
||||
from llama_index.core.workflow import Context
|
||||
|
||||
# TODO(developer): replace this with another import if needed
|
||||
|
||||
from llama_index.llms.google_genai import GoogleGenAI
|
||||
|
||||
# from llama_index.llms.anthropic import Anthropic
|
||||
|
||||
from toolbox_llamaindex import ToolboxClient
|
||||
|
||||
prompt = """
|
||||
You're a helpful hotel assistant. You handle hotel searching, booking and
|
||||
cancellations. When the user searches for a hotel, mention it's name, id,
|
||||
location and price tier. Always mention hotel ids while performing any
|
||||
searches. This is very important for any operations. For any bookings or
|
||||
cancellations, please provide the appropriate confirmation. Be sure to
|
||||
update checkin or checkout dates if mentioned by the user.
|
||||
Don't ask for confirmations from the user.
|
||||
"""
|
||||
|
||||
queries = [
|
||||
"Find hotels in Basel with Basel in its name.",
|
||||
"Can you book the Hilton Basel for me?",
|
||||
"Oh wait, this is too expensive. Please cancel it and book the Hyatt Regency instead.",
|
||||
"My check in dates would be from April 10, 2024 to April 19, 2024.",
|
||||
]
|
||||
|
||||
async def main():
|
||||
# TODO(developer): replace this with another model if needed
|
||||
llm = GoogleGenAI(
|
||||
model="gemini-2.0-flash-001",
|
||||
vertexai_config={"project": "project-id", "location": "us-central1"},
|
||||
)
|
||||
# llm = GoogleGenAI(
|
||||
# api_key=os.getenv("GOOGLE_API_KEY"),
|
||||
# model="gemini-2.0-flash-001",
|
||||
# )
|
||||
# llm = Anthropic(
|
||||
# model="claude-3-7-sonnet-latest",
|
||||
# api_key=os.getenv("ANTHROPIC_API_KEY")
|
||||
# )
|
||||
|
||||
# Load the tools from the Toolbox server
|
||||
async with ToolboxClient("http://127.0.0.1:5000") as client:
|
||||
tools = await client.aload_toolset()
|
||||
|
||||
agent = AgentWorkflow.from_tools_or_functions(
|
||||
tools,
|
||||
llm=llm,
|
||||
system_prompt=prompt,
|
||||
)
|
||||
ctx = Context(agent)
|
||||
for query in queries:
|
||||
response = await agent.run(user_msg=query, ctx=ctx)
|
||||
print(f"---- {query} ----")
|
||||
print(str(response))
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -13,7 +13,7 @@ In this section, we will download Toolbox, configure our tools in a
|
||||
<!-- {x-release-please-start-version} -->
|
||||
```bash
|
||||
export OS="linux/amd64" # one of linux/amd64, darwin/arm64, darwin/amd64, or windows/amd64
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/$OS/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/$OS/toolbox
|
||||
```
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
|
||||
@@ -6,328 +6,9 @@ description: >
|
||||
Connect your IDE to Firestore using Toolbox.
|
||||
---
|
||||
|
||||
[Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) is
|
||||
an open protocol for connecting Large Language Models (LLMs) to data sources
|
||||
like Firestore. This guide covers how to use [MCP Toolbox for Databases][toolbox]
|
||||
to expose your developer assistant tools to a Firestore instance:
|
||||
|
||||
* [Cursor][cursor]
|
||||
* [Windsurf][windsurf] (Codium)
|
||||
* [Visual Studio Code][vscode] (Copilot)
|
||||
* [Cline][cline] (VS Code extension)
|
||||
* [Claude desktop][claudedesktop]
|
||||
* [Claude code][claudecode]
|
||||
* [Gemini CLI][geminicli]
|
||||
* [Gemini Code Assist][geminicodeassist]
|
||||
|
||||
[toolbox]: https://github.com/googleapis/genai-toolbox
|
||||
[cursor]: #configure-your-mcp-client
|
||||
[windsurf]: #configure-your-mcp-client
|
||||
[vscode]: #configure-your-mcp-client
|
||||
[cline]: #configure-your-mcp-client
|
||||
[claudedesktop]: #configure-your-mcp-client
|
||||
[claudecode]: #configure-your-mcp-client
|
||||
[geminicli]: #configure-your-mcp-client
|
||||
[geminicodeassist]: #configure-your-mcp-client
|
||||
|
||||
## Set up Firestore
|
||||
|
||||
1. Create or select a Google Cloud project.
|
||||
|
||||
* [Create a new
|
||||
project](https://cloud.google.com/resource-manager/docs/creating-managing-projects)
|
||||
* [Select an existing
|
||||
project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects)
|
||||
|
||||
1. [Enable the Firestore
|
||||
API](https://console.cloud.google.com/apis/library/firestore.googleapis.com)
|
||||
for your project.
|
||||
|
||||
1. [Create a Firestore
|
||||
database](https://cloud.google.com/firestore/docs/create-database-web-mobile-client-library)
|
||||
if you haven't already.
|
||||
|
||||
1. Set up authentication for your local environment.
|
||||
|
||||
* [Install gcloud CLI](https://cloud.google.com/sdk/docs/install)
|
||||
* Run `gcloud auth application-default login` to authenticate
|
||||
|
||||
## Install MCP Toolbox
|
||||
|
||||
1. Download the latest version of Toolbox as a binary. Select the [correct
|
||||
binary](https://github.com/googleapis/genai-toolbox/releases) corresponding
|
||||
to your OS and CPU architecture. You are required to use Toolbox version
|
||||
V0.10.0+:
|
||||
|
||||
<!-- {x-release-please-start-version} -->
|
||||
{{< tabpane persist=header >}}
|
||||
{{< tab header="linux/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/linux/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/arm64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/darwin/arm64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/darwin/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="windows/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/windows/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
{{< /tabpane >}}
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
1. Make the binary executable:
|
||||
|
||||
```bash
|
||||
chmod +x toolbox
|
||||
```
|
||||
|
||||
1. Verify the installation:
|
||||
|
||||
```bash
|
||||
./toolbox --version
|
||||
```
|
||||
|
||||
## Configure your MCP Client
|
||||
|
||||
{{< tabpane text=true >}}
|
||||
{{% tab header="Claude code" lang="en" %}}
|
||||
|
||||
1. Install [Claude
|
||||
Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview).
|
||||
1. Create a `.mcp.json` file in your project root if it doesn't exist.
|
||||
1. Add the following configuration, replace the environment variables with your
|
||||
values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"firestore": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","firestore","--stdio"],
|
||||
"env": {
|
||||
"FIRESTORE_PROJECT": "your-project-id",
|
||||
"FIRESTORE_DATABASE": "(default)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Restart Claude code to apply the new configuration.
|
||||
{{% /tab %}}
|
||||
|
||||
{{% tab header="Claude desktop" lang="en" %}}
|
||||
|
||||
1. Open [Claude desktop](https://claude.ai/download) and navigate to Settings.
|
||||
1. Under the Developer tab, tap Edit Config to open the configuration file.
|
||||
1. Add the following configuration, replace the environment variables with your
|
||||
values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"firestore": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","firestore","--stdio"],
|
||||
"env": {
|
||||
"FIRESTORE_PROJECT": "your-project-id",
|
||||
"FIRESTORE_DATABASE": "(default)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Restart Claude desktop.
|
||||
1. From the new chat screen, you should see a hammer (MCP) icon appear with the
|
||||
new MCP server available.
|
||||
{{% /tab %}}
|
||||
|
||||
{{% tab header="Cline" lang="en" %}}
|
||||
|
||||
1. Open the [Cline](https://github.com/cline/cline) extension in VS Code and tap
|
||||
the **MCP Servers** icon.
|
||||
1. Tap Configure MCP Servers to open the configuration file.
|
||||
1. Add the following configuration, replace the environment variables with your
|
||||
values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"firestore": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","firestore","--stdio"],
|
||||
"env": {
|
||||
"FIRESTORE_PROJECT": "your-project-id",
|
||||
"FIRESTORE_DATABASE": "(default)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. You should see a green active status after the server is successfully
|
||||
connected.
|
||||
{{% /tab %}}
|
||||
|
||||
{{% tab header="Cursor" lang="en" %}}
|
||||
|
||||
1. Create a `.cursor` directory in your project root if it doesn't exist.
|
||||
1. Create a `.cursor/mcp.json` file if it doesn't exist and open it.
|
||||
1. Add the following configuration, replace the environment variables with your
|
||||
values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"firestore": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","firestore","--stdio"],
|
||||
"env": {
|
||||
"FIRESTORE_PROJECT": "your-project-id",
|
||||
"FIRESTORE_DATABASE": "(default)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. [Cursor](https://www.cursor.com/) and navigate to **Settings > Cursor
|
||||
Settings > MCP**. You should see a green active status after the server is
|
||||
successfully connected.
|
||||
{{% /tab %}}
|
||||
|
||||
{{% tab header="Visual Studio Code (Copilot)" lang="en" %}}
|
||||
|
||||
1. Open [VS Code](https://code.visualstudio.com/docs/copilot/overview) and
|
||||
create a `.vscode` directory in your project root if it doesn't exist.
|
||||
1. Create a `.vscode/mcp.json` file if it doesn't exist and open it.
|
||||
1. Add the following configuration, replace the environment variables with your
|
||||
values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"firestore": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","firestore","--stdio"],
|
||||
"env": {
|
||||
"FIRESTORE_PROJECT": "your-project-id",
|
||||
"FIRESTORE_DATABASE": "(default)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
|
||||
{{% tab header="Windsurf" lang="en" %}}
|
||||
|
||||
1. Open [Windsurf](https://docs.codeium.com/windsurf) and navigate to the
|
||||
Cascade assistant.
|
||||
1. Tap on the hammer (MCP) icon, then Configure to open the configuration file.
|
||||
1. Add the following configuration, replace the environment variables with your
|
||||
values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"firestore": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","firestore","--stdio"],
|
||||
"env": {
|
||||
"FIRESTORE_PROJECT": "your-project-id",
|
||||
"FIRESTORE_DATABASE": "(default)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
{{% tab header="Gemini CLI" lang="en" %}}
|
||||
|
||||
1. Install the [Gemini
|
||||
CLI](https://github.com/google-gemini/gemini-cli?tab=readme-ov-file#quickstart).
|
||||
1. In your working directory, create a folder named `.gemini`. Within it, create
|
||||
a `settings.json` file.
|
||||
1. Add the following configuration, replace the environment variables with your
|
||||
values, and then save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"firestore": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","firestore","--stdio"],
|
||||
"env": {
|
||||
"FIRESTORE_PROJECT": "your-project-id",
|
||||
"FIRESTORE_DATABASE": "(default)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
{{% tab header="Gemini Code Assist" lang="en" %}}
|
||||
|
||||
1. Install the [Gemini Code
|
||||
Assist](https://marketplace.visualstudio.com/items?itemName=Google.geminicodeassist)
|
||||
extension in Visual Studio Code.
|
||||
1. Enable Agent Mode in Gemini Code Assist chat.
|
||||
1. In your working directory, create a folder named `.gemini`. Within it, create
|
||||
a `settings.json` file.
|
||||
1. Add the following configuration, replace the environment variables with your
|
||||
values, and then save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"firestore": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","firestore","--stdio"],
|
||||
"env": {
|
||||
"FIRESTORE_PROJECT": "your-project-id",
|
||||
"FIRESTORE_DATABASE": "(default)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
{{< /tabpane >}}
|
||||
|
||||
## Use Tools
|
||||
|
||||
Your AI tool is now connected to Firestore using MCP. Try asking your AI
|
||||
assistant to list collections, get documents, query collections, or manage
|
||||
security rules.
|
||||
|
||||
The following tools are available to the LLM:
|
||||
|
||||
1. **firestore-get-documents**: Gets multiple documents from Firestore by their
|
||||
paths
|
||||
1. **firestore-list-collections**: List Firestore collections for a given parent
|
||||
path
|
||||
1. **firestore-delete-documents**: Delete multiple documents from Firestore
|
||||
1. **firestore-query-collection**: Query documents from a collection with
|
||||
filtering, ordering, and limit options
|
||||
1. **firestore-get-rules**: Retrieves the active Firestore security rules for
|
||||
the current project
|
||||
1. **firestore-validate-rules**: Validates Firestore security rules syntax and
|
||||
errors
|
||||
|
||||
{{< notice note >}}
|
||||
Prebuilt tools are pre-1.0, so expect some tool changes between versions. LLMs
|
||||
will adapt to the tools available, so this shouldn't affect most users.
|
||||
{{< /notice >}}
|
||||
<html>
|
||||
<head>
|
||||
<link rel="canonical" href="https://cloud.google.com/firestore/native/docs/connect-ide-using-mcp-toolbox"/>
|
||||
<meta http-equiv="refresh" content="0;url=https://cloud.google.com/firestore/native/docs/connect-ide-using-mcp-toolbox"/>
|
||||
</head>
|
||||
</html>
|
||||
|
||||
@@ -48,19 +48,19 @@ to expose your developer assistant tools to a Looker instance:
|
||||
<!-- {x-release-please-start-version} -->
|
||||
{{< tabpane persist=header >}}
|
||||
{{< tab header="linux/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/linux/amd64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/linux/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/arm64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/darwin/arm64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/darwin/arm64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/darwin/amd64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/darwin/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="windows/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/windows/amd64/toolbox.exe
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/windows/amd64/toolbox.exe
|
||||
{{< /tab >}}
|
||||
{{< /tabpane >}}
|
||||
<!-- {x-release-please-end} -->
|
||||
@@ -235,7 +235,7 @@ curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/windows/amd64/toolb
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"servers": {
|
||||
"looker-toolbox": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--stdio", "--prebuilt", "looker"],
|
||||
|
||||
@@ -37,19 +37,19 @@ description: "Connect your IDE to SQL Server using Toolbox."
|
||||
<!-- {x-release-please-start-version} -->
|
||||
{{< tabpane persist=header >}}
|
||||
{{< tab header="linux/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/linux/amd64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/linux/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/arm64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/darwin/arm64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/darwin/arm64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/darwin/amd64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/darwin/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="windows/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/windows/amd64/toolbox.exe
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/windows/amd64/toolbox.exe
|
||||
{{< /tab >}}
|
||||
{{< /tabpane >}}
|
||||
<!-- {x-release-please-end} -->
|
||||
@@ -182,19 +182,17 @@ curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/windows/amd64/toolb
|
||||
|
||||
```json
|
||||
{
|
||||
"mcp" : {
|
||||
"servers": {
|
||||
"cloud-sql-sqlserver": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","cloud-sql-mssql","--stdio"],
|
||||
"env": {
|
||||
"MSSQL_HOST": "",
|
||||
"MSSQL_PORT": "",
|
||||
"MSSQL_DATABASE": "",
|
||||
"MSSQL_USER": "",
|
||||
"MSSQL_PASSWORD": ""
|
||||
}
|
||||
}
|
||||
"servers": {
|
||||
"mssql": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","mssql","--stdio"],
|
||||
"env": {
|
||||
"MSSQL_HOST": "",
|
||||
"MSSQL_PORT": "",
|
||||
"MSSQL_DATABASE": "",
|
||||
"MSSQL_USER": "",
|
||||
"MSSQL_PASSWORD": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,4 +284,4 @@ The following tools are available to the LLM:
|
||||
|
||||
{{< notice note >}}
|
||||
Prebuilt tools are pre-1.0, so expect some tool changes between versions. LLMs will adapt to the tools available, so this shouldn't affect most users.
|
||||
{{< /notice >}}
|
||||
{{< /notice >}}
|
||||
|
||||
@@ -37,19 +37,19 @@ description: "Connect your IDE to MySQL using Toolbox."
|
||||
<!-- {x-release-please-start-version} -->
|
||||
{{< tabpane persist=header >}}
|
||||
{{< tab header="linux/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/linux/amd64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/linux/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/arm64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/darwin/arm64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/darwin/arm64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/darwin/amd64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/darwin/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="windows/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/windows/amd64/toolbox.exe
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/windows/amd64/toolbox.exe
|
||||
{{< /tab >}}
|
||||
{{< /tabpane >}}
|
||||
<!-- {x-release-please-end} -->
|
||||
@@ -182,7 +182,7 @@ curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/windows/amd64/toolb
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"servers": {
|
||||
"mysql": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","mysql","--stdio"],
|
||||
|
||||
281
docs/en/how-to/connect-ide/neo4j_mcp.md
Normal file
281
docs/en/how-to/connect-ide/neo4j_mcp.md
Normal file
@@ -0,0 +1,281 @@
|
||||
---
|
||||
title: Neo4j using MCP
|
||||
type: docs
|
||||
weight: 2
|
||||
description: "Connect your IDE to Neo4j using Toolbox."
|
||||
---
|
||||
|
||||
[Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) is an open protocol for connecting Large Language Models (LLMs) to data sources like Neo4j. This guide covers how to use [MCP Toolbox for Databases][toolbox] to expose your developer assistant tools to a Neo4j instance:
|
||||
|
||||
* [Cursor][cursor]
|
||||
* [Windsurf][windsurf] (Codium)
|
||||
* [Visual Studio Code][vscode] (Copilot)
|
||||
* [Cline][cline] (VS Code extension)
|
||||
* [Claude desktop][claudedesktop]
|
||||
* [Claude code][claudecode]
|
||||
* [Gemini CLI][geminicli]
|
||||
* [Gemini Code Assist][geminicodeassist]
|
||||
|
||||
[toolbox]: https://github.com/googleapis/genai-toolbox
|
||||
[cursor]: #configure-your-mcp-client
|
||||
[windsurf]: #configure-your-mcp-client
|
||||
[vscode]: #configure-your-mcp-client
|
||||
[cline]: #configure-your-mcp-client
|
||||
[claudedesktop]: #configure-your-mcp-client
|
||||
[claudecode]: #configure-your-mcp-client
|
||||
[geminicli]: #configure-your-mcp-client
|
||||
[geminicodeassist]: #configure-your-mcp-client
|
||||
|
||||
## Set up the database
|
||||
|
||||
1. [Create or select a Neo4j instance.](https://neo4j.com/cloud/platform/aura-graph-database/)
|
||||
|
||||
## Install MCP Toolbox
|
||||
|
||||
1. Download the latest version of Toolbox as a binary. Select the [correct binary](https://github.com/googleapis/genai-toolbox/releases) corresponding to your OS and CPU architecture. You are required to use Toolbox version v0.15.0+:
|
||||
|
||||
<!-- {x-release-please-start-version} -->
|
||||
{{< tabpane persist=header >}}
|
||||
{{< tab header="linux/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.15.0/linux/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/arm64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.15.0/darwin/arm64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.15.0/darwin/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="windows/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.15.0/windows/amd64/toolbox.exe
|
||||
{{< /tab >}}
|
||||
{{< /tabpane >}}
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
1. Make the binary executable:
|
||||
|
||||
```bash
|
||||
chmod +x toolbox
|
||||
```
|
||||
|
||||
1. Verify the installation:
|
||||
|
||||
```bash
|
||||
./toolbox --version
|
||||
```
|
||||
|
||||
## Configure your MCP Client
|
||||
|
||||
{{< tabpane text=true >}}
|
||||
{{% tab header="Claude code" lang="en" %}}
|
||||
|
||||
1. Install [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview).
|
||||
1. Create a `.mcp.json` file in your project root if it doesn't exist.
|
||||
1. Add the following configuration, replace the environment variables with your values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"neo4j": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","neo4j","--stdio"],
|
||||
"env": {
|
||||
"NEO4J_URI": "",
|
||||
"NEO4J_DATABASE": "",
|
||||
"NEO4J_USERNAME": "",
|
||||
"NEO4J_PASSWORD": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Restart Claude code to apply the new configuration.
|
||||
{{% /tab %}}
|
||||
{{% tab header="Claude desktop" lang="en" %}}
|
||||
|
||||
1. Open [Claude desktop](https://claude.ai/download) and navigate to Settings.
|
||||
1. Under the Developer tab, tap Edit Config to open the configuration file.
|
||||
1. Add the following configuration, replace the environment variables with your values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"neo4j": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","neo4j","--stdio"],
|
||||
"env": {
|
||||
"NEO4J_URI": "",
|
||||
"NEO4J_DATABASE": "",
|
||||
"NEO4J_USERNAME": "",
|
||||
"NEO4J_PASSWORD": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Restart Claude desktop.
|
||||
1. From the new chat screen, you should see a hammer (MCP) icon appear with the new MCP server available.
|
||||
{{% /tab %}}
|
||||
{{% tab header="Cline" lang="en" %}}
|
||||
|
||||
1. Open the [Cline](https://github.com/cline/cline) extension in VS Code and tap the **MCP Servers** icon.
|
||||
1. Tap Configure MCP Servers to open the configuration file.
|
||||
1. Add the following configuration, replace the environment variables with your values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"neo4j": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","neo4j","--stdio"],
|
||||
"env": {
|
||||
"NEO4J_URI": "",
|
||||
"NEO4J_DATABASE": "",
|
||||
"NEO4J_USERNAME": "",
|
||||
"NEO4J_PASSWORD": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. You should see a green active status after the server is successfully connected.
|
||||
{{% /tab %}}
|
||||
{{% tab header="Cursor" lang="en" %}}
|
||||
|
||||
1. Create a `.cursor` directory in your project root if it doesn't exist.
|
||||
1. Create a `.cursor/mcp.json` file if it doesn't exist and open it.
|
||||
1. Add the following configuration, replace the environment variables with your values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"neo4j": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","neo4j","--stdio"],
|
||||
"env": {
|
||||
"NEO4J_URI": "",
|
||||
"NEO4J_DATABASE": "",
|
||||
"NEO4J_USERNAME": "",
|
||||
"NEO4J_PASSWORD": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Open [Cursor](https://www.cursor.com/) and navigate to **Settings > Cursor Settings > MCP**. You should see a green active status after the server is successfully connected.
|
||||
{{% /tab %}}
|
||||
{{% tab header="Visual Studio Code (Copilot)" lang="en" %}}
|
||||
|
||||
1. Open [VS Code](https://code.visualstudio.com/docs/copilot/overview) and create a `.vscode` directory in your project root if it doesn't exist.
|
||||
1. Create a `.vscode/mcp.json` file if it doesn't exist and open it.
|
||||
1. Add the following configuration, replace the environment variables with your values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcp" : {
|
||||
"servers": {
|
||||
"neo4j": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","neo4j","--stdio"],
|
||||
"env": {
|
||||
"NEO4J_URI": "",
|
||||
"NEO4J_DATABASE": "",
|
||||
"NEO4J_USERNAME": "",
|
||||
"NEO4J_PASSWORD": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{% tab header="Windsurf" lang="en" %}}
|
||||
|
||||
1. Open [Windsurf](https://docs.codeium.com/windsurf) and navigate to the Cascade assistant.
|
||||
1. Tap on the hammer (MCP) icon, then Configure to open the configuration file.
|
||||
1. Add the following configuration, replace the environment variables with your values, and save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"neo4j": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","neo4j","--stdio"],
|
||||
"env": {
|
||||
"NEO4J_URI": "",
|
||||
"NEO4J_DATABASE": "",
|
||||
"NEO4J_USERNAME": "",
|
||||
"NEO4J_PASSWORD": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{% tab header="Gemini CLI" lang="en" %}}
|
||||
|
||||
1. Install the [Gemini CLI](https://github.com/google-gemini/gemini-cli?tab=readme-ov-file#quickstart).
|
||||
1. In your working directory, create a folder named `.gemini`. Within it, create a `settings.json` file.
|
||||
1. Add the following configuration, replace the environment variables with your values, and then save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"neo4j": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","neo4j","--stdio"],
|
||||
"env": {
|
||||
"NEO4J_URI": "",
|
||||
"NEO4J_DATABASE": "",
|
||||
"NEO4J_USERNAME": "",
|
||||
"NEO4J_PASSWORD": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{% tab header="Gemini Code Assist" lang="en" %}}
|
||||
|
||||
1. Install the [Gemini Code Assist](https://marketplace.visualstudio.com/items?itemName=Google.geminicodeassist) extension in Visual Studio Code.
|
||||
1. Enable Agent Mode in Gemini Code Assist chat.
|
||||
1. In your working directory, create a folder named `.gemini`. Within it, create a `settings.json` file.
|
||||
1. Add the following configuration, replace the environment variables with your values, and then save:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"neo4j": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","neo4j","--stdio"],
|
||||
"env": {
|
||||
"NEO4J_URI": "",
|
||||
"NEO4J_DATABASE": "",
|
||||
"NEO4J_USERNAME": "",
|
||||
"NEO4J_PASSWORD": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{< /tabpane >}}
|
||||
|
||||
## Use Tools
|
||||
|
||||
Your AI tool is now connected to Neo4j using MCP. Try asking your AI assistant to get the graph schema or execute Cypher statements.
|
||||
|
||||
The following tools are available to the LLM:
|
||||
|
||||
1. **get_schema**: extracts the complete database schema, including details about node labels, relationships, properties, constraints, and indexes.
|
||||
1. **execute_cypher**: executes any arbitrary Cypher statement.
|
||||
|
||||
{{< notice note >}}
|
||||
Prebuilt tools are pre-1.0, so expect some tool changes between versions. LLMs will adapt to the tools available, so this shouldn't affect most users.
|
||||
{{< /notice >}}
|
||||
@@ -56,19 +56,19 @@ Omni](https://cloud.google.com/alloydb/omni/current/docs/overview).
|
||||
<!-- {x-release-please-start-version} -->
|
||||
{{< tabpane persist=header >}}
|
||||
{{< tab header="linux/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/linux/amd64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/linux/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/arm64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/darwin/arm64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/darwin/arm64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="darwin/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/darwin/amd64/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/darwin/amd64/toolbox
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab header="windows/amd64" lang="bash" >}}
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/windows/amd64/toolbox.exe
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/windows/amd64/toolbox.exe
|
||||
{{< /tab >}}
|
||||
{{< /tabpane >}}
|
||||
<!-- {x-release-please-end} -->
|
||||
@@ -217,7 +217,7 @@ curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/windows/amd64/toolb
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"servers": {
|
||||
"postgres": {
|
||||
"command": "./PATH/TO/toolbox",
|
||||
"args": ["--prebuilt","postgres","--stdio"],
|
||||
|
||||
@@ -19,8 +19,9 @@ See guides, [Connect from your IDE](../how-to/connect-ide/_index.md), for detail
|
||||
* `ALLOYDB_POSTGRES_CLUSTER`: The ID of your AlloyDB cluster.
|
||||
* `ALLOYDB_POSTGRES_INSTANCE`: The ID of your AlloyDB instance.
|
||||
* `ALLOYDB_POSTGRES_DATABASE`: The name of the database to connect to.
|
||||
* `ALLOYDB_POSTGRES_USER`: The database username.
|
||||
* `ALLOYDB_POSTGRES_PASSWORD`: The password for the database user.
|
||||
* `ALLOYDB_POSTGRES_USER`: (Optional) The database username. Defaults to IAM authentication if unspecified.
|
||||
* `ALLOYDB_POSTGRES_PASSWORD`: (Optional) The password for the database user. Defaults to IAM authentication if unspecified.
|
||||
* `ALLOYDB_POSTGRES_IP_TYPE`: (Optional) The IP type i.e. "Public" or "Private" (Default: Public).
|
||||
* **Permissions:**
|
||||
* **AlloyDB Client** (`roles/alloydb.client`) to connect to the instance.
|
||||
* Database-level permissions (e.g., `SELECT`, `INSERT`) are required to execute queries.
|
||||
@@ -49,12 +50,16 @@ See guides, [Connect from your IDE](../how-to/connect-ide/_index.md), for detail
|
||||
* `--prebuilt` value: `bigquery`
|
||||
* **Environment Variables:**
|
||||
* `BIGQUERY_PROJECT`: The GCP project ID.
|
||||
* `BIGQUERY_LOCATION`: (Optional) The dataset location.
|
||||
* **Permissions:**
|
||||
* **BigQuery User** (`roles/bigquery.user`) to execute queries and view metadata.
|
||||
* **BigQuery Metadata Viewer** (`roles/bigquery.metadataViewer`) to view all datasets.
|
||||
* **BigQuery Data Editor** (`roles/bigquery.dataEditor`) to create or modify datasets and tables.
|
||||
* **Gemini for Google Cloud** (`roles/cloudaicompanion.user`) to use the conversational analytics API.
|
||||
* **Tools:**
|
||||
* `ask_data_insights`: Use this tool to perform data analysis, get insights, or answer complex questions about the contents of specific BigQuery tables. For more information on required roles, API setup, and IAM configuration, see the setup and authentication section of the [Conversational Analytics API documentation](https://cloud.google.com/gemini/docs/conversational-analytics-api/overview).
|
||||
* `execute_sql`: Executes a SQL statement.
|
||||
* `forecast`: Use this tool to forecast time series data.
|
||||
* `get_dataset_info`: Gets dataset metadata.
|
||||
* `get_table_info`: Gets table metadata.
|
||||
* `list_dataset_ids`: Lists datasets.
|
||||
@@ -70,6 +75,8 @@ See guides, [Connect from your IDE](../how-to/connect-ide/_index.md), for detail
|
||||
* `CLOUD_SQL_MYSQL_DATABASE`: The name of the database to connect to.
|
||||
* `CLOUD_SQL_MYSQL_USER`: The database username.
|
||||
* `CLOUD_SQL_MYSQL_PASSWORD`: The password for the database user.
|
||||
* `CLOUD_SQL_MYSQL_IP_TYPE`: The IP type i.e. "Public
|
||||
or "Private" (Default: Public).
|
||||
* **Permissions:**
|
||||
* **Cloud SQL Client** (`roles/cloudsql.client`) to connect to the instance.
|
||||
* Database-level permissions (e.g., `SELECT`, `INSERT`) are required to execute queries.
|
||||
@@ -85,8 +92,9 @@ See guides, [Connect from your IDE](../how-to/connect-ide/_index.md), for detail
|
||||
* `CLOUD_SQL_POSTGRES_REGION`: The region of your Cloud SQL instance.
|
||||
* `CLOUD_SQL_POSTGRES_INSTANCE`: The ID of your Cloud SQL instance.
|
||||
* `CLOUD_SQL_POSTGRES_DATABASE`: The name of the database to connect to.
|
||||
* `CLOUD_SQL_POSTGRES_USER`: The database username.
|
||||
* `CLOUD_SQL_POSTGRES_PASSWORD`: The password for the database user.
|
||||
* `CLOUD_SQL_POSTGRES_USER`: (Optional) The database username. Defaults to IAM authentication if unspecified.
|
||||
* `CLOUD_SQL_POSTGRES_PASSWORD`: (Optional) The password for the database user. Defaults to IAM authentication if unspecified.
|
||||
* `CLOUD_SQL_POSTGRES_IP_TYPE`: (Optional) The IP type i.e. "Public" or "Private" (Default: Public).
|
||||
* **Permissions:**
|
||||
* **Cloud SQL Client** (`roles/cloudsql.client`) to connect to the instance.
|
||||
* Database-level permissions (e.g., `SELECT`, `INSERT`) are required to execute queries.
|
||||
@@ -105,6 +113,7 @@ See guides, [Connect from your IDE](../how-to/connect-ide/_index.md), for detail
|
||||
* `CLOUD_SQL_MSSQL_IP_ADDRESS`: The IP address of the Cloud SQL instance.
|
||||
* `CLOUD_SQL_MSSQL_USER`: The database username.
|
||||
* `CLOUD_SQL_MSSQL_PASSWORD`: The password for the database user.
|
||||
* `CLOUD_SQL_MSSQL_IP_TYPE`: (Optional) The IP type i.e. "Public" or "Private" (Default: Public).
|
||||
* **Permissions:**
|
||||
* **Cloud SQL Client** (`roles/cloudsql.client`) to connect to the instance.
|
||||
* Database-level permissions (e.g., `SELECT`, `INSERT`) are required to execute queries.
|
||||
@@ -130,7 +139,7 @@ See guides, [Connect from your IDE](../how-to/connect-ide/_index.md), for detail
|
||||
* `--prebuilt` value: `firestore`
|
||||
* **Environment Variables:**
|
||||
* `FIRESTORE_PROJECT`: The GCP project ID.
|
||||
* `FIRESTORE_DATABASE`: The Firestore database ID.
|
||||
* `FIRESTORE_DATABASE`: (Optional) The Firestore database ID. Defaults to "(default)".
|
||||
* **Permissions:**
|
||||
* **Cloud Datastore User** (`roles/datastore.user`) to get documents, list collections, and query collections.
|
||||
* **Firebase Rules Viewer** (`roles/firebaserules.viewer`) to get and validate Firestore rules.
|
||||
@@ -223,6 +232,7 @@ See guides, [Connect from your IDE](../how-to/connect-ide/_index.md), for detail
|
||||
* `POSTGRES_DATABASE`: The name of the database to connect to.
|
||||
* `POSTGRES_USER`: The database username.
|
||||
* `POSTGRES_PASSWORD`: The password for the database user.
|
||||
* `POSTGRES_QUERY_PARAMS`: (Optional) Raw query to be added to the db connection string.
|
||||
* **Permissions:**
|
||||
* Database-level permissions (e.g., `SELECT`, `INSERT`) are required to execute queries.
|
||||
* **Tools:**
|
||||
@@ -258,3 +268,17 @@ See guides, [Connect from your IDE](../how-to/connect-ide/_index.md), for detail
|
||||
* `execute_sql`: Executes a DML SQL query using the PostgreSQL interface for Spanner.
|
||||
* `execute_sql_dql`: Executes a DQL SQL query using the PostgreSQL interface for Spanner.
|
||||
* `list_tables`: Lists tables in the database.
|
||||
|
||||
## Neo4j
|
||||
|
||||
* `--prebuilt` value: `neo4j`
|
||||
* **Environment Variables:**
|
||||
* `NEO4J_URI`: The URI of the Neo4j instance (e.g., `bolt://localhost:7687`).
|
||||
* `NEO4J_DATABASE`: The name of the Neo4j database to connect to.
|
||||
* `NEO4J_USERNAME`: The username for the Neo4j instance.
|
||||
* `NEO4J_PASSWORD`: The password for the Neo4j instance.
|
||||
* **Permissions:**
|
||||
* **Database-level permissions** are required to execute Cypher queries.
|
||||
* **Tools:**
|
||||
* `execute_cypher`: Executes a Cypher query.
|
||||
* `get_schema`: Retrieves the schema of the Neo4j database.
|
||||
|
||||
36
docs/en/resources/sources/alloydb-admin.md
Normal file
36
docs/en/resources/sources/alloydb-admin.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: "AlloyDB Admin"
|
||||
linkTitle: "AlloyDB Admin"
|
||||
type: docs
|
||||
weight: 2
|
||||
description: >
|
||||
The "alloydb-admin" source provides a client for the AlloyDB API.
|
||||
aliases:
|
||||
- /resources/sources/alloydb-admin
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
The `alloydb-admin` source provides a client to interact with the [Google AlloyDB API](https://cloud.google.com/alloydb/docs/reference/rest). This allows tools to perform administrative tasks on AlloyDB resources, such as managing clusters, instances, and users.
|
||||
|
||||
Authentication can be handled in two ways:
|
||||
1. **Application Default Credentials (ADC):** By default, the source uses ADC to authenticate with the API.
|
||||
2. **Client-side OAuth:** If `useClientOAuth` is set to `true`, the source will expect an OAuth 2.0 access token to be provided by the client (e.g., a web browser) for each request.
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
my-alloydb-admin:
|
||||
kind: alloy-admin
|
||||
|
||||
my-oauth-alloydb-admin:
|
||||
kind: alloydb-admin
|
||||
useClientOAuth: true
|
||||
```
|
||||
|
||||
## Reference
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|----------------|:--------:|:------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "alloydb-admin". |
|
||||
| useClientOAuth | boolean | false | If true, the source will use client-side OAuth for authorization. Otherwise, it will use Application Default Credentials. Defaults to `false`. |
|
||||
@@ -33,6 +33,9 @@ cluster][alloydb-free-trial].
|
||||
- [`postgres-execute-sql`](../tools/postgres/postgres-execute-sql.md)
|
||||
Run parameterized SQL statements in AlloyDB Postgres.
|
||||
|
||||
- [`postgres-list-tables`](../tools/postgres/postgres-list-tables.md)
|
||||
List tables in an AlloyDB for PostgreSQL database.
|
||||
|
||||
### Pre-built Configurations
|
||||
|
||||
- [AlloyDB using MCP](https://googleapis.github.io/genai-toolbox/how-to/connect-ide/alloydb_pg_mcp/)
|
||||
|
||||
@@ -36,12 +36,15 @@ avoiding full table scans or complex filters.
|
||||
|
||||
## Available Tools
|
||||
|
||||
- [`bigquery-sql`](../tools/bigquery/bigquery-sql.md)
|
||||
Run SQL queries directly against BigQuery datasets.
|
||||
- [`bigquery-conversational-analytics`](../tools/bigquery/bigquery-conversational-analytics.md)
|
||||
Allows conversational interaction with a BigQuery source.
|
||||
|
||||
- [`bigquery-execute-sql`](../tools/bigquery/bigquery-execute-sql.md)
|
||||
Execute structured queries using parameters.
|
||||
|
||||
- [`bigquery-forecast`](../tools/bigquery/bigquery-forecast.md)
|
||||
Forecasts time series data in BigQuery.
|
||||
|
||||
- [`bigquery-get-dataset-info`](../tools/bigquery/bigquery-get-dataset-info.md)
|
||||
Retrieve metadata for a specific dataset.
|
||||
|
||||
@@ -54,6 +57,9 @@ avoiding full table scans or complex filters.
|
||||
- [`bigquery-list-table-ids`](../tools/bigquery/bigquery-list-table-ids.md)
|
||||
List tables in a given dataset.
|
||||
|
||||
- [`bigquery-sql`](../tools/bigquery/bigquery-sql.md)
|
||||
Run SQL queries directly against BigQuery datasets.
|
||||
|
||||
### Pre-built Configurations
|
||||
|
||||
- [BigQuery using MCP](https://googleapis.github.io/genai-toolbox/how-to/connect-ide/bigquery_mcp/)
|
||||
@@ -65,34 +71,71 @@ Connect your IDE to BigQuery using Toolbox.
|
||||
|
||||
BigQuery uses [Identity and Access Management (IAM)][iam-overview] to control
|
||||
user and group access to BigQuery resources like projects, datasets, and tables.
|
||||
Toolbox will use your [Application Default Credentials (ADC)][adc] to authorize
|
||||
and authenticate when interacting with [BigQuery][bigquery-docs].
|
||||
|
||||
In addition to [setting the ADC for your server][set-adc], you need to ensure
|
||||
the IAM identity has been given the correct IAM permissions for the queries
|
||||
you intend to run. Common roles include `roles/bigquery.user` (which includes
|
||||
permissions to run jobs and read data) or `roles/bigquery.dataViewer`. See
|
||||
[Introduction to BigQuery IAM][grant-permissions] for more information on
|
||||
applying IAM permissions and roles to an identity.
|
||||
### Authentication via Application Default Credentials (ADC)
|
||||
|
||||
[iam-overview]: https://cloud.google.com/bigquery/docs/access-control
|
||||
[adc]: https://cloud.google.com/docs/authentication#adc
|
||||
[set-adc]: https://cloud.google.com/docs/authentication/provide-credentials-adc
|
||||
[grant-permissions]: https://cloud.google.com/bigquery/docs/access-control
|
||||
By **default**, Toolbox will use your [Application Default Credentials (ADC)][adc] to authorize and authenticate when interacting with [BigQuery][bigquery-docs].
|
||||
|
||||
## Example
|
||||
When using this method, you need to ensure the IAM identity associated with your
|
||||
ADC (such as a service account) has the correct permissions for the queries you
|
||||
intend to run. Common roles include `roles/bigquery.user` (which includes
|
||||
permissions to run jobs and read data) or `roles/bigbigquery.dataViewer`.
|
||||
Follow this [guide][set-adc] to set up your ADC.
|
||||
|
||||
#### Example (ADC)
|
||||
|
||||
Initialize a BigQuery source that uses ADC:
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
my-bigquery-source:
|
||||
kind: "bigquery"
|
||||
project: "my-project-id"
|
||||
# location: "US" # Optional: Specifies the location for query jobs.
|
||||
# allowedDatasets: # Optional: Restricts tool access to a specific list of datasets.
|
||||
# - "my_dataset_1"
|
||||
# - "other_project.my_dataset_2"
|
||||
```
|
||||
|
||||
### Authentication via User's OAuth Access Token
|
||||
|
||||
If the `useClientOAuth` parameter is set to `true`, Toolbox will instead use the
|
||||
OAuth access token for authentication. This token is parsed from the
|
||||
`Authorization` header passed in with the tool invocation request. This method
|
||||
allows Toolbox to make queries to [BigQuery][bigquery-docs] on behalf of the
|
||||
client or the end-user.
|
||||
|
||||
When using this on-behalf-of authentication, you must ensure that the
|
||||
identity used has been granted the correct IAM permissions.
|
||||
|
||||
[iam-overview]: <https://cloud.google.com/bigquery/docs/access-control>
|
||||
[adc]: <https://cloud.google.com/docs/authentication#adc>
|
||||
[set-adc]: <https://cloud.google.com/docs/authentication/provide-credentials-adc>
|
||||
|
||||
#### Example (Client OAuth)
|
||||
|
||||
Initialize a BigQuery source that uses the client's access token:
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
my-bigquery-client-auth-source:
|
||||
kind: "bigquery"
|
||||
project: "my-project-id"
|
||||
useClientOAuth: true
|
||||
# location: "US" # Optional: Specifies the location for query jobs.
|
||||
# allowedDatasets: # Optional: Restricts tool access to a specific list of datasets.
|
||||
# - "my_dataset_1"
|
||||
# - "other_project.my_dataset_2"
|
||||
```
|
||||
|
||||
To connect to Gemini CLI using the client OAuth feature, you can follow this step-by-step [guide](../../samples/bigquery/bigquery_gemini_cli_client_oauth/_index.md).
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-----------|:--------:|:------------:|-------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "bigquery". |
|
||||
| project | string | true | Id of the GCP project that the cluster was created in (e.g. "my-project-id"). |
|
||||
| location | string | false | Specifies the location (e.g., 'us', 'asia-northeast1') in which to run the query job. This location must match the location of any tables referenced in the query. The default behavior is for it to be executed in the US multi-region |
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|----------------|:--------:|:------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "bigquery". |
|
||||
| project | string | true | Id of the Google Cloud project to use for billing and as the default project for BigQuery resources. |
|
||||
| location | string | false | Specifies the location (e.g., 'us', 'asia-northeast1') in which to run the query job. This location must match the location of any tables referenced in the query. Defaults to the table's location or 'US' if the location cannot be determined. [Learn More](https://cloud.google.com/bigquery/docs/locations) |
|
||||
| allowedDatasets | []string | false | An optional list of dataset IDs that tools using this source are allowed to access. If provided, any tool operation attempting to access a dataset not in this list will be rejected. To enforce this, two types of operations are also disallowed: 1) Dataset-level operations (e.g., `CREATE SCHEMA`), and 2) operations where table access cannot be statically analyzed (e.g., `EXECUTE IMMEDIATE`, `CREATE PROCEDURE`). If a single dataset is provided, it will be treated as the default for prebuilt tools. |
|
||||
| useClientOAuth | bool | false | If true, forwards the client's OAuth access token from the "Authorization" header to downstream queries. |
|
||||
|
||||
91
docs/en/resources/sources/clickhouse.md
Normal file
91
docs/en/resources/sources/clickhouse.md
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
title: "ClickHouse"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
ClickHouse is an open-source, OLTP database.
|
||||
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
[ClickHouse][clickhouse-docs] is a fast, open-source, column-oriented database
|
||||
|
||||
[clickhouse-docs]: https://clickhouse.com/docs
|
||||
|
||||
## Available Tools
|
||||
|
||||
- [`clickhouse-execute-sql`](../tools/clickhouse/clickhouse-execute-sql.md)
|
||||
Execute parameterized SQL queries in ClickHouse with query logging.
|
||||
|
||||
- [`clickhouse-sql`](../tools/clickhouse/clickhouse-sql.md)
|
||||
Execute SQL queries as prepared statements in ClickHouse.
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
### Database User
|
||||
|
||||
This source uses standard ClickHouse authentication. You will need to [create a
|
||||
ClickHouse user][clickhouse-users] (or with [ClickHouse Cloud][clickhouse-cloud]) to connect to the database with. The user
|
||||
should have appropriate permissions for the operations you plan to perform.
|
||||
|
||||
[clickhouse-cloud]: https://clickhouse.com/docs/getting-started/quick-start/cloud#connect-with-your-app
|
||||
[clickhouse-users]: https://clickhouse.com/docs/en/sql-reference/statements/create/user
|
||||
|
||||
### Network Access
|
||||
|
||||
ClickHouse supports multiple protocols:
|
||||
|
||||
- **HTTPS protocol** (default port 8443) - Secure HTTP access (default)
|
||||
- **HTTP protocol** (default port 8123) - Good for web-based access
|
||||
|
||||
## Example
|
||||
|
||||
### Secure Connection Example
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
secure-clickhouse-source:
|
||||
kind: clickhouse
|
||||
host: clickhouse.example.com
|
||||
port: "8443"
|
||||
database: analytics
|
||||
user: ${CLICKHOUSE_USER}
|
||||
password: ${CLICKHOUSE_PASSWORD}
|
||||
protocol: https
|
||||
secure: true
|
||||
```
|
||||
|
||||
### HTTP Protocol Example
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
http-clickhouse-source:
|
||||
kind: clickhouse
|
||||
host: localhost
|
||||
port: "8123"
|
||||
database: logs
|
||||
user: ${CLICKHOUSE_USER}
|
||||
password: ${CLICKHOUSE_PASSWORD}
|
||||
protocol: http
|
||||
secure: false
|
||||
```
|
||||
|
||||
{{< notice tip >}}
|
||||
Use environment variable replacement with the format ${ENV_NAME}
|
||||
instead of hardcoding your secrets into the configuration file.
|
||||
{{< /notice >}}
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-------------|:--------:|:------------:|------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "clickhouse". |
|
||||
| host | string | true | IP address or hostname to connect to (e.g. "127.0.0.1" or "clickhouse.example.com") |
|
||||
| port | string | true | Port to connect to (e.g. "8443" for HTTPS, "8123" for HTTP) |
|
||||
| database | string | true | Name of the ClickHouse database to connect to (e.g. "my_database"). |
|
||||
| user | string | true | Name of the ClickHouse user to connect as (e.g. "analytics_user"). |
|
||||
| password | string | false | Password of the ClickHouse user (e.g. "my-password"). |
|
||||
| protocol | string | false | Connection protocol: "https" (default) or "http". |
|
||||
| secure | boolean | false | Whether to use a secure connection (TLS). Default: false. |
|
||||
36
docs/en/resources/sources/cloud-monitoring.md
Normal file
36
docs/en/resources/sources/cloud-monitoring.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: "Cloud Monitoring"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "cloud-monitoring" source provides a client for the Cloud Monitoring API.
|
||||
aliases:
|
||||
- /resources/sources/cloud-monitoring
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
The `cloud-monitoring` source provides a client to interact with the [Google Cloud Monitoring API](https://cloud.google.com/monitoring/api). This allows tools to access cloud monitoring metrics explorer and run promql queries.
|
||||
|
||||
Authentication can be handled in two ways:
|
||||
1. **Application Default Credentials (ADC):** By default, the source uses ADC to authenticate with the API.
|
||||
2. **Client-side OAuth:** If `useClientOAuth` is set to `true`, the source will expect an OAuth 2.0 access token to be provided by the client (e.g., a web browser) for each request.
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
my-cloud-monitoring:
|
||||
kind: cloud-monitoring
|
||||
|
||||
my-oauth-cloud-monitoring:
|
||||
kind: cloud-monitoring
|
||||
useClientOAuth: true
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|----------------|:--------:|:------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "cloud-monitoring". |
|
||||
| useClientOAuth | boolean | false | If true, the source will use client-side OAuth for authorization. Otherwise, it will use Application Default Credentials. Defaults to `false`. |
|
||||
36
docs/en/resources/sources/cloud-sql-admin.md
Normal file
36
docs/en/resources/sources/cloud-sql-admin.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: "Cloud SQL Admin"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "cloud-sql-admin" source provides a client for the Cloud SQL Admin API.
|
||||
aliases:
|
||||
- /resources/sources/cloud-sql-admin
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
The `cloud-sql-admin` source provides a client to interact with the [Google Cloud SQL Admin API](https://cloud.google.com/sql/docs/mysql/admin-api/v1). This allows tools to perform administrative tasks on Cloud SQL instances, such as creating users and databases.
|
||||
|
||||
Authentication can be handled in two ways:
|
||||
1. **Application Default Credentials (ADC):** By default, the source uses ADC to authenticate with the API.
|
||||
2. **Client-side OAuth:** If `useClientOAuth` is set to `true`, the source will expect an OAuth 2.0 access token to be provided by the client (e.g., a web browser) for each request.
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
my-cloud-sql-admin:
|
||||
kind: cloud-sql-admin
|
||||
|
||||
my-oauth-cloud-sql-admin:
|
||||
kind: cloud-sql-admin
|
||||
useClientOAuth: true
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|----------------|:--------:|:------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "cloud-sql-admin". |
|
||||
| useClientOAuth | boolean | false | If true, the source will use client-side OAuth for authorization. Otherwise, it will use Application Default Credentials. Defaults to `false`. |
|
||||
@@ -28,6 +28,9 @@ to a database by following these instructions][csql-mysql-quickstart].
|
||||
- [`mysql-execute-sql`](../tools/mysql/mysql-execute-sql.md)
|
||||
Run parameterized SQL queries in Cloud SQL for MySQL.
|
||||
|
||||
- [`mysql-list-tables`](../tools/mysql/mysql-list-tables.md)
|
||||
List tables in a Cloud SQL for MySQL database.
|
||||
|
||||
### Pre-built Configurations
|
||||
|
||||
- [Cloud SQL for MySQL using MCP](https://googleapis.github.io/genai-toolbox/how-to/connect-ide/cloud_sql_mysql_mcp/)
|
||||
|
||||
@@ -28,6 +28,9 @@ to a database by following these instructions][csql-pg-quickstart].
|
||||
- [`postgres-execute-sql`](../tools/postgres/postgres-execute-sql.md)
|
||||
Run parameterized SQL statements in PostgreSQL.
|
||||
|
||||
- [`postgres-list-tables`](../tools/postgres/postgres-list-tables.md)
|
||||
List tables in a PostgreSQL database.
|
||||
|
||||
### Pre-built Configurations
|
||||
|
||||
- [Cloud SQL for Postgres using MCP](https://googleapis.github.io/genai-toolbox/how-to/connect-ide/cloud_sql_pg_mcp/)
|
||||
|
||||
@@ -47,7 +47,8 @@ a self-signed ssl certificate for the Looker server. Anything other than "true"
|
||||
will be interpreted as false.
|
||||
|
||||
The client id and client secret are seemingly random character sequences
|
||||
assigned by the looker server.
|
||||
assigned by the looker server. If you are using Looker OAuth you don't need
|
||||
these settings
|
||||
|
||||
{{< notice tip >}}
|
||||
Use environment variable replacement with the format ${ENV_NAME}
|
||||
@@ -56,11 +57,15 @@ instead of hardcoding your secrets into the configuration file.
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
| ------------- | :------: | :----------: | ----------------------------------------------------------------------------------------- |
|
||||
| kind | string | true | Must be "looker". |
|
||||
| base_url | string | true | The URL of your Looker server with no trailing /). |
|
||||
| client_id | string | true | The client id assigned by Looker. |
|
||||
| client_secret | string | true | The client secret assigned by Looker. |
|
||||
| verify_ssl | string | true | Whether to check the ssl certificate of the server. |
|
||||
| timeout | string | false | Maximum time to wait for query execution (e.g. "30s", "2m"). By default, 120s is applied. |
|
||||
| **field** | **type** | **required** | **description** |
|
||||
| -------------------- | :------: | :----------: | ----------------------------------------------------------------------------------------- |
|
||||
| kind | string | true | Must be "looker". |
|
||||
| base_url | string | true | The URL of your Looker server with no trailing /). |
|
||||
| client_id | string | false | The client id assigned by Looker. |
|
||||
| client_secret | string | false | The client secret assigned by Looker. |
|
||||
| verify_ssl | string | false | Whether to check the ssl certificate of the server. |
|
||||
| timeout | string | false | Maximum time to wait for query execution (e.g. "30s", "2m"). By default, 120s is applied. |
|
||||
| use_client_oauth | string | false | Use OAuth tokens instead of client_id and client_secret. (default: false) |
|
||||
| show_hidden_models | string | false | Show or hide hidden models. (default: true) |
|
||||
| show_hidden_explores | string | false | Show or hide hidden explores. (default: true) |
|
||||
| show_hidden_fields | string | false | Show or hide hidden fields. (default: true) |
|
||||
|
||||
@@ -22,6 +22,9 @@ reliability, performance, and ease of use.
|
||||
- [`mysql-execute-sql`](../tools/mysql/mysql-execute-sql.md)
|
||||
Run parameterized SQL queries in MySQL.
|
||||
|
||||
- [`mysql-list-tables`](../tools/mysql/mysql-list-tables.md)
|
||||
List tables in a MySQL database.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Database User
|
||||
@@ -42,6 +45,9 @@ sources:
|
||||
database: my_db
|
||||
user: ${USER_NAME}
|
||||
password: ${PASSWORD}
|
||||
# Optional TLS and other driver parameters. For example, enable preferred TLS:
|
||||
# queryParams:
|
||||
# tls: preferred
|
||||
queryTimeout: 30s # Optional: query timeout duration
|
||||
```
|
||||
|
||||
@@ -61,3 +67,4 @@ instead of hardcoding your secrets into the configuration file.
|
||||
| user | string | true | Name of the MySQL user to connect as (e.g. "my-mysql-user"). |
|
||||
| password | string | true | Password of the MySQL user (e.g. "my-password"). |
|
||||
| queryTimeout | string | false | Maximum time to wait for query execution (e.g. "30s", "2m"). By default, no timeout is applied. |
|
||||
| queryParams | map<string,string> | false | Arbitrary DSN parameters passed to the driver (e.g. `tls: preferred`, `charset: utf8mb4`). Useful for enabling TLS or other connection options. |
|
||||
|
||||
@@ -23,6 +23,9 @@ reputation for reliability, feature robustness, and performance.
|
||||
- [`postgres-execute-sql`](../tools/postgres/postgres-execute-sql.md)
|
||||
Run parameterized SQL statements in PostgreSQL.
|
||||
|
||||
- [`postgres-list-tables`](../tools/postgres/postgres-list-tables.md)
|
||||
List tables in a PostgreSQL database.
|
||||
|
||||
### Pre-built Configurations
|
||||
|
||||
- [PostgreSQL using MCP](https://googleapis.github.io/genai-toolbox/how-to/connect-ide/postgres_mcp/)
|
||||
|
||||
44
docs/en/resources/sources/yugabytedb.md
Normal file
44
docs/en/resources/sources/yugabytedb.md
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: "YugabyteDB"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
YugabyteDB is a high-performance, distributed SQL database.
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
[YugabyteDB][yugabytedb] is a high-performance, distributed SQL database designed for global, internet-scale applications, with full PostgreSQL compatibility.
|
||||
|
||||
[yugabytedb]: https://www.yugabyte.com/
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
my-yb-source:
|
||||
kind: yugabytedb
|
||||
host: 127.0.0.1
|
||||
port: 5433
|
||||
database: yugabyte
|
||||
user: ${USER_NAME}
|
||||
password: ${PASSWORD}
|
||||
loadBalance: true
|
||||
topologyKeys: cloud.region.zone1:1,cloud.region.zone2:2
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-----------------------------------|:--------:|:------------:|------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "yugabytedb". |
|
||||
| host | string | true | IP address to connect to. |
|
||||
| port | integer | true | Port to connect to. The default port is 5433. |
|
||||
| database | string | true | Name of the YugabyteDB database to connect to. The default database name is yugabyte. |
|
||||
| user | string | true | Name of the YugabyteDB user to connect as. The default user is yugabyte. |
|
||||
| password | string | true | Password of the YugabyteDB user. The default password is yugabyte. |
|
||||
| loadBalance | boolean | false | If true, enable uniform load balancing. The default loadBalance value is false. |
|
||||
| topologyKeys | string | false | Comma-separated geo-locations in the form cloud.region.zone:priority to enable topology-aware load balancing. Ignored if loadBalance is false. It is null by default. |
|
||||
| ybServersRefreshInterval | integer | false | The interval (in seconds) to refresh the servers list; ignored if loadBalance is false. The default value of ybServersRefreshInterval is 300. |
|
||||
| fallbackToTopologyKeysOnly | boolean | false | If set to true and topologyKeys are specified, only connect to nodes specified in topologyKeys. By defualt, this is set to false. |
|
||||
| failedHostReconnectDelaySecs | integer | false | Time (in seconds) to wait before trying to connect to failed nodes. The default value of is 5. |
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "bigquery-analyze-contribution"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "bigquery-analyze-contribution" tool performs contribution analysis in BigQuery.
|
||||
aliases:
|
||||
- /resources/tools/bigquery-analyze-contribution
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
A `bigquery-analyze-contribution` tool performs contribution analysis in BigQuery by creating a temporary `CONTRIBUTION_ANALYSIS` model and then querying it with `ML.GET_INSIGHTS` to find top contributors for a given metric.
|
||||
|
||||
It's compatible with the following sources:
|
||||
|
||||
- [bigquery](../../sources/bigquery.md)
|
||||
|
||||
`bigquery-analyze-contribution` takes the following parameters:
|
||||
|
||||
- **input_data** (string, required): The data that contain the test and control data to analyze. This can be a fully qualified BigQuery table ID (e.g., `my-project.my_dataset.my_table`) or a SQL query that returns the data.
|
||||
- **contribution_metric** (string, required): The name of the column that contains the metric to analyze. This can be SUM(metric_column_name), SUM(numerator_metric_column_name)/SUM(denominator_metric_column_name) or SUM(metric_sum_column_name)/COUNT(DISTINCT categorical_column_name) depending the type of metric to analyze.
|
||||
- **is_test_col** (string, required): The name of the column that identifies whether a row is in the test or control group. The column must contain boolean values.
|
||||
- **dimension_id_cols** (array of strings, optional): An array of column names that uniquely identify each dimension.
|
||||
- **top_k_insights_by_apriori_support** (integer, optional): The number of top insights to return, ranked by apriori support. Default to '30'.
|
||||
- **pruning_method** (string, optional): The method to use for pruning redundant insights. Can be `'NO_PRUNING'` or `'PRUNE_REDUNDANT_INSIGHTS'`. Defaults to `'PRUNE_REDUNDANT_INSIGHTS'`.
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
contribution_analyzer:
|
||||
kind: bigquery-analyze-contribution
|
||||
source: my-bigquery-source
|
||||
description: Use this tool to run contribution analysis on a dataset in BigQuery.
|
||||
```
|
||||
|
||||
## Sample Prompt
|
||||
You can prepare a sample table following https://cloud.google.com/bigquery/docs/get-contribution-analysis-insights.
|
||||
And use the following sample prompts to call this tool:
|
||||
|
||||
- What drives the changes in sales in the table `bqml_tutorial.iowa_liquor_sales_sum_data`? Use the project id myproject.
|
||||
- Analyze the contribution for the `total_sales` metric in the table `bqml_tutorial.iowa_liquor_sales_sum_data`. The test group is identified by the `is_test` column. The dimensions are `store_name`, `city`, `vendor_name`, `category_name` and `item_description`.
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-------------|:--------:|:------------:|------------------------------------------------------------|
|
||||
| kind | string | true | Must be "bigquery-analyze-contribution". |
|
||||
| source | string | true | Name of the source the tool should execute on. |
|
||||
| description | string | true | Description of the tool that is passed to the LLM. |
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "bigquery-conversational-analytics"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "bigquery-conversational-analytics" tool allows conversational interaction with a BigQuery source.
|
||||
aliases:
|
||||
- /resources/tools/bigquery-conversational-analytics
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
A `bigquery-conversational-analytics` tool allows you to ask questions about your data in natural language.
|
||||
|
||||
This function takes a user's question (which can include conversational history for context)
|
||||
and references to specific BigQuery tables, and sends them to a stateless conversational API.
|
||||
|
||||
The API uses a GenAI agent to understand the question, generate and execute SQL queries
|
||||
and Python code, and formulate an answer. This function returns a detailed, sequential
|
||||
log of this entire process, which includes any generated SQL or Python code, the data
|
||||
retrieved, and the final text answer.
|
||||
|
||||
**Note**: This tool requires additional setup in your project. Please refer to the
|
||||
official [Conversational Analytics API documentation](https://cloud.google.com/gemini/docs/conversational-analytics-api/overview)
|
||||
for instructions.
|
||||
|
||||
It's compatible with the following sources:
|
||||
|
||||
- [bigquery](../sources/bigquery.md)
|
||||
|
||||
The tool takes the following input parameters:
|
||||
|
||||
* `user_query_with_context`: The user's question, potentially including conversation history and system instructions for context.
|
||||
* `table_references`: A JSON string of a list of BigQuery tables to use as context. Each object in the list must contain `projectId`, `datasetId`, and `tableId`. Example: `'[{"projectId": "my-gcp-project", "datasetId": "my_dataset", "tableId": "my_table"}]'`
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
ask_data_insights:
|
||||
kind: bigquery-conversational-analytics
|
||||
source: my-bigquery-source
|
||||
description: |
|
||||
Use this tool to perform data analysis, get insights, or answer complex
|
||||
questions about the contents of specific BigQuery tables.
|
||||
```
|
||||
|
||||
## Reference
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "bigquery-conversational-analytics". |
|
||||
| source | string | true | Name of the source for chat. |
|
||||
| description | string | true | Description of the tool
|
||||
that is passed to the LLM. |
|
||||
@@ -15,10 +15,19 @@ It's compatible with the following sources:
|
||||
|
||||
- [bigquery](../../sources/bigquery.md)
|
||||
|
||||
`bigquery-list-table-ids` takes a required `dataset` parameter to specify the dataset
|
||||
from which to list table IDs. It also optionally accepts a `project` parameter to
|
||||
define the Google Cloud project ID. If the `project` parameter is not provided, the
|
||||
tool defaults to using the project defined in the source configuration.
|
||||
`bigquery-list-table-ids` accepts the following parameters:
|
||||
- **`dataset`** (required): Specifies the dataset from which to list table IDs.
|
||||
- **`project`** (optional): Defines the Google Cloud project ID. If not provided,
|
||||
the tool defaults to the project from the source configuration.
|
||||
|
||||
The tool's behavior regarding these parameters is influenced by the
|
||||
`allowedDatasets` restriction on the `bigquery` source:
|
||||
- **Without `allowedDatasets` restriction:** The tool can list tables from any
|
||||
dataset specified by the `dataset` and `project` parameters.
|
||||
- **With `allowedDatasets` restriction:** Before listing tables, the tool verifies
|
||||
that the requested dataset is in the allowed list. If it is not, the request is
|
||||
denied. If only one dataset is specified in the `allowedDatasets` list, it
|
||||
will be used as the default value for the `dataset` parameter.
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
7
docs/en/resources/tools/clickhouse/_index.md
Normal file
7
docs/en/resources/tools/clickhouse/_index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: "ClickHouse"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
Tools for interacting with ClickHouse databases and tables.
|
||||
---
|
||||
46
docs/en/resources/tools/clickhouse/clickhouse-execute-sql.md
Normal file
46
docs/en/resources/tools/clickhouse/clickhouse-execute-sql.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "clickhouse-execute-sql"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "clickhouse-execute-sql" tool executes a SQL statement against a ClickHouse
|
||||
database.
|
||||
aliases:
|
||||
- /resources/tools/clickhouse-execute-sql
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
A `clickhouse-execute-sql` tool executes a SQL statement against a ClickHouse
|
||||
database. It's compatible with the [clickhouse](../../sources/clickhouse.md) source.
|
||||
|
||||
`clickhouse-execute-sql` takes one input parameter `sql` and runs the SQL
|
||||
statement against the specified `source`. This tool includes query logging
|
||||
capabilities for monitoring and debugging purposes.
|
||||
|
||||
> **Note:** This tool is intended for developer assistant workflows with
|
||||
> human-in-the-loop and shouldn't be used for production agents.
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
execute_sql_tool:
|
||||
kind: clickhouse-execute-sql
|
||||
source: my-clickhouse-instance
|
||||
description: Use this tool to execute SQL statements against ClickHouse.
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| **parameter** | **type** | **required** | **description** |
|
||||
|---------------|:--------:|:------------:|----------------------------------------------------|
|
||||
| sql | string | true | The SQL statement to execute against the database |
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-------------|:--------:|:------------:|---------------------------------------------------------|
|
||||
| kind | string | true | Must be "clickhouse-execute-sql". |
|
||||
| source | string | true | Name of the ClickHouse source to execute SQL against. |
|
||||
| description | string | true | Description of the tool that is passed to the LLM. |
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: "clickhouse-list-databases"
|
||||
type: docs
|
||||
weight: 3
|
||||
description: >
|
||||
A "clickhouse-list-databases" tool lists all databases in a ClickHouse instance.
|
||||
aliases:
|
||||
- /resources/tools/clickhouse-list-databases
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
A `clickhouse-list-databases` tool lists all available databases in a
|
||||
ClickHouse instance. It's compatible with the [clickhouse](../../sources/clickhouse.md) source.
|
||||
|
||||
This tool executes the `SHOW DATABASES` command and returns a list of all
|
||||
databases accessible to the configured user, making it useful for database
|
||||
discovery and exploration tasks.
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
list_clickhouse_databases:
|
||||
kind: clickhouse-list-databases
|
||||
source: my-clickhouse-instance
|
||||
description: List all available databases in the ClickHouse instance
|
||||
```
|
||||
|
||||
## Return Value
|
||||
|
||||
The tool returns an array of objects, where each object contains:
|
||||
- `name`: The name of the database
|
||||
|
||||
Example response:
|
||||
```json
|
||||
[
|
||||
{"name": "default"},
|
||||
{"name": "system"},
|
||||
{"name": "analytics"},
|
||||
{"name": "user_data"}
|
||||
]
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|--------------------|:------------------:|:------------:|-----------------------------------------------------------|
|
||||
| kind | string | true | Must be "clickhouse-list-databases". |
|
||||
| source | string | true | Name of the ClickHouse source to list databases from. |
|
||||
| description | string | true | Description of the tool that is passed to the LLM. |
|
||||
| authRequired | array of string | false | Authentication services required to use this tool. |
|
||||
| parameters | array of Parameter | false | Parameters for the tool (typically not used). |
|
||||
81
docs/en/resources/tools/clickhouse/clickhouse-sql.md
Normal file
81
docs/en/resources/tools/clickhouse/clickhouse-sql.md
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: "clickhouse-sql"
|
||||
type: docs
|
||||
weight: 2
|
||||
description: >
|
||||
A "clickhouse-sql" tool executes SQL queries as prepared statements in ClickHouse.
|
||||
aliases:
|
||||
- /resources/tools/clickhouse-sql
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
A `clickhouse-sql` tool executes SQL queries as prepared statements against a
|
||||
ClickHouse database. It's compatible with the [clickhouse](../../sources/clickhouse.md) source.
|
||||
|
||||
This tool supports both template parameters (for SQL statement customization)
|
||||
and regular parameters (for prepared statement values), providing flexible
|
||||
query execution capabilities.
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
my_analytics_query:
|
||||
kind: clickhouse-sql
|
||||
source: my-clickhouse-instance
|
||||
description: Get user analytics for a specific date range
|
||||
statement: |
|
||||
SELECT
|
||||
user_id,
|
||||
count(*) as event_count,
|
||||
max(timestamp) as last_event
|
||||
FROM events
|
||||
WHERE date >= ? AND date <= ?
|
||||
GROUP BY user_id
|
||||
ORDER BY event_count DESC
|
||||
LIMIT ?
|
||||
parameters:
|
||||
- name: start_date
|
||||
description: Start date for the query (YYYY-MM-DD format)
|
||||
- name: end_date
|
||||
description: End date for the query (YYYY-MM-DD format)
|
||||
- name: limit
|
||||
description: Maximum number of results to return
|
||||
```
|
||||
|
||||
## Template Parameters Example
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
flexible_table_query:
|
||||
kind: clickhouse-sql
|
||||
source: my-clickhouse-instance
|
||||
description: Query any table with flexible columns
|
||||
statement: |
|
||||
SELECT {{columns}}
|
||||
FROM {{table_name}}
|
||||
WHERE created_date >= ?
|
||||
LIMIT ?
|
||||
templateParameters:
|
||||
- name: columns
|
||||
description: Comma-separated list of columns to select
|
||||
- name: table_name
|
||||
description: Name of the table to query
|
||||
parameters:
|
||||
- name: start_date
|
||||
description: Start date filter
|
||||
- name: limit
|
||||
description: Maximum number of results
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|--------------------|:------------------:|:------------:|-----------------------------------------------------------|
|
||||
| kind | string | true | Must be "clickhouse-sql". |
|
||||
| source | string | true | Name of the ClickHouse source to execute SQL against. |
|
||||
| description | string | true | Description of the tool that is passed to the LLM. |
|
||||
| statement | string | true | The SQL statement template to execute. |
|
||||
| parameters | array of Parameter | false | Parameters for prepared statement values. |
|
||||
| templateParameters | array of Parameter | false | Parameters for SQL statement template customization. |
|
||||
412
docs/en/resources/tools/firestore/firestore-query.md
Normal file
412
docs/en/resources/tools/firestore/firestore-query.md
Normal file
@@ -0,0 +1,412 @@
|
||||
---
|
||||
title: "firestore-query"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
Query a Firestore collection with parameterizable filters and Firestore native JSON value types
|
||||
aliases:
|
||||
- /resources/tools/firestore-query
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The `firestore-query` tool allows you to query Firestore collections with dynamic, parameterizable filters that support Firestore's native JSON value types. This tool is designed for querying single collection, which is the standard pattern in Firestore. The collection path itself can be parameterized, making it flexible for various use cases. This tool is particularly useful when you need to create reusable query templates with parameters that can be substituted at runtime.
|
||||
|
||||
**Developer Note**: This tool serves as the general querying foundation that developers can use to create custom tools with specific query patterns.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Parameterizable Queries**: Use Go template syntax to create dynamic queries
|
||||
- **Dynamic Collection Paths**: The collection path can be parameterized for flexibility
|
||||
- **Native JSON Value Types**: Support for Firestore's typed values (stringValue, integerValue, doubleValue, etc.)
|
||||
- **Complex Filter Logic**: Support for AND/OR logical operators in filters
|
||||
- **Template Substitution**: Dynamic collection paths, filters, and ordering
|
||||
- **Query Analysis**: Optional query performance analysis with explain metrics (non-parameterizable)
|
||||
|
||||
## Configuration
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
query_countries:
|
||||
kind: firestore-query
|
||||
source: my-firestore-source
|
||||
description: Query countries with dynamic filters
|
||||
collectionPath: "countries"
|
||||
filters: |
|
||||
{
|
||||
"field": "continent",
|
||||
"op": "==",
|
||||
"value": {"stringValue": "{{.continent}}"}
|
||||
}
|
||||
parameters:
|
||||
- name: continent
|
||||
type: string
|
||||
description: Continent to filter by
|
||||
required: true
|
||||
```
|
||||
|
||||
### Advanced Configuration with Complex Filters
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
advanced_query:
|
||||
kind: firestore-query
|
||||
source: my-firestore-source
|
||||
description: Advanced query with complex filters
|
||||
collectionPath: "{{.collection}}"
|
||||
filters: |
|
||||
{
|
||||
"or": [
|
||||
{"field": "status", "op": "==", "value": {"stringValue": "{{.status}}"}},
|
||||
{
|
||||
"and": [
|
||||
{"field": "priority", "op": ">", "value": {"integerValue": "{{.priority}}"}},
|
||||
{"field": "area", "op": "<", "value": {"doubleValue": {{.maxArea}}}},
|
||||
{"field": "active", "op": "==", "value": {"booleanValue": {{.isActive}}}}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
select:
|
||||
- name
|
||||
- status
|
||||
- priority
|
||||
orderBy:
|
||||
field: "{{.sortField}}"
|
||||
direction: "{{.sortDirection}}"
|
||||
limit: 100
|
||||
analyzeQuery: true
|
||||
parameters:
|
||||
- name: collection
|
||||
type: string
|
||||
description: Collection to query
|
||||
required: true
|
||||
- name: status
|
||||
type: string
|
||||
description: Status to filter by
|
||||
required: true
|
||||
- name: priority
|
||||
type: string
|
||||
description: Minimum priority value
|
||||
required: true
|
||||
- name: maxArea
|
||||
type: float
|
||||
description: Maximum area value
|
||||
required: true
|
||||
- name: isActive
|
||||
type: boolean
|
||||
description: Filter by active status
|
||||
required: true
|
||||
- name: sortField
|
||||
type: string
|
||||
description: Field to sort by
|
||||
required: false
|
||||
default: "createdAt"
|
||||
- name: sortDirection
|
||||
type: string
|
||||
description: Sort direction (ASCENDING or DESCENDING)
|
||||
required: false
|
||||
default: "DESCENDING"
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
### Configuration Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `kind` | string | Yes | Must be `firestore-query` |
|
||||
| `source` | string | Yes | Name of the Firestore source to use |
|
||||
| `description` | string | Yes | Description of what this tool does |
|
||||
| `collectionPath` | string | Yes | Path to the collection to query (supports templates) |
|
||||
| `filters` | string | No | JSON string defining query filters (supports templates) |
|
||||
| `select` | array | No | Fields to select from documents(supports templates - string or array) |
|
||||
| `orderBy` | object | No | Ordering configuration with `field` and `direction`(supports templates for the value of field or direction) |
|
||||
| `limit` | integer | No | Maximum number of documents to return (default: 100) (supports templates) |
|
||||
| `analyzeQuery` | boolean | No | Whether to analyze query performance (default: false) |
|
||||
| `parameters` | array | Yes | Parameter definitions for template substitution |
|
||||
|
||||
### Runtime Parameters
|
||||
|
||||
Runtime parameters are defined in the `parameters` array and can be used in templates throughout the configuration.
|
||||
|
||||
## Filter Format
|
||||
|
||||
### Simple Filter
|
||||
```json
|
||||
{
|
||||
"field": "age",
|
||||
"op": ">",
|
||||
"value": {"integerValue": "25"}
|
||||
}
|
||||
```
|
||||
|
||||
### AND Filter
|
||||
```json
|
||||
{
|
||||
"and": [
|
||||
{"field": "status", "op": "==", "value": {"stringValue": "active"}},
|
||||
{"field": "age", "op": ">=", "value": {"integerValue": "18"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### OR Filter
|
||||
```json
|
||||
{
|
||||
"or": [
|
||||
{"field": "role", "op": "==", "value": {"stringValue": "admin"}},
|
||||
{"field": "role", "op": "==", "value": {"stringValue": "moderator"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Nested Filters
|
||||
```json
|
||||
{
|
||||
"or": [
|
||||
{"field": "type", "op": "==", "value": {"stringValue": "premium"}},
|
||||
{
|
||||
"and": [
|
||||
{"field": "type", "op": "==", "value": {"stringValue": "standard"}},
|
||||
{"field": "credits", "op": ">", "value": {"integerValue": "1000"}}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Firestore Native Value Types
|
||||
|
||||
The tool supports all Firestore native JSON value types:
|
||||
|
||||
| Type | Format | Example |
|
||||
|------|--------|---------|
|
||||
| String | `{"stringValue": "text"}` | `{"stringValue": "{{.name}}"}` |
|
||||
| Integer | `{"integerValue": "123"}` or `{"integerValue": 123}` | `{"integerValue": "{{.age}}"}` or `{"integerValue": {{.age}}}` |
|
||||
| Double | `{"doubleValue": 45.67}` | `{"doubleValue": {{.price}}}` |
|
||||
| Boolean | `{"booleanValue": true}` | `{"booleanValue": {{.active}}}` |
|
||||
| Null | `{"nullValue": null}` | `{"nullValue": null}` |
|
||||
| Timestamp | `{"timestampValue": "RFC3339"}` | `{"timestampValue": "{{.date}}"}` |
|
||||
| GeoPoint | `{"geoPointValue": {"latitude": 0, "longitude": 0}}` | See below |
|
||||
| Array | `{"arrayValue": {"values": [...]}}` | See below |
|
||||
| Map | `{"mapValue": {"fields": {...}}}` | See below |
|
||||
|
||||
### Complex Type Examples
|
||||
|
||||
**GeoPoint:**
|
||||
```json
|
||||
{
|
||||
"field": "location",
|
||||
"op": "==",
|
||||
"value": {
|
||||
"geoPointValue": {
|
||||
"latitude": 37.7749,
|
||||
"longitude": -122.4194
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Array:**
|
||||
```json
|
||||
{
|
||||
"field": "tags",
|
||||
"op": "array-contains",
|
||||
"value": {"stringValue": "{{.tag}}"}
|
||||
}
|
||||
```
|
||||
|
||||
## Supported Operators
|
||||
|
||||
- `<` - Less than
|
||||
- `<=` - Less than or equal
|
||||
- `>` - Greater than
|
||||
- `>=` - Greater than or equal
|
||||
- `==` - Equal
|
||||
- `!=` - Not equal
|
||||
- `array-contains` - Array contains value
|
||||
- `array-contains-any` - Array contains any of the values
|
||||
- `in` - Value is in array
|
||||
- `not-in` - Value is not in array
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Query with Dynamic Collection Path
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
user_documents:
|
||||
kind: firestore-query
|
||||
source: my-firestore
|
||||
description: Query user-specific documents
|
||||
collectionPath: "users/{{.userId}}/documents"
|
||||
filters: |
|
||||
{
|
||||
"field": "type",
|
||||
"op": "==",
|
||||
"value": {"stringValue": "{{.docType}}"}
|
||||
}
|
||||
parameters:
|
||||
- name: userId
|
||||
type: string
|
||||
description: User ID
|
||||
required: true
|
||||
- name: docType
|
||||
type: string
|
||||
description: Document type to filter
|
||||
required: true
|
||||
```
|
||||
|
||||
### Example 2: Complex Geographic Query
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
location_search:
|
||||
kind: firestore-query
|
||||
source: my-firestore
|
||||
description: Search locations by area and population
|
||||
collectionPath: "cities"
|
||||
filters: |
|
||||
{
|
||||
"and": [
|
||||
{"field": "country", "op": "==", "value": {"stringValue": "{{.country}}"}},
|
||||
{"field": "population", "op": ">", "value": {"integerValue": "{{.minPopulation}}"}},
|
||||
{"field": "area", "op": "<", "value": {"doubleValue": {{.maxArea}}}}
|
||||
]
|
||||
}
|
||||
orderBy:
|
||||
field: "population"
|
||||
direction: "DESCENDING"
|
||||
limit: 50
|
||||
parameters:
|
||||
- name: country
|
||||
type: string
|
||||
description: Country code
|
||||
required: true
|
||||
- name: minPopulation
|
||||
type: string
|
||||
description: Minimum population (as string for large numbers)
|
||||
required: true
|
||||
- name: maxArea
|
||||
type: float
|
||||
description: Maximum area in square kilometers
|
||||
required: true
|
||||
```
|
||||
|
||||
### Example 3: Time-based Query with Analysis
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
activity_log:
|
||||
kind: firestore-query
|
||||
source: my-firestore
|
||||
description: Query activity logs within time range
|
||||
collectionPath: "logs"
|
||||
filters: |
|
||||
{
|
||||
"and": [
|
||||
{"field": "timestamp", "op": ">=", "value": {"timestampValue": "{{.startTime}}"}},
|
||||
{"field": "timestamp", "op": "<=", "value": {"timestampValue": "{{.endTime}}"}},
|
||||
{"field": "severity", "op": "in", "value": {"arrayValue": {"values": [
|
||||
{"stringValue": "ERROR"},
|
||||
{"stringValue": "CRITICAL"}
|
||||
]}}}
|
||||
]
|
||||
}
|
||||
select:
|
||||
- timestamp
|
||||
- message
|
||||
- severity
|
||||
- userId
|
||||
orderBy:
|
||||
field: "timestamp"
|
||||
direction: "DESCENDING"
|
||||
analyzeQuery: true
|
||||
parameters:
|
||||
- name: startTime
|
||||
type: string
|
||||
description: Start time in RFC3339 format
|
||||
required: true
|
||||
- name: endTime
|
||||
type: string
|
||||
description: End time in RFC3339 format
|
||||
required: true
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Invoking the Tool
|
||||
|
||||
```bash
|
||||
# Using curl
|
||||
curl -X POST http://localhost:5000/api/tool/your-tool-name/invoke \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"continent": "Europe",
|
||||
"minPopulation": "1000000",
|
||||
"maxArea": 500000.5,
|
||||
"isActive": true
|
||||
}'
|
||||
```
|
||||
|
||||
### Response Format
|
||||
|
||||
**Without analyzeQuery:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "doc1",
|
||||
"path": "countries/doc1",
|
||||
"data": {
|
||||
"name": "France",
|
||||
"continent": "Europe",
|
||||
"population": 67000000,
|
||||
"area": 551695
|
||||
},
|
||||
"createTime": "2024-01-01T00:00:00Z",
|
||||
"updateTime": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**With analyzeQuery:**
|
||||
```json
|
||||
{
|
||||
"documents": [...],
|
||||
"explainMetrics": {
|
||||
"planSummary": {
|
||||
"indexesUsed": [...]
|
||||
},
|
||||
"executionStats": {
|
||||
"resultsReturned": 10,
|
||||
"executionDuration": "15ms",
|
||||
"readOperations": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use Typed Values**: Always use Firestore's native JSON value types for proper type handling
|
||||
2. **String Numbers for Large Integers**: Use string representation for large integers to avoid precision loss
|
||||
3. **Template Security**: Validate all template parameters to prevent injection attacks
|
||||
4. **Index Optimization**: Use `analyzeQuery` to identify missing indexes
|
||||
5. **Limit Results**: Always set a reasonable `limit` to prevent excessive data retrieval
|
||||
6. **Field Selection**: Use `select` to retrieve only necessary fields
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Queries operate on a single collection (the standard Firestore pattern)
|
||||
- Maximum of 100 filters per query (configurable)
|
||||
- Template parameters must be properly escaped in JSON contexts
|
||||
- Complex nested queries may require composite indexes
|
||||
|
||||
## See Also
|
||||
|
||||
- [firestore-query-collection](firestore-query-collection.md) - Non-parameterizable query tool
|
||||
- [Firestore Source Configuration](../../sources/firestore.md)
|
||||
- [Firestore Query Documentation](https://firebase.google.com/docs/firestore/query-data/queries)
|
||||
@@ -33,6 +33,29 @@ tools:
|
||||
|
||||
It takes two parameters, the model_name looked up from get_models and the
|
||||
explore_name looked up from get_explores.
|
||||
|
||||
If this returns a suggestions field for a dimension, the contents of suggestions
|
||||
can be used as filters for this field. If this returns a suggest_explore and
|
||||
suggest_dimension, a query against that explore and dimension can be used to find
|
||||
valid filters for this field.
|
||||
|
||||
```
|
||||
|
||||
The response is a json array with the following elements:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "field name",
|
||||
"description": "field description",
|
||||
"type": "field type",
|
||||
"label": "field label",
|
||||
"label_short": "field short label",
|
||||
"tags": ["tags", ...],
|
||||
"synonyms": ["synonyms", ...],
|
||||
"suggestions": ["suggestion", ...],
|
||||
"suggest_explore": "explore",
|
||||
"suggest_dimension": "dimension"
|
||||
}
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
@@ -21,6 +21,16 @@ It's compatible with the following sources:
|
||||
`looker-get-explores` accepts one parameter, the
|
||||
`model` id.
|
||||
|
||||
The return type is an array of maps, each map is formatted like:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "explore name",
|
||||
"description": "explore description",
|
||||
"label": "explore label",
|
||||
"group_label": "group label"
|
||||
}
|
||||
```
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
|
||||
@@ -35,6 +35,24 @@ tools:
|
||||
explore_name looked up from get_explores.
|
||||
```
|
||||
|
||||
The response is a json array with the following elements:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "field name",
|
||||
"description": "field description",
|
||||
"type": "field type",
|
||||
"label": "field label",
|
||||
"label_short": "field short label",
|
||||
"tags": ["tags", ...],
|
||||
"synonyms": ["synonyms", ...],
|
||||
"suggestions": ["suggestion", ...],
|
||||
"suggest_explore": "explore",
|
||||
"suggest_dimension": "dimension"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|
||||
@@ -33,8 +33,32 @@ tools:
|
||||
|
||||
It takes two parameters, the model_name looked up from get_models and the
|
||||
explore_name looked up from get_explores.
|
||||
|
||||
If this returns a suggestions field for a measure, the contents of suggestions
|
||||
can be used as filters for this field. If this returns a suggest_explore and
|
||||
suggest_dimension, a query against that explore and dimension can be used to find
|
||||
valid filters for this field.
|
||||
|
||||
```
|
||||
|
||||
The response is a json array with the following elements:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "field name",
|
||||
"description": "field description",
|
||||
"type": "field type",
|
||||
"label": "field label",
|
||||
"label_short": "field short label",
|
||||
"tags": ["tags", ...],
|
||||
"synonyms": ["synonyms", ...],
|
||||
"suggestions": ["suggestion", ...],
|
||||
"suggest_explore": "explore",
|
||||
"suggest_dimension": "dimension"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|
||||
@@ -35,6 +35,24 @@ tools:
|
||||
explore_name looked up from get_explores.
|
||||
```
|
||||
|
||||
The response is a json array with the following elements:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "field name",
|
||||
"description": "field description",
|
||||
"type": "field type",
|
||||
"label": "field label",
|
||||
"label_short": "field short label",
|
||||
"tags": ["tags", ...],
|
||||
"synonyms": ["synonyms", ...],
|
||||
"suggestions": ["suggestion", ...],
|
||||
"suggest_explore": "explore",
|
||||
"suggest_dimension": "dimension"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|
||||
43
docs/en/resources/tools/mysql/mysql-list-tables.md
Normal file
43
docs/en/resources/tools/mysql/mysql-list-tables.md
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: "mysql-list-tables"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
The "mysql-list-tables" tool lists schema information for all or specified tables in a MySQL database.
|
||||
aliases:
|
||||
- /resources/tools/mysql-list-tables
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
The `mysql-list-tables` tool retrieves schema information for all or specified tables in a MySQL database. It is compatible with any of the following sources:
|
||||
|
||||
- [cloud-sql-mysql](../../sources/cloud-sql-mysql.md)
|
||||
- [mysql](../../sources/mysql.md)
|
||||
|
||||
`mysql-list-tables` lists detailed schema information (object type, columns, constraints, indexes, triggers, owner, comment) as JSON for user-created tables (ordinary or partitioned). Filters by a comma-separated list of names. If names are omitted, it lists all tables in user schemas. The output format can be set to `simple` which will return only the table names or `detailed` which is the default.
|
||||
|
||||
The tool takes the following input parameters:
|
||||
|
||||
| Parameter | Type | Description | Required |
|
||||
| :--------- | :----- | :--------------------------------------------------------------------------------------- | :------- |
|
||||
| `table_names` | string | Filters by a comma-separated list of names. By default, it lists all tables in user schemas. Default: `""` | No |
|
||||
| `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 |
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
mysql_list_tables:
|
||||
kind: mysql-list-tables
|
||||
source: mysql-source
|
||||
description: Use this tool to retrieve schema information for all or specified tables. Output format can be simple (only table names) or detailed.
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "mysql-list-tables". |
|
||||
| source | string | true | Name of the source the SQL should execute on. |
|
||||
| description | string | true | Description of the tool that is passed to the agent. |
|
||||
39
docs/en/resources/tools/postgres/postgres-list-tables.md
Normal file
39
docs/en/resources/tools/postgres/postgres-list-tables.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: "postgres-list-tables"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
The "postgres-list-tables" tool lists schema information for all or specified tables in a Postgres database.
|
||||
aliases:
|
||||
- /resources/tools/postgres-list-tables
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
The `postgres-list-tables` tool retrieves schema information for all or specified tables in a Postgres database. It's compatible with any of the following sources:
|
||||
|
||||
- [alloydb-postgres](../../sources/alloydb-pg.md)
|
||||
- [cloud-sql-postgres](../../sources/cloud-sql-pg.md)
|
||||
- [postgres](../../sources/postgres.md)
|
||||
|
||||
`postgres-list-tables` lists detailed schema information (object type, columns, constraints, indexes, triggers, owner, comment) as JSON for user-created tables (ordinary or partitioned). The tool takes the following input parameters:
|
||||
* `table_names` (optional): Filters by a comma-separated list of names. By default, it lists all tables in user schemas.
|
||||
* `output_format` (optional): Indicate the output format of table schema. `simple` will return only the table names, `detailed` will return the full table information. Default: `detailed`.
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
postgres_list_tables:
|
||||
kind: postgres-list-tables
|
||||
source: postgres-source
|
||||
description: Use this tool to retrieve schema information for all or specified tables. Output format can be simple (only table names) or detailed.
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "postgres-list-tables". |
|
||||
| source | string | true | Name of the source the SQL should execute on. |
|
||||
| description | string | true | Description of the tool that is passed to the agent. |
|
||||
101
docs/en/resources/tools/yugabytedb-sql.md
Normal file
101
docs/en/resources/tools/yugabytedb-sql.md
Normal file
@@ -0,0 +1,101 @@
|
||||
---
|
||||
title: "yugabytedb-sql"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "yugabytedb-sql" tool executes a pre-defined SQL statement against a YugabyteDB
|
||||
database.
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
A `yugabytedb-sql` tool executes a pre-defined SQL statement against a YugabyteDB
|
||||
database.
|
||||
|
||||
The specified SQL statement is executed as a prepared statement,
|
||||
and specified parameters will inserted according to their position: e.g. `1`
|
||||
will be the first parameter specified, `$@` will be the second parameter, and so
|
||||
on. If template parameters are included, they will be resolved before execution
|
||||
of the prepared statement.
|
||||
|
||||
## Example
|
||||
|
||||
> **Note:** This tool uses parameterized queries to prevent SQL injections.
|
||||
> Query parameters can be used as substitutes for arbitrary expressions.
|
||||
> Parameters cannot be used as substitutes for identifiers, column names, table
|
||||
> names, or other parts of the query.
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
search_flights_by_number:
|
||||
kind: yugabytedb-sql
|
||||
source: my-yb-instance
|
||||
statement: |
|
||||
SELECT * FROM flights
|
||||
WHERE airline = $1
|
||||
AND flight_number = $2
|
||||
LIMIT 10
|
||||
description: |
|
||||
Use this tool to get information for a specific flight.
|
||||
Takes an airline code and flight number and returns info on the flight.
|
||||
Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number.
|
||||
A airline code is a code for an airline service consisting of two-character
|
||||
airline designator and followed by flight number, which is 1 to 4 digit number.
|
||||
For example, if given CY 0123, the airline is "CY", and flight_number is "123".
|
||||
Another example for this is DL 1234, the airline is "DL", and flight_number is "1234".
|
||||
If the tool returns more than one option choose the date closes to today.
|
||||
Example:
|
||||
{{
|
||||
"airline": "CY",
|
||||
"flight_number": "888",
|
||||
}}
|
||||
Example:
|
||||
{{
|
||||
"airline": "DL",
|
||||
"flight_number": "1234",
|
||||
}}
|
||||
parameters:
|
||||
- name: airline
|
||||
type: string
|
||||
description: Airline unique 2 letter identifier
|
||||
- name: flight_number
|
||||
type: string
|
||||
description: 1 to 4 digit number
|
||||
```
|
||||
|
||||
### Example with Template Parameters
|
||||
|
||||
> **Note:** This tool allows direct modifications to the SQL statement, including identifiers, column names,
|
||||
> and table names. **This makes it more vulnerable to SQL injections**. Using basic parameters
|
||||
> only (see above) is recommended for performance and safety reasons. For more details, please
|
||||
> check [templateParameters](_index#template-parameters).
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
list_table:
|
||||
kind: yugabytedb-sql
|
||||
source: my-yb-instance
|
||||
statement: |
|
||||
SELECT * FROM {{.tableName}}
|
||||
description: |
|
||||
Use this tool to list all information from a specific table.
|
||||
Example:
|
||||
{{
|
||||
"tableName": "flights",
|
||||
}}
|
||||
templateParameters:
|
||||
- name: tableName
|
||||
type: string
|
||||
description: Table to select from
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|---------------------|:---------------------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| kind | string | true | Must be "yugabytedb-sql". |
|
||||
| source | string | true | Name of the source the SQL should execute on. |
|
||||
| description | string | true | Description of the tool that is passed to the LLM. |
|
||||
| statement | string | true | SQL statement to execute on. |
|
||||
| parameters | [parameters](_index#specifying-parameters) | false | List of [parameters](_index#specifying-parameters) that will be inserted into the SQL statement. |
|
||||
| templateParameters | [templateParameters](_index#template-parameters) | false | List of [templateParameters](_index#template-parameters) that will be inserted into the SQL statement before executing prepared statement. |
|
||||
@@ -79,7 +79,7 @@
|
||||
"# @markdown Please fill in the value below with your GCP project ID and then run the cell.\n",
|
||||
"\n",
|
||||
"# Please fill in these values.\n",
|
||||
"project_id = \"project-id\" # @param {type:\"string\"}\n",
|
||||
"project_id = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# Quick input validations.\n",
|
||||
"assert project_id, \"⚠️ Please provide a Google Cloud project ID\"\n",
|
||||
@@ -767,7 +767,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"version = \"0.11.0\" # x-release-please-version\n",
|
||||
"version = \"0.14.0\" # x-release-please-version\n",
|
||||
"! curl -L -o /content/toolbox https://storage.googleapis.com/genai-toolbox/v{version}/linux/amd64/toolbox\n",
|
||||
"\n",
|
||||
"# Make the binary executable\n",
|
||||
|
||||
@@ -114,7 +114,7 @@ In this section, we will download and install the Toolbox binary.
|
||||
<!-- {x-release-please-start-version} -->
|
||||
```bash
|
||||
export OS="linux/amd64" # one of linux/amd64, darwin/arm64, darwin/amd64, or windows/amd64
|
||||
export VERSION="0.11.0"
|
||||
export VERSION="0.14.0"
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v$VERSION/$OS/toolbox
|
||||
```
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
---
|
||||
title: "Access BigQuery from Gemini-CLI with End-User Credentials"
|
||||
type: docs
|
||||
weight: 2
|
||||
description: >
|
||||
How to connect to BigQuery from Gemini-CLI with end-user credentials
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Gemini-CLI can be configured to get an OAuth access token from the Google OAuth endpoint, then send this token to MCP Toolbox as part of the request. MCP Toolbox can then use this token to authentincate with BigQuery. This enables each user to access Toolbox with thier own IAM identity for a Toolbox multi-tenancy use case.
|
||||
|
||||
{{< notice note >}}
|
||||
This feature requires Toolbox v0.14.0 or later.
|
||||
{{< /notice >}}
|
||||
|
||||
## Step 1: Register the OAuth on GCP
|
||||
|
||||
You first need to register the OAuth application following this [guide](register-oauth) to get a client ID and client secret.
|
||||
|
||||
## Step 2: Install and configure Toolbox
|
||||
|
||||
In this section, we will download Toolbox and run the Toolbox server.
|
||||
|
||||
1. Download the latest version of Toolbox as a binary:
|
||||
|
||||
{{< notice tip >}}
|
||||
Select the
|
||||
[correct binary](https://github.com/googleapis/genai-toolbox/releases)
|
||||
corresponding to your OS and CPU architecture.
|
||||
{{< /notice >}}
|
||||
<!-- {x-release-please-start-version} -->
|
||||
```bash
|
||||
export OS="linux/amd64" # one of linux/amd64, darwin/arm64, darwin/amd64, or windows/amd64
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/$OS/toolbox
|
||||
```
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
1. Create a `tools.yaml` file and include the following BigQuery source configuration:
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
my-bigquery-client-auth-source:
|
||||
kind: "bigquery"
|
||||
project: "my-project-id"
|
||||
useClientOAuth: true
|
||||
# location: "US" # Optional: Specifies the location for query jobs.
|
||||
# allowedDatasets: # Optional: Restricts tool access to a specific list of datasets.
|
||||
# - "my_dataset_1"
|
||||
# - "other_project.my_dataset_2"
|
||||
```
|
||||
|
||||
1. Continue to configure one or more BigQuery tools. Here is a naive example to get started:
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
naive-bq-tool:
|
||||
kind: "bigquery-sql"
|
||||
source: "my-bigquery-client-auth-source"
|
||||
description: Naive BQ Tool that returns 1.
|
||||
statement: |
|
||||
SELECT 1;
|
||||
```
|
||||
|
||||
1. Run the Toolbox server:
|
||||
|
||||
```bash
|
||||
./toolbox --tools-file "tools.yaml"
|
||||
|
||||
```
|
||||
|
||||
The toolbox server will begin listening on localhost port 5000. Leave it
|
||||
running and continue in another terminal.
|
||||
|
||||
Later, when it is time to shut everything down, you can quit the toolbox
|
||||
server with Ctrl-C in this terminal window.
|
||||
|
||||
## Step 3: Configure Gemini-CLI
|
||||
|
||||
1. Edit the file `~/.gemini/settings.json` to include the following configuration:
|
||||
|
||||
```json
|
||||
"mcpServers": {
|
||||
"toolbox": {
|
||||
"httpUrl": "<http://localhost:5000/mcp>", // Replace this with your Toolbox URL if deployed somewhere else.
|
||||
"oauth": {
|
||||
"enabled": true,
|
||||
"clientId": <YOUR_CLIENT_ID>,
|
||||
"clientSecret": <YOUR_CLIENT_SECRET>,
|
||||
"authorizationUrl": "<https://accounts.google.com/o/oauth2/v2/auth>",
|
||||
"tokenUrl": "<https://oauth2.googleapis.com/token>",
|
||||
"scopes": ["https://www.googleapis.com/auth/cloud-platform"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to substitue your client ID and client secret received from step 1.
|
||||
|
||||
1. Start Gemini-CLI:
|
||||
|
||||
```shell
|
||||
gemini-cli
|
||||
```
|
||||
|
||||
1. Authenticate with the command `/mcp auth toolbox`. Gemini-CLI will open up a
|
||||
browser where you will log in to your Google account.
|
||||
|
||||

|
||||
|
||||
1. Use Gemini-CLI with your tools. To test the naive Tool we configured previously, ask Gemini to run this Tool:
|
||||
|
||||
```text
|
||||
Call naive-bq-tool
|
||||
```
|
||||
|
||||
## Using Toolbox as a Shared Service
|
||||
|
||||
Toolbox can be run on another server as a shared service accessed by multiple
|
||||
users. We strongly recommend running toolbox behind a web proxy such as `nginx`
|
||||
which will provide SSL encryption. Google Cloud Run is another good way to run
|
||||
toolbox. You will connect to a service like `https://toolbox.example.com/mcp`.
|
||||
The proxy server will handle the SSL encryption and certificates. Then it will
|
||||
foward the requests to `http://localhost:5000/mcp` running in that environment.
|
||||
The details of the config are beyond the scope of this document, but will be
|
||||
familiar to your system administrators.
|
||||
|
||||
To use the shared service, just change the `localhost:5000` in the `httpUrl` in
|
||||
`~/.gemini/settings.json` to the host name and possibly the port of the shared
|
||||
service.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -220,7 +220,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"version = \"0.12.0\" # x-release-please-version\n",
|
||||
"version = \"0.14.0\" # x-release-please-version\n",
|
||||
"! curl -O https://storage.googleapis.com/genai-toolbox/v{version}/linux/amd64/toolbox\n",
|
||||
"\n",
|
||||
"# Make the binary executable\n",
|
||||
|
||||
@@ -179,7 +179,7 @@ to use BigQuery, and then run the Toolbox server.
|
||||
<!-- {x-release-please-start-version} -->
|
||||
```bash
|
||||
export OS="linux/amd64" # one of linux/amd64, darwin/arm64, darwin/amd64, or windows/amd64
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/$OS/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/$OS/toolbox
|
||||
```
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ In this section, we will download Toolbox, configure our tools in a
|
||||
<!-- {x-release-please-start-version} -->
|
||||
```bash
|
||||
export OS="linux/amd64" # one of linux/amd64, darwin/arm64, darwin/amd64, or windows/amd64
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/$OS/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/$OS/toolbox
|
||||
```
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ In this section, we will download Toolbox and run the Toolbox server.
|
||||
<!-- {x-release-please-start-version} -->
|
||||
```bash
|
||||
export OS="linux/amd64" # one of linux/amd64, darwin/arm64, darwin/amd64, or windows/amd64
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/$OS/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/$OS/toolbox
|
||||
```
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
|
||||
140
docs/en/samples/looker/looker_gemini_oauth/_index.md
Normal file
140
docs/en/samples/looker/looker_gemini_oauth/_index.md
Normal file
@@ -0,0 +1,140 @@
|
||||
---
|
||||
title: "Gemini-CLI and OAuth"
|
||||
type: docs
|
||||
weight: 2
|
||||
description: >
|
||||
How to connect to Looker from Gemini-CLI with end-user credentials
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Gemini-CLI can be configured to get an OAuth token from Looker, then send this
|
||||
token to MCP Toolbox as part of the request. MCP Toolbox can then use this token
|
||||
to authentincate with Looker. This means that there is no need to get a Looker
|
||||
Client ID and Client Secret. This also means that MCP Toolbox can be set up as a
|
||||
shared resource.
|
||||
|
||||
This configuration requires Toolbox v0.14.0 or later.
|
||||
|
||||
## Step 1: Register the OAuth App in Looker
|
||||
|
||||
You first need to register the OAuth application. Refer to the documentation
|
||||
[here](https://cloud.google.com/looker/docs/api-cors#registering_an_oauth_client_application).
|
||||
You may need to ask an administrator to do this for you.
|
||||
|
||||
1. Go to the API Explorer application, locate "Register OAuth App", and press
|
||||
the "Run It" button.
|
||||
1. Set the `client_guid` to "gemini-cli".
|
||||
1. Set the `redirect_uri` to "http://localhost:7777/oauth/callback".
|
||||
1. The `display_name` and `description` can be "Gemini-CLI" or anything
|
||||
meaningful.
|
||||
1. Set `enabled` to "true".
|
||||
1. Check the box confirming that you understand this API will change data.
|
||||
1. Click the "Run" button.
|
||||
|
||||

|
||||
|
||||
## Step 2: Install and configure Toolbox
|
||||
|
||||
In this section, we will download Toolbox and run the Toolbox server.
|
||||
|
||||
1. Download the latest version of Toolbox as a binary:
|
||||
|
||||
{{< notice tip >}}
|
||||
Select the
|
||||
[correct binary](https://github.com/googleapis/genai-toolbox/releases)
|
||||
corresponding to your OS and CPU architecture.
|
||||
{{< /notice >}}
|
||||
<!-- {x-release-please-start-version} -->
|
||||
```bash
|
||||
export OS="linux/amd64" # one of linux/amd64, darwin/arm64, darwin/amd64, or windows/amd64
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/$OS/toolbox
|
||||
```
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
1. Make the binary executable:
|
||||
|
||||
```bash
|
||||
chmod +x toolbox
|
||||
```
|
||||
|
||||
1. Create a file `looker_env` with the settings for your
|
||||
Looker instance.
|
||||
|
||||
```bash
|
||||
export LOOKER_BASE_URL=https://looker.example.com
|
||||
export LOOKER_VERIFY_SSL=true
|
||||
```
|
||||
|
||||
In some instances you may need to append `:19999` to
|
||||
the LOOKER_BASE_URL.
|
||||
|
||||
1. Load the looker_env file into your environment.
|
||||
|
||||
```bash
|
||||
source looker_env
|
||||
```
|
||||
|
||||
1. Run the Toolbox server using the prebuilt Looker tools.
|
||||
|
||||
```bash
|
||||
./toolbox --prebuilt looker
|
||||
```
|
||||
|
||||
The toolbox server will begin listening on localhost port 5000. Leave it
|
||||
running and continue in another terminal.
|
||||
|
||||
Later, when it is time to shut everything down, you can quit the toolbox
|
||||
server with Ctrl-C in this terminal window.
|
||||
|
||||
## Step 3: Configure Gemini-CLI
|
||||
|
||||
1. Edit the file `~/.gemini/settings.json`. Add the following, substituting your
|
||||
Looker server host name for `looker.example.com`.
|
||||
|
||||
```json
|
||||
"mcpServers": {
|
||||
"looker": {
|
||||
"httpUrl": "http://localhost:5000/mcp",
|
||||
"oauth": {
|
||||
"enabled": true,
|
||||
"clientId": "gemini-cli",
|
||||
"authorizationUrl": "https://looker.example.com/auth",
|
||||
"tokenUrl": "https://looker.example.com/api/token",
|
||||
"scopes": ["cors_api"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `authorizationUrl` should point to the URL you use to access Looker via the
|
||||
web UI. The `tokenUrl` should point to the URL you use to access Looker via
|
||||
the API. In some cases you will need to use the port number `:19999` after
|
||||
the host name but before the `/api/token` part.
|
||||
|
||||
1. Start Gemini-CLI.
|
||||
|
||||
1. Authenticate with the command `/mcp auth looker`. Gemini-CLI will open up a
|
||||
browser where you will confirm that you want to access Looker with your
|
||||
account.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
1. Use Gemini-CLI with your tools.
|
||||
|
||||
## Using Toolbox as a Shared Service
|
||||
|
||||
Toolbox can be run on another server as a shared service accessed by multiple
|
||||
users. We strongly recommend running toolbox behind a web proxy such as `nginx`
|
||||
which will provide SSL encryption. Google Cloud Run is another good way to run
|
||||
toolbox. You will connect to a service like `https://toolbox.example.com/mcp`.
|
||||
The proxy server will handle the SSL encryption and certificates. Then it will
|
||||
foward the requests to `http://localhost:5000/mcp` running in that environment.
|
||||
The details of the config are beyond the scope of this document, but will be
|
||||
familiar to your system administrators.
|
||||
|
||||
To use the shared service, just change the `localhost:5000` in the `httpUrl` in
|
||||
`~/.gemini/settings.json` to the host name and possibly the port of the shared
|
||||
service.
|
||||
BIN
docs/en/samples/looker/looker_gemini_oauth/authenticated.png
Normal file
BIN
docs/en/samples/looker/looker_gemini_oauth/authenticated.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
BIN
docs/en/samples/looker/looker_gemini_oauth/authorize.png
Normal file
BIN
docs/en/samples/looker/looker_gemini_oauth/authorize.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
BIN
docs/en/samples/looker/looker_gemini_oauth/registration.png
Normal file
BIN
docs/en/samples/looker/looker_gemini_oauth/registration.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
@@ -34,7 +34,7 @@ In this section, we will download Toolbox and run the Toolbox server.
|
||||
<!-- {x-release-please-start-version} -->
|
||||
```bash
|
||||
export OS="linux/amd64" # one of linux/amd64, darwin/arm64, darwin/amd64, or windows/amd64
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.12.0/$OS/toolbox
|
||||
curl -O https://storage.googleapis.com/genai-toolbox/v0.14.0/$OS/toolbox
|
||||
```
|
||||
<!-- {x-release-please-end} -->
|
||||
|
||||
|
||||
56
go.mod
56
go.mod
@@ -1,24 +1,25 @@
|
||||
module github.com/googleapis/genai-toolbox
|
||||
|
||||
go 1.24
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.25.0
|
||||
toolchain go1.25.1
|
||||
|
||||
require (
|
||||
cloud.google.com/go/alloydbconn v1.15.5
|
||||
cloud.google.com/go/bigquery v1.69.0
|
||||
cloud.google.com/go/bigtable v1.38.0
|
||||
cloud.google.com/go/cloudsqlconn v1.18.0
|
||||
cloud.google.com/go/bigquery v1.70.0
|
||||
cloud.google.com/go/bigtable v1.39.0
|
||||
cloud.google.com/go/cloudsqlconn v1.18.1
|
||||
cloud.google.com/go/dataplex v1.26.0
|
||||
cloud.google.com/go/firestore v1.18.0
|
||||
cloud.google.com/go/spanner v1.84.1
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.40.1
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.29.0
|
||||
github.com/cenkalti/backoff/v5 v5.0.3
|
||||
github.com/couchbase/gocb/v2 v2.10.1
|
||||
github.com/couchbase/gocb/v2 v2.11.0
|
||||
github.com/couchbase/tools-common/http v1.0.9
|
||||
github.com/fsnotify/fsnotify v1.9.0
|
||||
github.com/go-chi/chi/v5 v5.2.2
|
||||
github.com/go-chi/chi/v5 v5.2.3
|
||||
github.com/go-chi/httplog/v2 v2.1.1
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/go-goquery/goquery v1.0.1
|
||||
@@ -27,17 +28,18 @@ require (
|
||||
github.com/goccy/go-yaml v1.18.0
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jackc/pgx/v5 v5.7.5
|
||||
github.com/jackc/pgx/v5 v5.7.6
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/looker-open-source/sdk-codegen/go v0.25.10
|
||||
github.com/microsoft/go-mssqldb v1.9.2
|
||||
github.com/microsoft/go-mssqldb v1.9.3
|
||||
github.com/nakagami/firebirdsql v0.9.15
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.28.2
|
||||
github.com/redis/go-redis/v9 v9.12.1
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.28.3
|
||||
github.com/redis/go-redis/v9 v9.13.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/thlib/go-timezone-local v0.0.7
|
||||
github.com/trinodb/trino-go-client v0.328.0
|
||||
github.com/valkey-io/valkey-go v1.0.64
|
||||
github.com/yugabyte/pgx/v5 v5.5.3-yb-5
|
||||
go.mongodb.org/mongo-driver v1.17.4
|
||||
go.opentelemetry.io/contrib/propagators/autoprop v0.62.0
|
||||
go.opentelemetry.io/otel v1.37.0
|
||||
@@ -47,21 +49,28 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.37.0
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0
|
||||
go.opentelemetry.io/otel/trace v1.37.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
google.golang.org/api v0.248.0
|
||||
google.golang.org/genproto v0.0.0-20250818200422-3122310a409c
|
||||
golang.org/x/oauth2 v0.31.0
|
||||
google.golang.org/api v0.249.0
|
||||
google.golang.org/genproto v0.0.0-20250826171959-ef028d996bc1
|
||||
modernc.org/sqlite v1.38.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/ClickHouse/ch-go v0.67.0 // indirect
|
||||
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.3 // indirect
|
||||
github.com/go-faster/city v1.0.1 // indirect
|
||||
github.com/go-faster/errors v0.7.1 // indirect
|
||||
github.com/paulmach/orb v0.11.1 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||
gonum.org/v1/gonum v0.16.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.24.0 // indirect
|
||||
cloud.google.com/go v0.121.4 // indirect
|
||||
cloud.google.com/go v0.121.6 // indirect
|
||||
cloud.google.com/go/alloydb v1.18.0 // indirect
|
||||
cloud.google.com/go/auth v0.16.5 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
@@ -72,14 +81,14 @@ require (
|
||||
cloud.google.com/go/trace v1.11.6 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.3 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0 // indirect
|
||||
github.com/PuerkitoBio/goquery v1.10.3 // indirect
|
||||
github.com/ajg/form v1.5.1 // indirect
|
||||
github.com/apache/arrow/go/v15 v15.0.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect
|
||||
github.com/couchbase/gocbcore/v10 v10.7.1 // indirect
|
||||
github.com/couchbase/gocbcore/v10 v10.8.0 // indirect
|
||||
github.com/couchbase/gocbcoreps v0.1.3 // indirect
|
||||
github.com/couchbase/goprotostellar v1.0.2 // indirect
|
||||
github.com/couchbase/tools-common/errors v1.0.0 // indirect
|
||||
@@ -90,7 +99,7 @@ require (
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.1 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
@@ -132,7 +141,6 @@ require (
|
||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
@@ -145,7 +153,7 @@ require (
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.62.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/aws v1.37.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.37.0 // indirect
|
||||
@@ -164,10 +172,10 @@ require (
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
golang.org/x/tools v0.35.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250811230008-5f3141c8851a // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect
|
||||
google.golang.org/grpc v1.74.2 // indirect
|
||||
google.golang.org/protobuf v1.36.7 // indirect
|
||||
google.golang.org/grpc v1.75.0 // indirect
|
||||
google.golang.org/protobuf v1.36.8 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
modernc.org/libc v1.66.3 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
|
||||
130
go.sum
130
go.sum
@@ -38,8 +38,8 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY
|
||||
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
|
||||
cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I=
|
||||
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
|
||||
cloud.google.com/go v0.121.4 h1:cVvUiY0sX0xwyxPwdSU2KsF9knOVmtRyAMt8xou0iTs=
|
||||
cloud.google.com/go v0.121.4/go.mod h1:XEBchUiHFJbz4lKBZwYBDHV/rSyfFktk737TLDU089s=
|
||||
cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c=
|
||||
cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI=
|
||||
cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4=
|
||||
cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw=
|
||||
cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E=
|
||||
@@ -137,10 +137,10 @@ cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/Zur
|
||||
cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac=
|
||||
cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q=
|
||||
cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU=
|
||||
cloud.google.com/go/bigquery v1.69.0 h1:rZvHnjSUs5sHK3F9awiuFk2PeOaB8suqNuim21GbaTc=
|
||||
cloud.google.com/go/bigquery v1.69.0/go.mod h1:TdGLquA3h/mGg+McX+GsqG9afAzTAcldMjqhdjHTLew=
|
||||
cloud.google.com/go/bigtable v1.38.0 h1:L/PnUXRtAzFfa7qMULJHt4cXa/O2dqPJEkzYNGA4hfo=
|
||||
cloud.google.com/go/bigtable v1.38.0/go.mod h1:o/lntJarF3Y5C0XYLMJLjLYwxaRbcrtM0BiV57ymXbI=
|
||||
cloud.google.com/go/bigquery v1.70.0 h1:V1OIhhOSionCOXWMmypXOvZu/ogkzosa7s1ArWJO/Yg=
|
||||
cloud.google.com/go/bigquery v1.70.0/go.mod h1:6lEAkgTJN+H2JcaX1eKiuEHTKyqBaJq5U3SpLGbSvwI=
|
||||
cloud.google.com/go/bigtable v1.39.0 h1:NF0aaSend+Z5CKND2vWY9fgDwaeZ4bDgzUdgw8rk75Y=
|
||||
cloud.google.com/go/bigtable v1.39.0/go.mod h1:zgL2Vxux9Bx+TcARDJDUxVyE+BCUfP2u4Zm9qeHF+g0=
|
||||
cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY=
|
||||
cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s=
|
||||
cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI=
|
||||
@@ -167,8 +167,8 @@ cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb
|
||||
cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM=
|
||||
cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk=
|
||||
cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA=
|
||||
cloud.google.com/go/cloudsqlconn v1.18.0 h1:mP6TY/7I+nrnIh6vmbWCRJPxpFBZSL6AZhW6HaYC/OI=
|
||||
cloud.google.com/go/cloudsqlconn v1.18.0/go.mod h1:58bxZZ17Mz5D83ddMT8x6w56yKpcmVXyaOwGWkzGcMw=
|
||||
cloud.google.com/go/cloudsqlconn v1.18.1 h1:IIvs7QJ8eqKUUHSon13Joie9oH7/i7MJwNzBLG+FrhM=
|
||||
cloud.google.com/go/cloudsqlconn v1.18.1/go.mod h1:58bxZZ17Mz5D83ddMT8x6w56yKpcmVXyaOwGWkzGcMw=
|
||||
cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY=
|
||||
cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI=
|
||||
cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4=
|
||||
@@ -563,8 +563,8 @@ cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeL
|
||||
cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
|
||||
cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y=
|
||||
cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4=
|
||||
cloud.google.com/go/storage v1.55.0 h1:NESjdAToN9u1tmhVqhXCaCwYBuvEhZLLv0gBr+2znf0=
|
||||
cloud.google.com/go/storage v1.55.0/go.mod h1:ztSmTTwzsdXe5syLVS0YsbFxXuvEmEyZj7v7zChEmuY=
|
||||
cloud.google.com/go/storage v1.56.0 h1:iixmq2Fse2tqxMbWhLWC9HfBj1qdxqAmiK8/eqtsLxI=
|
||||
cloud.google.com/go/storage v1.56.0/go.mod h1:Tpuj6t4NweCLzlNbw9Z9iwxEkrSem20AetIeH/shgVU=
|
||||
cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w=
|
||||
cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I=
|
||||
cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4=
|
||||
@@ -632,8 +632,8 @@ cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoIS
|
||||
cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M=
|
||||
cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
|
||||
cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
@@ -655,10 +655,14 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJ
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/ClickHouse/ch-go v0.67.0 h1:18MQF6vZHj+4/hTRaK7JbS/TIzn4I55wC+QzO24uiqc=
|
||||
github.com/ClickHouse/ch-go v0.67.0/go.mod h1:2MSAeyVmgt+9a2k2SQPPG1b4qbTPzdGDpf1+bcHh+18=
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.40.1 h1:PbwsHBgqXRydU7jKULD1C8CHmifczffvQqmFvltM2W4=
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.40.1/go.mod h1:GDzSBLVhladVm8V01aEB36IoBOVLLICfyeuiIp/8Ezc=
|
||||
github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.3 h1:2afWGsMzkIcN8Qm4mgPJKZWyroE5QBszMiDMYEBrnfw=
|
||||
github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.3/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0 h1:owcC2UnmsZycprQ5RfRgjydWhuoxg71LUfyiQdijZuM=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0/go.mod h1:ZPpqegjbE99EPKsu3iUWV22A04wzGPcAY/ziSIQEEgs=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.29.0 h1:YVtMlmfRUTaWs3+1acwMBp7rBUo6zrxl6Kn13/R9YW4=
|
||||
@@ -684,6 +688,8 @@ github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T
|
||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
||||
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
|
||||
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
@@ -770,10 +776,10 @@ github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv
|
||||
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||
github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8=
|
||||
github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
|
||||
github.com/couchbase/gocb/v2 v2.10.1 h1:5r1jngGxw3dTZdtq6Xmjq3pdU6hOwRvynvbVIp58T64=
|
||||
github.com/couchbase/gocb/v2 v2.10.1/go.mod h1:GGEJuYjrfnPHCQLcxTcIco+Puy63PS2p8QQd8FRw66I=
|
||||
github.com/couchbase/gocbcore/v10 v10.7.1 h1:6jsNDtqyfoQ8Xg6kv99rzccc3CrHbp7FjeY+ahWXTF4=
|
||||
github.com/couchbase/gocbcore/v10 v10.7.1/go.mod h1:Q8JWVenMCEOuRgrDQKApHbzzPif38HzefGgRVe9apAI=
|
||||
github.com/couchbase/gocb/v2 v2.11.0 h1:OVB+KlVeXlKVtziKx/LWZT7DClLsoQHQFrI4wan5Ijc=
|
||||
github.com/couchbase/gocb/v2 v2.11.0/go.mod h1:Y+lODSgyVzDSaf0Sy8sIzIa0RTAw3vlZUsjY6+FUq9Y=
|
||||
github.com/couchbase/gocbcore/v10 v10.8.0 h1:zDcJyYqOirFyC8T/aVvNL4N9oj6GI4qtaBuTGGWCDb4=
|
||||
github.com/couchbase/gocbcore/v10 v10.8.0/go.mod h1:OWKfU9R5Nm5V3QZBtfdZl5qCfgxtxTqOgXiNr4pn9/c=
|
||||
github.com/couchbase/gocbcoreps v0.1.3 h1:fILaKGCjxFIeCgAUG8FGmRDSpdrRggohOMKEgO9CUpg=
|
||||
github.com/couchbase/gocbcoreps v0.1.3/go.mod h1:hBFpDNPnRno6HH5cRXExhqXYRmTsFJlFHQx7vztcXPk=
|
||||
github.com/couchbase/goprotostellar v1.0.2 h1:yoPbAL9sCtcyZ5e/DcU5PRMOEFaJrF9awXYu3VPfGls=
|
||||
@@ -796,8 +802,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwenxRM7/rLu8=
|
||||
github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY=
|
||||
github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
|
||||
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
@@ -840,12 +846,16 @@ github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
|
||||
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
|
||||
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-chi/httplog/v2 v2.1.1 h1:ojojiu4PIaoeJ/qAO4GWUxJqvYUTobeo7zmuHQJAxRk=
|
||||
github.com/go-chi/httplog/v2 v2.1.1/go.mod h1:/XXdxicJsp4BA5fapgIC3VuTD+z0Z/VzukoB3VDc1YE=
|
||||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
|
||||
github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw=
|
||||
github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg=
|
||||
github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo=
|
||||
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
|
||||
github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
|
||||
github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
|
||||
@@ -856,8 +866,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-goquery/goquery v1.0.1 h1:kpchVA1LdOFWdRpkDPESVdlb1JQI6ixsJ5MiNUITO7U=
|
||||
github.com/go-goquery/goquery v1.0.1/go.mod h1:W5s8OWbqWf6lG0LkXWBeh7U1Y/X5XTI0Br65MHF8uJk=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI=
|
||||
github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
|
||||
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
|
||||
@@ -933,6 +943,7 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
|
||||
@@ -1058,8 +1069,8 @@ github.com/jackc/pgtype v1.14.4 h1:fKuNiCumbKTAIxQwXfB/nsrnkEI6bPJrrSiMKgbJ2j8=
|
||||
github.com/jackc/pgtype v1.14.4/go.mod h1:aKeozOde08iifGosdJpz9MBZonJOUJxqNpPBcMJTlVA=
|
||||
github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA=
|
||||
github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw=
|
||||
github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
|
||||
github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
|
||||
github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
|
||||
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
|
||||
github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0=
|
||||
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
@@ -1088,6 +1099,7 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
@@ -1119,8 +1131,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/microsoft/go-mssqldb v1.9.2 h1:nY8TmFMQOHpm2qVWo6y4I2mAmVdZqlGiMGAYt64Ibbs=
|
||||
github.com/microsoft/go-mssqldb v1.9.2/go.mod h1:GBbW9ASTiDC+mpgWDGKdm3FnFLTUsLYN3iFL90lQ+PA=
|
||||
github.com/microsoft/go-mssqldb v1.9.3 h1:hy4p+LDC8LIGvI3JATnLVmBOLMJbmn5X400mr5j0lPs=
|
||||
github.com/microsoft/go-mssqldb v1.9.3/go.mod h1:GBbW9ASTiDC+mpgWDGKdm3FnFLTUsLYN3iFL90lQ+PA=
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
|
||||
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
@@ -1134,6 +1146,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/nakagami/chacha20 v0.1.0 h1:2fbf5KeVUw7oRpAe6/A7DqvBJLYYu0ka5WstFbnkEVo=
|
||||
@@ -1142,19 +1155,22 @@ github.com/nakagami/firebirdsql v0.9.15 h1:Mf05jaFI8+kjy6sBstsAu76zOkJ44AGd6cpAp
|
||||
github.com/nakagami/firebirdsql v0.9.15/go.mod h1:bZKRs3rpHAjJgXAoc9YiPobTz3R22i41Zjo+llIS2B0=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.28.2 h1:uG7nMK0zS/a/iSWMZgCIY40SfYzWBc6uSrMONhiIS0U=
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.28.2/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k=
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.28.3 h1:OHP/vzX0oZ2YUY5DnGUp7QY21BIpOzw+Pp+Dga8zYl4=
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.28.3/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k=
|
||||
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
|
||||
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/opencontainers/runc v1.1.13 h1:98S2srgG9vw0zWcDpFMn5TRrh8kLxa/5OFUstuUhmRs=
|
||||
github.com/opencontainers/runc v1.1.13/go.mod h1:R016aXacfp/gwQBYw2FDGa9m+n6atbLWrYY8hNMT/sA=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/ory/dockertest/v3 v3.11.0 h1:OiHcxKAvSDUwsEVh2BjxQQc/5EHz9n0va9awCtNGuyA=
|
||||
github.com/ory/dockertest/v3 v3.11.0/go.mod h1:VIPxS1gwT9NpPOrfD3rACs8Y9Z7yhzO4SB194iUDnUI=
|
||||
github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU=
|
||||
github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
|
||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
||||
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
|
||||
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
|
||||
github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
|
||||
@@ -1179,8 +1195,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||
github.com/redis/go-redis/v9 v9.12.1 h1:k5iquqv27aBtnTm2tIkROUDp8JBXhXZIVu1InSgvovg=
|
||||
github.com/redis/go-redis/v9 v9.12.1/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/redis/go-redis/v9 v9.13.0 h1:PpmlVykE0ODh8P43U0HqC+2NXHXwG+GUtQyz+MPKGRg=
|
||||
github.com/redis/go-redis/v9 v9.13.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
@@ -1193,8 +1209,10 @@ github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWN
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
|
||||
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
@@ -1228,14 +1246,17 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/thlib/go-timezone-local v0.0.7 h1:fX8zd3aJydqLlTs/TrROrIIdztzsdFV23OzOQx31jII=
|
||||
github.com/thlib/go-timezone-local v0.0.7/go.mod h1:/Tnicc6m/lsJE0irFMA0LfIwTBo4QP7A8IfyIv4zZKI=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/trinodb/trino-go-client v0.328.0 h1:X6hrGGysA3nvyVcz8kJbBS98srLNTNsnNYwRkMC1atA=
|
||||
github.com/trinodb/trino-go-client v0.328.0/go.mod h1:e/nck9W6hy+9bbyZEpXKFlNsufn3lQGpUgDL1d5f1FI=
|
||||
github.com/valkey-io/valkey-go v1.0.64 h1:3u4+b6D6zs9JQs254TLy4LqitCMHHr9XorP9GGk7XY4=
|
||||
github.com/valkey-io/valkey-go v1.0.64/go.mod h1:bHmwjIEOrGq/ubOJfh5uMRs7Xj6mV3mQ/ZXUbmqpjqY=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
@@ -1244,8 +1265,13 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||
github.com/yugabyte/pgx/v5 v5.5.3-yb-5 h1:MV66FoH4HFsA9IC+h1hRY/+9Rmo040zVyZovOX7zpuk=
|
||||
github.com/yugabyte/pgx/v5 v5.5.3-yb-5/go.mod h1:2SxizGfDY7UDCRTtbI/xd98C/oGN7S/3YoGF8l9gx/c=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -1261,6 +1287,7 @@ github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b h1:7gd+rd8P3bqcn/96gOZa3F5dpJr/vEiDQYlNb/y2uNs=
|
||||
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
|
||||
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
||||
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
|
||||
go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
@@ -1276,8 +1303,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.62.0 h1:rbRJ8BBoVMsQShESYZ0FkvcITu8X8QNwJogcLUmDNNw=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.62.0/go.mod h1:ru6KHrNtNHxM4nD/vd6QrLVWgKhxPYgblq4VAtNawTQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY=
|
||||
go.opentelemetry.io/contrib/propagators/autoprop v0.62.0 h1:1+EHlhAe/tukctfePZRrDruB9vn7MdwyC+rf36nUSPM=
|
||||
@@ -1330,6 +1357,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
@@ -1439,6 +1467,7 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
@@ -1494,8 +1523,8 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec
|
||||
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
|
||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo=
|
||||
golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1794,8 +1823,8 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/
|
||||
google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI=
|
||||
google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0=
|
||||
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
||||
google.golang.org/api v0.248.0 h1:hUotakSkcwGdYUqzCRc5yGYsg4wXxpkKlW5ryVqvC1Y=
|
||||
google.golang.org/api v0.248.0/go.mod h1:yAFUAF56Li7IuIQbTFoLwXTCI6XCFKueOlS7S9e4F9k=
|
||||
google.golang.org/api v0.249.0 h1:0VrsWAKzIZi058aeq+I86uIXbNhm9GxSHpbmZ92a38w=
|
||||
google.golang.org/api v0.249.0/go.mod h1:dGk9qyI0UYPwO/cjt2q06LG/EhUpwZGdAbYF14wHHrQ=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@@ -1936,10 +1965,10 @@ google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOl
|
||||
google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||
google.golang.org/genproto v0.0.0-20250818200422-3122310a409c h1:ZERoum3uuqL0PRSc6SXielu26FN96T4BUGaaW0oL+c8=
|
||||
google.golang.org/genproto v0.0.0-20250818200422-3122310a409c/go.mod h1:Q8kep885BJnK3Jt6QZXIFeLHSzoAQtlI1CCloQigiyU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250811230008-5f3141c8851a h1:DMCgtIAIQGZqJXMVzJF4MV8BlWoJh2ZuFiRdAleyr58=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250811230008-5f3141c8851a/go.mod h1:y2yVLIE/CSMCPXaHnSKXxu1spLPnglFLegmgdY23uuE=
|
||||
google.golang.org/genproto v0.0.0-20250826171959-ef028d996bc1 h1:Nm5SEGIguOIBDXs5rhfz2aKwEVWlgwC58UcmEnLDc8Y=
|
||||
google.golang.org/genproto v0.0.0-20250826171959-ef028d996bc1/go.mod h1:Jz9LrroM7Mcm+a0QrLh4UpZ1B/WhjIbqwEcUf4y08nQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:qXWI/sQtv5UKboZ/zUk7h+mrf/lXORyI+n9DKDAusdg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
@@ -1983,8 +2012,8 @@ google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5v
|
||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||
google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
|
||||
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
@@ -2003,10 +2032,11 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
||||
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
||||
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.61.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
|
||||
@@ -22,8 +22,10 @@ import (
|
||||
|
||||
var expectedToolSources = []string{
|
||||
"alloydb-postgres-admin",
|
||||
"alloydb-postgres-observability",
|
||||
"alloydb-postgres",
|
||||
"bigquery",
|
||||
"clickhouse",
|
||||
"cloud-sql-mssql",
|
||||
"cloud-sql-mysql",
|
||||
"cloud-sql-postgres",
|
||||
@@ -32,6 +34,7 @@ var expectedToolSources = []string{
|
||||
"looker",
|
||||
"mssql",
|
||||
"mysql",
|
||||
"neo4j",
|
||||
"oceanbase",
|
||||
"postgres",
|
||||
"spanner-postgres",
|
||||
@@ -83,8 +86,10 @@ func TestLoadPrebuiltToolYAMLs(t *testing.T) {
|
||||
|
||||
func TestGetPrebuiltTool(t *testing.T) {
|
||||
alloydb_admin_config, _ := Get("alloydb-postgres-admin")
|
||||
alloydb_observability_config, _ := Get("alloydb-postgres-observability")
|
||||
alloydb_config, _ := Get("alloydb-postgres")
|
||||
bigquery_config, _ := Get("bigquery")
|
||||
clickhouse_config, _ := Get("clickhouse")
|
||||
cloudsqlpg_config, _ := Get("cloud-sql-postgres")
|
||||
cloudsqlmysql_config, _ := Get("cloud-sql-mysql")
|
||||
cloudsqlmssql_config, _ := Get("cloud-sql-mssql")
|
||||
@@ -96,15 +101,22 @@ func TestGetPrebuiltTool(t *testing.T) {
|
||||
postgresconfig, _ := Get("postgres")
|
||||
spanner_config, _ := Get("spanner")
|
||||
spannerpg_config, _ := Get("spanner-postgres")
|
||||
neo4jconfig, _ := Get("neo4j")
|
||||
if len(alloydb_admin_config) <= 0 {
|
||||
t.Fatalf("unexpected error: could not fetch alloydb prebuilt tools yaml")
|
||||
}
|
||||
if len(alloydb_config) <= 0 {
|
||||
t.Fatalf("unexpected error: could not fetch alloydb prebuilt tools yaml")
|
||||
}
|
||||
if len(alloydb_observability_config) <= 0 {
|
||||
t.Fatalf("unexpected error: could not fetch alloydb-observability prebuilt tools yaml")
|
||||
}
|
||||
if len(bigquery_config) <= 0 {
|
||||
t.Fatalf("unexpected error: could not fetch bigquery prebuilt tools yaml")
|
||||
}
|
||||
if len(clickhouse_config) <= 0 {
|
||||
t.Fatalf("unexpected error: could not fetch clickhouse prebuilt tools yaml")
|
||||
}
|
||||
if len(cloudsqlpg_config) <= 0 {
|
||||
t.Fatalf("unexpected error: could not fetch cloud sql pg prebuilt tools yaml")
|
||||
}
|
||||
@@ -138,6 +150,9 @@ func TestGetPrebuiltTool(t *testing.T) {
|
||||
if len(spannerpg_config) <= 0 {
|
||||
t.Fatalf("unexpected error: could not fetch spanner pg prebuilt tools yaml")
|
||||
}
|
||||
if len(neo4jconfig) <= 0 {
|
||||
t.Fatalf("unexpected error: could not fetch neo4j prebuilt tools yaml")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFailGetPrebuiltTool(t *testing.T) {
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
sources:
|
||||
cloud-monitoring-source:
|
||||
kind: cloud-monitoring
|
||||
tools:
|
||||
get_system_metrics:
|
||||
kind: cloud-monitoring-query-prometheus
|
||||
source: cloud-monitoring-source
|
||||
description: |
|
||||
Fetches system level cloudmonitoring data (timeseries metrics) for an AlloyDB cluster, instance.
|
||||
To use this tool, you must provide the Google Cloud `projectID` and a PromQL `query`.
|
||||
|
||||
Generate the PromQL `query` for AlloyDB system metrics using the provided metrics and rules. Get labels like `cluster_id` and `instance_id` from the user's intent.
|
||||
|
||||
Defaults:
|
||||
1. Interval: Use a default interval of `5m` for `_over_time` aggregation functions unless a different window is specified by the user.
|
||||
|
||||
PromQL Query Examples:
|
||||
1. Basic Time Series: `avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance"}[5m])`
|
||||
2. Top K: `topk(30, avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance"}[5m]))`
|
||||
3. Mean: `avg(avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="my-instance","cluster_id"="my-cluster"}[5m]))`
|
||||
4. Minimum: `min(min_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance","cluster_id"="alloydb-cluster"}[5m]))`
|
||||
5. Maximum: `max(max_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance","cluster_id"="alloydb-cluster"}[5m]))`
|
||||
6. Sum: `sum(avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance","cluster_id"="alloydb-cluster"}[5m]))`
|
||||
7. Count streams: `count(avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance","cluster_id"="alloydb-cluster"}[5m]))`
|
||||
8. Percentile with groupby on instanceid, clusterid: `quantile by ("instance_id","cluster_id")(0.99,avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","cluster_id"="my-cluster","instance_id"="my-instance"}[5m]))`
|
||||
|
||||
Available Metrics List: metricname. description. monitored resource. labels
|
||||
1. `alloydb.googleapis.com/instance/cpu/average_utilization`: The percentage of CPU being used on an instance. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
2. `alloydb.googleapis.com/instance/cpu/maximum_utilization`: Maximum CPU utilization across all currently serving nodes of the instance from 0 to 100. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
3. `alloydb.googleapis.com/cluster/storage/usage`: The total AlloyDB storage in bytes across the entire cluster. `alloydb.googleapis.com/Cluster`. `cluster_id`.
|
||||
4. `alloydb.googleapis.com/instance/postgres/replication/replicas`: The number of read replicas connected to the primary instance. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`, `state`, `replica_instance_id`.
|
||||
5. `alloydb.googleapis.com/instance/postgres/replication/maximum_lag`: The maximum replication time lag calculated across all serving read replicas of the instance. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`, `replica_instance_id`.
|
||||
6. `alloydb.googleapis.com/instance/memory/min_available_memory`: The minimum available memory across all currently serving nodes of the instance. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
7. `alloydb.googleapis.com/instance/postgres/instances`: The number of nodes in the instance, along with their status, which can be either up or down. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`, `status`.
|
||||
8. `alloydb.googleapis.com/database/postgresql/tuples`: Number of tuples (rows) by state per database in the instance. `alloydb.googleapis.com/Database`. `cluster_id`, `instance_id`, `database`, `state`.
|
||||
9. `alloydb.googleapis.com/database/postgresql/temp_bytes_written_for_top_databases`: The total amount of data(in bytes) written to temporary files by the queries per database for top 500 dbs. `alloydb.googleapis.com/Database`. `cluster_id`, `instance_id`, `database`.
|
||||
10. `alloydb.googleapis.com/database/postgresql/temp_files_written_for_top_databases`: The number of temporary files used for writing data per database while performing internal algorithms like join, sort etc for top 500 dbs. `alloydb.googleapis.com/Database`. `cluster_id`, `instance_id`, `database`.
|
||||
11. `alloydb.googleapis.com/database/postgresql/inserted_tuples_count_for_top_databases`: The total number of rows inserted per db for top 500 dbs as a result of the queries in the instance. `alloydb.googleapis.com/Database`. `cluster_id`, `instance_id`, `database`.
|
||||
12. `alloydb.googleapis.com/database/postgresql/updated_tuples_count_for_top_databases`: The total number of rows updated per db for top 500 dbs as a result of the queries in the instance. `alloydb.googleapis.com/Database`. `cluster_id`, `instance_id`, `database`.
|
||||
13. `alloydb.googleapis.com/database/postgresql/deleted_tuples_count_for_top_databases`: The total number of rows deleted per db for top 500 dbs as a result of the queries in the instance. `alloydb.googleapis.com/Database`. `cluster_id`, `instance_id`, `database`.
|
||||
14. `alloydb.googleapis.com/database/postgresql/backends_for_top_databases`: The current number of connections per database to the instance for top 500 dbs. `alloydb.googleapis.com/Database`. `cluster_id`, `instance_id`, `database`.
|
||||
15. `alloydb.googleapis.com/instance/postgresql/backends_by_state`: The current number of connections to the instance grouped by the state like idle, active, idle_in_transaction, idle_in_transaction_aborted, disabled, and fastpath_function_call. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`, `state`.
|
||||
16. `alloydb.googleapis.com/instance/postgresql/backends_for_top_applications`: The current number of connections to the AlloyDB instance, grouped by applications for top 500 applications. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`, `application_name`.
|
||||
17. `alloydb.googleapis.com/database/postgresql/new_connections_for_top_databases`: Total number of new connections added per database for top 500 databases to the instance. `alloydb.googleapis.com/Database`. `cluster_id`, `instance_id`, `database`.
|
||||
18. `alloydb.googleapis.com/database/postgresql/deadlock_count_for_top_databases`: Total number of deadlocks detected in the instance per database for top 500 dbs. `alloydb.googleapis.com/Database`. `cluster_id`, `instance_id`, `database`.
|
||||
19. `alloydb.googleapis.com/database/postgresql/statements_executed_count`: Total count of statements executed in the instance per database per operation_type. `alloydb.googleapis.com/Database`. `cluster_id`, `instance_id`, `database`, `operation_type`.
|
||||
20. `alloydb.googleapis.com/instance/postgresql/returned_tuples_count`: Number of rows scanned while processing the queries in the instance since the last sample. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
21. `alloydb.googleapis.com/instance/postgresql/fetched_tuples_count`: Number of rows fetched while processing the queries in the instance since the last sample. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
22. `alloydb.googleapis.com/instance/postgresql/updated_tuples_count`: Number of rows updated while processing the queries in the instance since the last sample. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
23. `alloydb.googleapis.com/instance/postgresql/inserted_tuples_count`: Number of rows inserted while processing the queries in the instance since the last sample. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
24. `alloydb.googleapis.com/instance/postgresql/deleted_tuples_count`: Number of rows deleted while processing the queries in the instance since the last sample. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
25. `alloydb.googleapis.com/instance/postgresql/written_tuples_count`: Number of rows written while processing the queries in the instance since the last sample. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
26. `alloydb.googleapis.com/instance/postgresql/deadlock_count`: Number of deadlocks detected in the instance. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
27. `alloydb.googleapis.com/instance/postgresql/blks_read`: Number of blocks read by Postgres that were not in the buffer cache. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
28. `alloydb.googleapis.com/instance/postgresql/blks_hit`: Number of times Postgres found the requested block in the buffer cache. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
29. `alloydb.googleapis.com/instance/postgresql/temp_bytes_written_count`: The total amount of data(in bytes) written to temporary files by the queries while performing internal algorithms like join, sort etc. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
30. `alloydb.googleapis.com/instance/postgresql/temp_files_written_count`: The number of temporary files used for writing data in the instance while performing internal algorithms like join, sort etc. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
31. `alloydb.googleapis.com/instance/postgresql/new_connections_count`: The number new connections added to the instance. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
32. `alloydb.googleapis.com/instance/postgresql/wait_count`: Total number of times processes waited for each wait event in the instance. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`, `wait_event_type`, `wait_event_name`.
|
||||
33. `alloydb.googleapis.com/instance/postgresql/wait_time`: Total elapsed wait time for each wait event in the instance. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`, `wait_event_type`, `wait_event_name`.
|
||||
34. `alloydb.googleapis.com/instance/postgres/transaction_count`: The number of committed and rolled back transactions across all serving nodes of the instance. `alloydb.googleapis.com/Instance`. `cluster_id`, `instance_id`.
|
||||
|
||||
get_query_metrics:
|
||||
kind: cloud-monitoring-query-prometheus
|
||||
source: cloud-monitoring-source
|
||||
description: |
|
||||
Fetches query level cloudmonitoring data (timeseries metrics) for queries running in an AlloyDB instance.
|
||||
To use this tool, you must provide the Google Cloud `projectId` and a PromQL `query`.
|
||||
|
||||
Generate the PromQL `query` for AlloyDB query metrics using the provided metrics and rules. Get labels like `cluster_id`, `instance_id`, and `query_hash` from the user's intent. If `query_hash` is provided, use the per-query metrics.
|
||||
|
||||
Defaults:
|
||||
1. Interval: Use a default interval of `5m` for `_over_time` aggregation functions unless a different window is specified by the user.
|
||||
|
||||
PromQL Query Examples:
|
||||
1. Basic Time Series: `avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance"}[5m])`
|
||||
2. Top K: `topk(30, avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance"}[5m]))`
|
||||
3. Mean: `avg(avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="my-instance","cluster_id"="my-cluster"}[5m]))`
|
||||
4. Minimum: `min(min_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance","cluster_id"="alloydb-cluster"}[5m]))`
|
||||
5. Maximum: `max(max_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance","cluster_id"="alloydb-cluster"}[5m]))`
|
||||
6. Sum: `sum(avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance","cluster_id"="alloydb-cluster"}[5m]))`
|
||||
7. Count streams: `count(avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance","cluster_id"="alloydb-cluster"}[5m]))`
|
||||
8. Percentile with groupby on instanceid, clusterid: `quantile by ("instance_id","cluster_id")(0.99,avg_over_time({"__name__"="alloydb.googleapis.com/instance/cpu/average_utilization","monitored_resource"="alloydb.googleapis.com/Instance","cluster_id"="my-cluster","instance_id"="my-instance"}[5m]))`
|
||||
|
||||
Available Metrics List: metricname. description. monitored resource. labels. aggregate is the aggregated values for all query stats, Use aggregate metrics if query id is not provided. For perquery metrics do not fetch querystring unless specified by user specifically. Have the aggregation on query hash to avoid fetching the querystring. Do not use latency metrics for anything.
|
||||
1. `alloydb.googleapis.com/database/postgresql/insights/aggregate/latencies`: Aggregated query latency distribution. `alloydb.googleapis.com/Database`. `user`, `client_addr`.
|
||||
2. `alloydb.googleapis.com/database/postgresql/insights/aggregate/execution_time`: Accumulated aggregated query execution time since the last sample. `alloydb.googleapis.com/Database`. `user`, `client_addr`.
|
||||
3. `alloydb.googleapis.com/database/postgresql/insights/aggregate/io_time`: Accumulated aggregated IO time since the last sample. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `io_type`.
|
||||
4. `alloydb.googleapis.com/database/postgresql/insights/aggregate/lock_time`: Accumulated aggregated lock wait time since the last sample. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `lock_type`.
|
||||
5. `alloydb.googleapis.com/database/postgresql/insights/aggregate/row_count`: Aggregated number of retrieved or affected rows since the last sample. `alloydb.googleapis.com/Database`. `user`, `client_addr`.
|
||||
6. `alloydb.googleapis.com/database/postgresql/insights/aggregate/shared_blk_access_count`: Aggregated shared blocks accessed by statement execution. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `access_type`.
|
||||
7. `alloydb.googleapis.com/database/postgresql/insights/perquery/latencies`: Per query latency distribution. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `querystring`, `query_hash`.
|
||||
8. `alloydb.googleapis.com/database/postgresql/insights/perquery/execution_time`: Accumulated execution times per user per database per query. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `querystring`, `query_hash`.
|
||||
9. `alloydb.googleapis.com/database/postgresql/insights/perquery/io_time`: Accumulated IO time since the last sample per query. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `io_type`, `querystring`, `query_hash`.
|
||||
10. `alloydb.googleapis.com/database/postgresql/insights/perquery/lock_time`: Accumulated lock wait time since the last sample per query. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `lock_type`, `querystring`, `query_hash`.
|
||||
11. `alloydb.googleapis.com/database/postgresql/insights/perquery/row_count`: The number of retrieved or affected rows since the last sample per query. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `querystring`, `query_hash`.
|
||||
12. `alloydb.googleapis.com/database/postgresql/insights/perquery/shared_blk_access_count`: Shared blocks accessed by statement execution per query. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `access_type`, `querystring`, `query_hash`.
|
||||
13. `alloydb.googleapis.com/database/postgresql/insights/pertag/latencies`: Query latency distribution. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `action`, `application`, `controller`, `db_driver`, `framework`, `route`, `tag_hash`.
|
||||
14. `alloydb.googleapis.com/database/postgresql/insights/pertag/execution_time`: Accumulated execution times since the last sample. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `action`, `application`, `controller`, `db_driver`, `framework`, `route`, `tag_hash`.
|
||||
15. `alloydb.googleapis.com/database/postgresql/insights/pertag/io_time`: Accumulated IO time since the last sample per tag. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `action`, `application`, `controller`, `db_driver`, `framework`, `route`, `io_type`, `tag_hash`.
|
||||
16. `alloydb.googleapis.com/database/postgresql/insights/pertag/lock_time`: Accumulated lock wait time since the last sample per tag. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `action`, `application`, `controller`, `db_driver`, `framework`, `route`, `lock_type`, `tag_hash`.
|
||||
17. `alloydb.googleapis.com/database/postgresql/insights/pertag/shared_blk_access_count`: Shared blocks accessed by statement execution per tag. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `action`, `application`, `controller`, `db_driver`, `framework`, `route`, `access_type`, `tag_hash`.
|
||||
18. `alloydb.googleapis.com/database/postgresql/insights/pertag/row_count`: The number of retrieved or affected rows since the last sample per tag. `alloydb.googleapis.com/Database`. `user`, `client_addr`, `action`, `application`, `controller`, `db_driver`, `framework`, `route`, `tag_hash`.
|
||||
|
||||
toolsets:
|
||||
alloydb-postgres-cloud-monitoring-tools:
|
||||
- get_system_metrics
|
||||
- get_query_metrics
|
||||
@@ -1,3 +1,17 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
sources:
|
||||
alloydb-pg-source:
|
||||
kind: "alloydb-postgres"
|
||||
@@ -6,8 +20,9 @@ sources:
|
||||
cluster: ${ALLOYDB_POSTGRES_CLUSTER}
|
||||
instance: ${ALLOYDB_POSTGRES_INSTANCE}
|
||||
database: ${ALLOYDB_POSTGRES_DATABASE}
|
||||
user: ${ALLOYDB_POSTGRES_USER}
|
||||
password: ${ALLOYDB_POSTGRES_PASSWORD}
|
||||
user: ${ALLOYDB_POSTGRES_USER:}
|
||||
password: ${ALLOYDB_POSTGRES_PASSWORD:}
|
||||
ipType: ${ALLOYDB_POSTGRES_IP_TYPE:public}
|
||||
|
||||
tools:
|
||||
execute_sql:
|
||||
@@ -16,93 +31,9 @@ tools:
|
||||
description: Use this tool to execute sql.
|
||||
|
||||
list_tables:
|
||||
kind: postgres-sql
|
||||
kind: postgres-list-tables
|
||||
source: alloydb-pg-source
|
||||
description: "Lists detailed schema information (object type, columns, constraints, indexes, triggers, owner, comment) as JSON for user-created tables (ordinary or partitioned). Filters by a comma-separated list of names. If names are omitted, lists all tables in user schemas."
|
||||
statement: |
|
||||
WITH desired_relkinds AS (
|
||||
SELECT ARRAY['r', 'p']::char[] AS kinds -- Always consider both 'TABLE' and 'PARTITIONED TABLE'
|
||||
),
|
||||
table_info AS (
|
||||
SELECT
|
||||
t.oid AS table_oid,
|
||||
ns.nspname AS schema_name,
|
||||
t.relname AS table_name,
|
||||
pg_get_userbyid(t.relowner) AS table_owner,
|
||||
obj_description(t.oid, 'pg_class') AS table_comment,
|
||||
t.relkind AS object_kind
|
||||
FROM
|
||||
pg_class t
|
||||
JOIN
|
||||
pg_namespace ns ON ns.oid = t.relnamespace
|
||||
CROSS JOIN desired_relkinds dk
|
||||
WHERE
|
||||
t.relkind = ANY(dk.kinds) -- Filter by selected table relkinds ('r', 'p')
|
||||
AND (NULLIF(TRIM($1), '') IS NULL OR t.relname = ANY(string_to_array($1,','))) -- $1 is object_names
|
||||
AND ns.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
|
||||
AND ns.nspname NOT LIKE 'pg_temp_%' AND ns.nspname NOT LIKE 'pg_toast_temp_%'
|
||||
),
|
||||
columns_info AS (
|
||||
SELECT
|
||||
att.attrelid AS table_oid, att.attname AS column_name, format_type(att.atttypid, att.atttypmod) AS data_type,
|
||||
att.attnum AS column_ordinal_position, att.attnotnull AS is_not_nullable,
|
||||
pg_get_expr(ad.adbin, ad.adrelid) AS column_default, col_description(att.attrelid, att.attnum) AS column_comment
|
||||
FROM pg_attribute att LEFT JOIN pg_attrdef ad ON att.attrelid = ad.adrelid AND att.attnum = ad.adnum
|
||||
JOIN table_info ti ON att.attrelid = ti.table_oid WHERE att.attnum > 0 AND NOT att.attisdropped
|
||||
),
|
||||
constraints_info AS (
|
||||
SELECT
|
||||
con.conrelid AS table_oid, con.conname AS constraint_name, pg_get_constraintdef(con.oid) AS constraint_definition,
|
||||
CASE con.contype WHEN 'p' THEN 'PRIMARY KEY' WHEN 'f' THEN 'FOREIGN KEY' WHEN 'u' THEN 'UNIQUE' WHEN 'c' THEN 'CHECK' ELSE con.contype::text END AS constraint_type,
|
||||
(SELECT array_agg(att.attname ORDER BY u.attposition) FROM unnest(con.conkey) WITH ORDINALITY AS u(attnum, attposition) JOIN pg_attribute att ON att.attrelid = con.conrelid AND att.attnum = u.attnum) AS constraint_columns,
|
||||
NULLIF(con.confrelid, 0)::regclass AS foreign_key_referenced_table,
|
||||
(SELECT array_agg(att.attname ORDER BY u.attposition) FROM unnest(con.confkey) WITH ORDINALITY AS u(attnum, attposition) JOIN pg_attribute att ON att.attrelid = con.confrelid AND att.attnum = u.attnum WHERE con.contype = 'f') AS foreign_key_referenced_columns
|
||||
FROM pg_constraint con JOIN table_info ti ON con.conrelid = ti.table_oid
|
||||
),
|
||||
indexes_info AS (
|
||||
SELECT
|
||||
idx.indrelid AS table_oid, ic.relname AS index_name, pg_get_indexdef(idx.indexrelid) AS index_definition,
|
||||
idx.indisunique AS is_unique, idx.indisprimary AS is_primary, am.amname AS index_method,
|
||||
(SELECT array_agg(att.attname ORDER BY u.ord) FROM unnest(idx.indkey::int[]) WITH ORDINALITY AS u(colidx, ord) LEFT JOIN pg_attribute att ON att.attrelid = idx.indrelid AND att.attnum = u.colidx WHERE u.colidx <> 0) AS index_columns
|
||||
FROM pg_index idx JOIN pg_class ic ON ic.oid = idx.indexrelid JOIN pg_am am ON am.oid = ic.relam JOIN table_info ti ON idx.indrelid = ti.table_oid
|
||||
),
|
||||
triggers_info AS (
|
||||
SELECT tg.tgrelid AS table_oid, tg.tgname AS trigger_name, pg_get_triggerdef(tg.oid) AS trigger_definition, tg.tgenabled AS trigger_enabled_state
|
||||
FROM pg_trigger tg JOIN table_info ti ON tg.tgrelid = ti.table_oid WHERE NOT tg.tgisinternal
|
||||
)
|
||||
SELECT
|
||||
ti.schema_name,
|
||||
ti.table_name AS object_name,
|
||||
CASE
|
||||
WHEN $2 = 'simple' THEN
|
||||
-- IF format is 'simple', return basic JSON
|
||||
json_build_object('name', ti.table_name)
|
||||
ELSE
|
||||
json_build_object(
|
||||
'schema_name', ti.schema_name,
|
||||
'object_name', ti.table_name,
|
||||
'object_type', CASE ti.object_kind
|
||||
WHEN 'r' THEN 'TABLE'
|
||||
WHEN 'p' THEN 'PARTITIONED TABLE'
|
||||
ELSE ti.object_kind::text -- Should not happen due to WHERE clause
|
||||
END,
|
||||
'owner', ti.table_owner,
|
||||
'comment', ti.table_comment,
|
||||
'columns', COALESCE((SELECT json_agg(json_build_object('column_name',ci.column_name,'data_type',ci.data_type,'ordinal_position',ci.column_ordinal_position,'is_not_nullable',ci.is_not_nullable,'column_default',ci.column_default,'column_comment',ci.column_comment) ORDER BY ci.column_ordinal_position) FROM columns_info ci WHERE ci.table_oid = ti.table_oid), '[]'::json),
|
||||
'constraints', COALESCE((SELECT json_agg(json_build_object('constraint_name',cons.constraint_name,'constraint_type',cons.constraint_type,'constraint_definition',cons.constraint_definition,'constraint_columns',cons.constraint_columns,'foreign_key_referenced_table',cons.foreign_key_referenced_table,'foreign_key_referenced_columns',cons.foreign_key_referenced_columns)) FROM constraints_info cons WHERE cons.table_oid = ti.table_oid), '[]'::json),
|
||||
'indexes', COALESCE((SELECT json_agg(json_build_object('index_name',ii.index_name,'index_definition',ii.index_definition,'is_unique',ii.is_unique,'is_primary',ii.is_primary,'index_method',ii.index_method,'index_columns',ii.index_columns)) FROM indexes_info ii WHERE ii.table_oid = ti.table_oid), '[]'::json),
|
||||
'triggers', COALESCE((SELECT json_agg(json_build_object('trigger_name',tri.trigger_name,'trigger_definition',tri.trigger_definition,'trigger_enabled_state',tri.trigger_enabled_state)) FROM triggers_info tri WHERE tri.table_oid = ti.table_oid), '[]'::json)
|
||||
)
|
||||
END AS object_details
|
||||
FROM table_info ti ORDER BY ti.schema_name, ti.table_name;
|
||||
parameters:
|
||||
- name: table_names
|
||||
type: string
|
||||
description: "Optional: A comma-separated list of table names. If empty, details for all tables in user-accessible schemas will be listed."
|
||||
- name: output_format
|
||||
type: string
|
||||
description: "Optional: Use 'simple' to return table names only or use 'detailed' to return the full information schema."
|
||||
default: "detailed"
|
||||
|
||||
toolsets:
|
||||
alloydb-postgres-database-tools:
|
||||
|
||||
@@ -1,9 +1,37 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
sources:
|
||||
bigquery-source:
|
||||
kind: "bigquery"
|
||||
project: ${BIGQUERY_PROJECT}
|
||||
location: ${BIGQUERY_LOCATION:}
|
||||
|
||||
tools:
|
||||
analyze_contribution:
|
||||
kind: bigquery-analyze-contribution
|
||||
source: bigquery-source
|
||||
description: Use this tool to analyze the contribution about changes to key metrics in multi-dimensional data.
|
||||
|
||||
ask_data_insights:
|
||||
kind: bigquery-conversational-analytics
|
||||
source: bigquery-source
|
||||
description: |
|
||||
Use this tool to perform data analysis, get insights,
|
||||
or answer complex questions about the contents of specific
|
||||
BigQuery tables.
|
||||
|
||||
execute_sql:
|
||||
kind: bigquery-execute-sql
|
||||
source: bigquery-source
|
||||
@@ -36,6 +64,8 @@ tools:
|
||||
|
||||
toolsets:
|
||||
bigquery-database-tools:
|
||||
- analyze_contribution
|
||||
- ask_data_insights
|
||||
- execute_sql
|
||||
- forecast
|
||||
- get_dataset_info
|
||||
|
||||
38
internal/prebuiltconfigs/tools/clickhouse.yaml
Normal file
38
internal/prebuiltconfigs/tools/clickhouse.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
sources:
|
||||
clickhouse-source:
|
||||
kind: clickhouse
|
||||
host: ${CLICKHOUSE_HOST}
|
||||
port: ${CLICKHOUSE_PORT}
|
||||
user: ${CLICKHOUSE_USER}
|
||||
password: ${CLICKHOUSE_PASSWORD}
|
||||
database: ${CLICKHOUSE_DATABASE}
|
||||
protocol: ${CLICKHOUSE_PROTOCOL}
|
||||
|
||||
tools:
|
||||
execute_sql:
|
||||
kind: clickhouse-execute-sql
|
||||
source: clickhouse-source
|
||||
description: Use this tool to execute SQL.
|
||||
|
||||
list_databases:
|
||||
kind: clickhouse-list-databases
|
||||
source: clickhouse-source
|
||||
description: Use this tool to list all databases in ClickHouse.
|
||||
|
||||
toolsets:
|
||||
clickhouse-database-tools:
|
||||
- execute_sql
|
||||
- list_databases
|
||||
@@ -1,3 +1,16 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
sources:
|
||||
cloudsql-mssql-source:
|
||||
kind: cloud-sql-mssql
|
||||
@@ -8,6 +21,7 @@ sources:
|
||||
ipAddress: ${CLOUD_SQL_MSSQL_IP_ADDRESS}
|
||||
user: ${CLOUD_SQL_MSSQL_USER}
|
||||
password: ${CLOUD_SQL_MSSQL_PASSWORD}
|
||||
ipType: ${CLOUD_SQL_MSSQL_IP_TYPE:public}
|
||||
tools:
|
||||
execute_sql:
|
||||
kind: mssql-execute-sql
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
sources:
|
||||
cloud-sql-mysql-source:
|
||||
kind: cloud-sql-mysql
|
||||
@@ -7,174 +21,16 @@ sources:
|
||||
database: ${CLOUD_SQL_MYSQL_DATABASE}
|
||||
user: ${CLOUD_SQL_MYSQL_USER}
|
||||
password: ${CLOUD_SQL_MYSQL_PASSWORD}
|
||||
ipType: ${CLOUD_SQL_MYSQL_IP_TYPE:PUBLIC}
|
||||
tools:
|
||||
execute_sql:
|
||||
kind: mysql-execute-sql
|
||||
source: cloud-sql-mysql-source
|
||||
description: Use this tool to execute SQL.
|
||||
list_tables:
|
||||
kind: mysql-sql
|
||||
kind: mysql-list-tables
|
||||
source: cloud-sql-mysql-source
|
||||
description: "Lists detailed schema information (object type, columns, constraints, indexes, triggers, comment) as JSON for user-created tables (ordinary or partitioned). Filters by a comma-separated list of names. If names are omitted, lists all tables in user schemas."
|
||||
statement: |
|
||||
SELECT
|
||||
T.TABLE_SCHEMA AS schema_name,
|
||||
T.TABLE_NAME AS object_name,
|
||||
CASE
|
||||
WHEN @output_format = 'simple' THEN
|
||||
JSON_OBJECT('name', T.TABLE_NAME)
|
||||
ELSE
|
||||
CONVERT( JSON_OBJECT(
|
||||
'schema_name', T.TABLE_SCHEMA,
|
||||
'object_name', T.TABLE_NAME,
|
||||
'object_type', 'TABLE',
|
||||
'owner', (
|
||||
SELECT
|
||||
IFNULL(U.GRANTEE, 'N/A')
|
||||
FROM
|
||||
INFORMATION_SCHEMA.SCHEMA_PRIVILEGES U
|
||||
WHERE
|
||||
U.TABLE_SCHEMA = T.TABLE_SCHEMA
|
||||
LIMIT 1
|
||||
),
|
||||
'comment', IFNULL(T.TABLE_COMMENT, ''),
|
||||
'columns', (
|
||||
SELECT
|
||||
IFNULL(
|
||||
JSON_ARRAYAGG(
|
||||
JSON_OBJECT(
|
||||
'column_name', C.COLUMN_NAME,
|
||||
'data_type', C.COLUMN_TYPE,
|
||||
'ordinal_position', C.ORDINAL_POSITION,
|
||||
'is_not_nullable', IF(C.IS_NULLABLE = 'NO', TRUE, FALSE),
|
||||
'column_default', C.COLUMN_DEFAULT,
|
||||
'column_comment', IFNULL(C.COLUMN_COMMENT, '')
|
||||
)
|
||||
),
|
||||
JSON_ARRAY()
|
||||
)
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS C
|
||||
WHERE
|
||||
C.TABLE_SCHEMA = T.TABLE_SCHEMA AND C.TABLE_NAME = T.TABLE_NAME
|
||||
ORDER BY C.ORDINAL_POSITION
|
||||
),
|
||||
'constraints', (
|
||||
SELECT
|
||||
IFNULL(
|
||||
JSON_ARRAYAGG(
|
||||
JSON_OBJECT(
|
||||
'constraint_name', TC.CONSTRAINT_NAME,
|
||||
'constraint_type',
|
||||
CASE TC.CONSTRAINT_TYPE
|
||||
WHEN 'PRIMARY KEY' THEN 'PRIMARY KEY'
|
||||
WHEN 'FOREIGN KEY' THEN 'FOREIGN KEY'
|
||||
WHEN 'UNIQUE' THEN 'UNIQUE'
|
||||
ELSE TC.CONSTRAINT_TYPE
|
||||
END,
|
||||
'constraint_definition', '',
|
||||
'constraint_columns', (
|
||||
SELECT
|
||||
IFNULL(JSON_ARRAYAGG(KCU.COLUMN_NAME), JSON_ARRAY())
|
||||
FROM
|
||||
INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU
|
||||
WHERE
|
||||
KCU.CONSTRAINT_SCHEMA = TC.CONSTRAINT_SCHEMA
|
||||
AND KCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
|
||||
AND KCU.TABLE_NAME = TC.TABLE_NAME
|
||||
ORDER BY KCU.ORDINAL_POSITION
|
||||
),
|
||||
'foreign_key_referenced_table', IF(TC.CONSTRAINT_TYPE = 'FOREIGN KEY', RC.REFERENCED_TABLE_NAME, NULL),
|
||||
'foreign_key_referenced_columns', IF(TC.CONSTRAINT_TYPE = 'FOREIGN KEY',
|
||||
(SELECT IFNULL(JSON_ARRAYAGG(FKCU.REFERENCED_COLUMN_NAME), JSON_ARRAY())
|
||||
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE FKCU
|
||||
WHERE FKCU.CONSTRAINT_SCHEMA = TC.CONSTRAINT_SCHEMA
|
||||
AND FKCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
|
||||
AND FKCU.TABLE_NAME = TC.TABLE_NAME
|
||||
AND FKCU.REFERENCED_TABLE_NAME IS NOT NULL
|
||||
ORDER BY FKCU.ORDINAL_POSITION),
|
||||
NULL
|
||||
)
|
||||
)
|
||||
),
|
||||
JSON_ARRAY()
|
||||
)
|
||||
FROM
|
||||
INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC
|
||||
LEFT JOIN
|
||||
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC
|
||||
ON TC.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA
|
||||
AND TC.CONSTRAINT_NAME = RC.CONSTRAINT_NAME
|
||||
AND TC.TABLE_NAME = RC.TABLE_NAME
|
||||
WHERE
|
||||
TC.TABLE_SCHEMA = T.TABLE_SCHEMA AND TC.TABLE_NAME = T.TABLE_NAME
|
||||
),
|
||||
'indexes', (
|
||||
SELECT
|
||||
IFNULL(
|
||||
JSON_ARRAYAGG(
|
||||
JSON_OBJECT(
|
||||
'index_name', IndexData.INDEX_NAME,
|
||||
'is_unique', IF(IndexData.NON_UNIQUE = 0, TRUE, FALSE),
|
||||
'is_primary', IF(IndexData.INDEX_NAME = 'PRIMARY', TRUE, FALSE),
|
||||
'index_columns', IFNULL(IndexData.INDEX_COLUMNS_ARRAY, JSON_ARRAY())
|
||||
)
|
||||
),
|
||||
JSON_ARRAY()
|
||||
)
|
||||
FROM (
|
||||
SELECT
|
||||
S.TABLE_SCHEMA,
|
||||
S.TABLE_NAME,
|
||||
S.INDEX_NAME,
|
||||
MIN(S.NON_UNIQUE) AS NON_UNIQUE, -- Aggregate NON_UNIQUE here to get unique status for the index
|
||||
JSON_ARRAYAGG(S.COLUMN_NAME) AS INDEX_COLUMNS_ARRAY -- Aggregate columns into an array for this index
|
||||
FROM
|
||||
INFORMATION_SCHEMA.STATISTICS S
|
||||
WHERE
|
||||
S.TABLE_SCHEMA = T.TABLE_SCHEMA AND S.TABLE_NAME = T.TABLE_NAME
|
||||
GROUP BY
|
||||
S.TABLE_SCHEMA, S.TABLE_NAME, S.INDEX_NAME
|
||||
) AS IndexData
|
||||
ORDER BY IndexData.INDEX_NAME
|
||||
),
|
||||
'triggers', (
|
||||
SELECT
|
||||
IFNULL(
|
||||
JSON_ARRAYAGG(
|
||||
JSON_OBJECT(
|
||||
'trigger_name', TR.TRIGGER_NAME,
|
||||
'trigger_definition', TR.ACTION_STATEMENT
|
||||
)
|
||||
),
|
||||
JSON_ARRAY()
|
||||
)
|
||||
FROM
|
||||
INFORMATION_SCHEMA.TRIGGERS TR
|
||||
WHERE
|
||||
TR.EVENT_OBJECT_SCHEMA = T.TABLE_SCHEMA AND TR.EVENT_OBJECT_TABLE = T.TABLE_NAME
|
||||
ORDER BY TR.TRIGGER_NAME
|
||||
)
|
||||
) USING utf8mb4)
|
||||
END AS object_details
|
||||
FROM
|
||||
INFORMATION_SCHEMA.TABLES T
|
||||
CROSS JOIN (SELECT @table_names := ?, @output_format := ?) AS variables
|
||||
WHERE
|
||||
T.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
|
||||
AND (NULLIF(TRIM(@table_names), '') IS NULL OR FIND_IN_SET(T.TABLE_NAME, @table_names))
|
||||
AND T.TABLE_TYPE = 'BASE TABLE'
|
||||
ORDER BY
|
||||
T.TABLE_SCHEMA, T.TABLE_NAME;
|
||||
parameters:
|
||||
- name: table_names
|
||||
type: string
|
||||
description: "Optional: A comma-separated list of table names. If empty, details for all tables in user-accessible schemas will be listed."
|
||||
default: ""
|
||||
- name: output_format
|
||||
type: string
|
||||
description: "Optional: Use 'simple' to return table names only or use 'detailed' to return the full information schema."
|
||||
default: "detailed"
|
||||
|
||||
toolsets:
|
||||
cloud-sql-mysql-database-tools:
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
sources:
|
||||
cloudsql-pg-source:
|
||||
kind: cloud-sql-postgres
|
||||
@@ -5,8 +19,9 @@ sources:
|
||||
region: ${CLOUD_SQL_POSTGRES_REGION}
|
||||
instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
|
||||
database: ${CLOUD_SQL_POSTGRES_DATABASE}
|
||||
user: ${CLOUD_SQL_POSTGRES_USER}
|
||||
password: ${CLOUD_SQL_POSTGRES_PASSWORD}
|
||||
user: ${CLOUD_SQL_POSTGRES_USER:}
|
||||
password: ${CLOUD_SQL_POSTGRES_PASSWORD:}
|
||||
ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE:public}
|
||||
|
||||
tools:
|
||||
execute_sql:
|
||||
@@ -15,93 +30,9 @@ tools:
|
||||
description: Use this tool to execute sql.
|
||||
|
||||
list_tables:
|
||||
kind: postgres-sql
|
||||
kind: postgres-list-tables
|
||||
source: cloudsql-pg-source
|
||||
description: "Lists detailed schema information (object type, columns, constraints, indexes, triggers, owner, comment) as JSON for user-created tables (ordinary or partitioned). Filters by a comma-separated list of names. If names are omitted, lists all tables in user schemas."
|
||||
statement: |
|
||||
WITH desired_relkinds AS (
|
||||
SELECT ARRAY['r', 'p']::char[] AS kinds -- Always consider both 'TABLE' and 'PARTITIONED TABLE'
|
||||
),
|
||||
table_info AS (
|
||||
SELECT
|
||||
t.oid AS table_oid,
|
||||
ns.nspname AS schema_name,
|
||||
t.relname AS table_name,
|
||||
pg_get_userbyid(t.relowner) AS table_owner,
|
||||
obj_description(t.oid, 'pg_class') AS table_comment,
|
||||
t.relkind AS object_kind
|
||||
FROM
|
||||
pg_class t
|
||||
JOIN
|
||||
pg_namespace ns ON ns.oid = t.relnamespace
|
||||
CROSS JOIN desired_relkinds dk
|
||||
WHERE
|
||||
t.relkind = ANY(dk.kinds) -- Filter by selected table relkinds ('r', 'p')
|
||||
AND (NULLIF(TRIM($1), '') IS NULL OR t.relname = ANY(string_to_array($1,','))) -- $1 is object_names
|
||||
AND ns.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
|
||||
AND ns.nspname NOT LIKE 'pg_temp_%' AND ns.nspname NOT LIKE 'pg_toast_temp_%'
|
||||
),
|
||||
columns_info AS (
|
||||
SELECT
|
||||
att.attrelid AS table_oid, att.attname AS column_name, format_type(att.atttypid, att.atttypmod) AS data_type,
|
||||
att.attnum AS column_ordinal_position, att.attnotnull AS is_not_nullable,
|
||||
pg_get_expr(ad.adbin, ad.adrelid) AS column_default, col_description(att.attrelid, att.attnum) AS column_comment
|
||||
FROM pg_attribute att LEFT JOIN pg_attrdef ad ON att.attrelid = ad.adrelid AND att.attnum = ad.adnum
|
||||
JOIN table_info ti ON att.attrelid = ti.table_oid WHERE att.attnum > 0 AND NOT att.attisdropped
|
||||
),
|
||||
constraints_info AS (
|
||||
SELECT
|
||||
con.conrelid AS table_oid, con.conname AS constraint_name, pg_get_constraintdef(con.oid) AS constraint_definition,
|
||||
CASE con.contype WHEN 'p' THEN 'PRIMARY KEY' WHEN 'f' THEN 'FOREIGN KEY' WHEN 'u' THEN 'UNIQUE' WHEN 'c' THEN 'CHECK' ELSE con.contype::text END AS constraint_type,
|
||||
(SELECT array_agg(att.attname ORDER BY u.attposition) FROM unnest(con.conkey) WITH ORDINALITY AS u(attnum, attposition) JOIN pg_attribute att ON att.attrelid = con.conrelid AND att.attnum = u.attnum) AS constraint_columns,
|
||||
NULLIF(con.confrelid, 0)::regclass AS foreign_key_referenced_table,
|
||||
(SELECT array_agg(att.attname ORDER BY u.attposition) FROM unnest(con.confkey) WITH ORDINALITY AS u(attnum, attposition) JOIN pg_attribute att ON att.attrelid = con.confrelid AND att.attnum = u.attnum WHERE con.contype = 'f') AS foreign_key_referenced_columns
|
||||
FROM pg_constraint con JOIN table_info ti ON con.conrelid = ti.table_oid
|
||||
),
|
||||
indexes_info AS (
|
||||
SELECT
|
||||
idx.indrelid AS table_oid, ic.relname AS index_name, pg_get_indexdef(idx.indexrelid) AS index_definition,
|
||||
idx.indisunique AS is_unique, idx.indisprimary AS is_primary, am.amname AS index_method,
|
||||
(SELECT array_agg(att.attname ORDER BY u.ord) FROM unnest(idx.indkey::int[]) WITH ORDINALITY AS u(colidx, ord) LEFT JOIN pg_attribute att ON att.attrelid = idx.indrelid AND att.attnum = u.colidx WHERE u.colidx <> 0) AS index_columns
|
||||
FROM pg_index idx JOIN pg_class ic ON ic.oid = idx.indexrelid JOIN pg_am am ON am.oid = ic.relam JOIN table_info ti ON idx.indrelid = ti.table_oid
|
||||
),
|
||||
triggers_info AS (
|
||||
SELECT tg.tgrelid AS table_oid, tg.tgname AS trigger_name, pg_get_triggerdef(tg.oid) AS trigger_definition, tg.tgenabled AS trigger_enabled_state
|
||||
FROM pg_trigger tg JOIN table_info ti ON tg.tgrelid = ti.table_oid WHERE NOT tg.tgisinternal
|
||||
)
|
||||
SELECT
|
||||
ti.schema_name,
|
||||
ti.table_name AS object_name,
|
||||
CASE
|
||||
WHEN $2 = 'simple' THEN
|
||||
-- IF format is 'simple', return basic JSON
|
||||
json_build_object('name', ti.table_name)
|
||||
ELSE
|
||||
json_build_object(
|
||||
'schema_name', ti.schema_name,
|
||||
'object_name', ti.table_name,
|
||||
'object_type', CASE ti.object_kind
|
||||
WHEN 'r' THEN 'TABLE'
|
||||
WHEN 'p' THEN 'PARTITIONED TABLE'
|
||||
ELSE ti.object_kind::text -- Should not happen due to WHERE clause
|
||||
END,
|
||||
'owner', ti.table_owner,
|
||||
'comment', ti.table_comment,
|
||||
'columns', COALESCE((SELECT json_agg(json_build_object('column_name',ci.column_name,'data_type',ci.data_type,'ordinal_position',ci.column_ordinal_position,'is_not_nullable',ci.is_not_nullable,'column_default',ci.column_default,'column_comment',ci.column_comment) ORDER BY ci.column_ordinal_position) FROM columns_info ci WHERE ci.table_oid = ti.table_oid), '[]'::json),
|
||||
'constraints', COALESCE((SELECT json_agg(json_build_object('constraint_name',cons.constraint_name,'constraint_type',cons.constraint_type,'constraint_definition',cons.constraint_definition,'constraint_columns',cons.constraint_columns,'foreign_key_referenced_table',cons.foreign_key_referenced_table,'foreign_key_referenced_columns',cons.foreign_key_referenced_columns)) FROM constraints_info cons WHERE cons.table_oid = ti.table_oid), '[]'::json),
|
||||
'indexes', COALESCE((SELECT json_agg(json_build_object('index_name',ii.index_name,'index_definition',ii.index_definition,'is_unique',ii.is_unique,'is_primary',ii.is_primary,'index_method',ii.index_method,'index_columns',ii.index_columns)) FROM indexes_info ii WHERE ii.table_oid = ti.table_oid), '[]'::json),
|
||||
'triggers', COALESCE((SELECT json_agg(json_build_object('trigger_name',tri.trigger_name,'trigger_definition',tri.trigger_definition,'trigger_enabled_state',tri.trigger_enabled_state)) FROM triggers_info tri WHERE tri.table_oid = ti.table_oid), '[]'::json)
|
||||
)
|
||||
END AS object_details
|
||||
FROM table_info ti ORDER BY ti.schema_name, ti.table_name;
|
||||
parameters:
|
||||
- name: table_names
|
||||
type: string
|
||||
description: "Optional: A comma-separated list of table names. If empty, details for all tables in user-accessible schemas will be listed."
|
||||
- name: output_format
|
||||
type: string
|
||||
description: "Optional: Use 'simple' to return table names only or use 'detailed' to return the full information schema."
|
||||
default: "detailed"
|
||||
|
||||
toolsets:
|
||||
cloud-sql-postgres-database-tools:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user