Compare commits

..

39 Commits

Author SHA1 Message Date
Twisha Bansal
1fb8f6fc5e update versions for v0.27.0 release 2026-02-13 11:20:19 +05:30
Twisha Bansal
9e92de2cbd Merge branch 'main' into binary-npx 2026-02-13 10:55:13 +05:30
Twisha Bansal
9670f25fdb have better release scripts 2026-01-27 14:25:13 +05:30
Twisha Bansal
7df74b16df update versions 2026-01-27 14:24:02 +05:30
Twisha Bansal
bd342c1b99 Merge branch 'main' into binary-npx 2026-01-27 14:20:47 +05:30
Anubhav Dhawan
57a2ade4c5 feat(npm): Bump server package versions to 0.25.0 and generate new platform-specific build artifacts. (#2284)
Releases the NPM package versions with latest toolbox release
(`v.0.25.0`).
2026-01-09 15:34:33 +05:30
Twisha Bansal
bcb3566ba3 update versions'
update versions
2026-01-09 14:32:43 +05:30
Twisha Bansal
47bbef10c5 update version 2026-01-09 14:32:43 +05:30
Twisha Bansal
44e782371e script for server release 2026-01-09 14:32:43 +05:30
Twisha Bansal
705be4018d update dep versions 2026-01-09 14:32:43 +05:30
Twisha Bansal
c968ed8925 rename file 2026-01-09 14:32:43 +05:30
Twisha Bansal
6f5911288d release dep package script 2026-01-09 14:32:43 +05:30
Twisha Bansal
cf42389d39 add script to update server packages 2026-01-09 14:32:43 +05:30
Twisha Bansal
49cb83ca5d update versions 2026-01-09 14:32:43 +05:30
Twisha Bansal
961c4726c7 bump version 2026-01-09 14:32:43 +05:30
Twisha Bansal
6e961ad48b update supported platforms 2026-01-09 14:32:43 +05:30
Twisha Bansal
d5a9031a65 bump version 2026-01-09 14:32:43 +05:30
Twisha Bansal
669b9b3b5d update linux package versions 2026-01-09 14:32:43 +05:30
Twisha Bansal
7bf04ddbb1 fix server package 2026-01-09 14:32:43 +05:30
Twisha Bansal
2705cf642c update server versions 2026-01-09 14:32:43 +05:30
Twisha Bansal
fb8f757eaf upate version 2026-01-09 14:32:43 +05:30
Twisha Bansal
6731e25cff remove apple quarantine 2026-01-09 14:32:43 +05:30
Twisha Bansal
0aece20ada Update downloadBinary.js 2026-01-09 14:32:43 +05:30
Twisha Bansal
401d0307d5 Update downloadBinary.js 2026-01-09 14:32:43 +05:30
Twisha Bansal
7479f5b871 Update downloadBinary.js 2026-01-09 14:32:43 +05:30
Twisha Bansal
a61a1d78a3 Update downloadBinary.js 2026-01-09 14:32:43 +05:30
Twisha Bansal
2fbf51968d Update testing.md 2026-01-09 14:32:43 +05:30
Twisha Bansal
54b56ee7cc fix 2026-01-09 14:32:43 +05:30
Twisha Bansal
39615a6011 fix path 2026-01-09 14:32:43 +05:30
Twisha Bansal
83562eb5ec fix package.json 2026-01-09 14:32:43 +05:30
Twisha Bansal
bb76fc6a84 fix testing 2026-01-09 14:32:43 +05:30
Twisha Bansal
21e4db2ed4 Update testing.md 2026-01-09 14:32:43 +05:30
Twisha Bansal
05e075b3fe Update testing.md 2026-01-09 14:32:43 +05:30
Twisha Bansal
e94eebc6af fix package 2026-01-09 14:32:43 +05:30
Twisha Bansal
e50dc777b7 Fixed readme 2026-01-09 14:32:43 +05:30
Twisha Bansal
1aaa84313c add markdown on how to test 2026-01-09 14:32:43 +05:30
Twisha Bansal
829e3168ff fix 2026-01-09 14:32:43 +05:30
Twisha Bansal
3d76f60401 fix 2026-01-09 14:32:43 +05:30
Twisha Bansal
d065b41598 add files 2026-01-09 14:32:43 +05:30
41 changed files with 896 additions and 1481 deletions

View File

@@ -943,7 +943,7 @@ steps:
# Install the C compiler and Oracle SDK headers needed for cgo
dnf install -y gcc oracle-instantclient-devel
# Install Go
curl -L -o go.tar.gz "https://go.dev/dl/go1.25.5.linux-amd64.tar.gz"
curl -L -o go.tar.gz "https://go.dev/dl/go1.25.1.linux-amd64.tar.gz"
tar -C /usr/local -xzf go.tar.gz
export PATH="/usr/local/go/bin:$$PATH"

View File

@@ -37,7 +37,6 @@ extraFiles: [
"docs/en/how-to/connect-ide/postgres_mcp.md",
"docs/en/how-to/connect-ide/neo4j_mcp.md",
"docs/en/how-to/connect-ide/sqlite_mcp.md",
"docs/en/how-to/connect-ide/oracle_mcp.md",
"gemini-extension.json",
{
"type": "json",

View File

@@ -618,505 +618,6 @@ func TestSingleEdit(t *testing.T) {
}
}
func TestPrebuiltTools(t *testing.T) {
// Get prebuilt configs
alloydb_omni_config, _ := prebuiltconfigs.Get("alloydb-omni")
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")
cloudsqlpg_admin_config, _ := prebuiltconfigs.Get("cloud-sql-postgres-admin")
cloudsqlmysql_config, _ := prebuiltconfigs.Get("cloud-sql-mysql")
cloudsqlmysql_admin_config, _ := prebuiltconfigs.Get("cloud-sql-mysql-admin")
cloudsqlmssql_config, _ := prebuiltconfigs.Get("cloud-sql-mssql")
cloudsqlmssql_admin_config, _ := prebuiltconfigs.Get("cloud-sql-mssql-admin")
dataplex_config, _ := prebuiltconfigs.Get("dataplex")
firestoreconfig, _ := prebuiltconfigs.Get("firestore")
mysql_config, _ := prebuiltconfigs.Get("mysql")
mssql_config, _ := prebuiltconfigs.Get("mssql")
looker_config, _ := prebuiltconfigs.Get("looker")
lookerca_config, _ := prebuiltconfigs.Get("looker-conversational-analytics")
postgresconfig, _ := prebuiltconfigs.Get("postgres")
spanner_config, _ := prebuiltconfigs.Get("spanner")
spannerpg_config, _ := prebuiltconfigs.Get("spanner-postgres")
mindsdb_config, _ := prebuiltconfigs.Get("mindsdb")
sqlite_config, _ := prebuiltconfigs.Get("sqlite")
neo4jconfig, _ := prebuiltconfigs.Get("neo4j")
alloydbobsvconfig, _ := prebuiltconfigs.Get("alloydb-postgres-observability")
cloudsqlpgobsvconfig, _ := prebuiltconfigs.Get("cloud-sql-postgres-observability")
cloudsqlmysqlobsvconfig, _ := prebuiltconfigs.Get("cloud-sql-mysql-observability")
cloudsqlmssqlobsvconfig, _ := prebuiltconfigs.Get("cloud-sql-mssql-observability")
serverless_spark_config, _ := prebuiltconfigs.Get("serverless-spark")
cloudhealthcare_config, _ := prebuiltconfigs.Get("cloud-healthcare")
snowflake_config, _ := prebuiltconfigs.Get("snowflake")
// Set environment variables
t.Setenv("API_KEY", "your_api_key")
t.Setenv("BIGQUERY_PROJECT", "your_gcp_project_id")
t.Setenv("DATAPLEX_PROJECT", "your_gcp_project_id")
t.Setenv("FIRESTORE_PROJECT", "your_gcp_project_id")
t.Setenv("FIRESTORE_DATABASE", "your_firestore_db_name")
t.Setenv("SPANNER_PROJECT", "your_gcp_project_id")
t.Setenv("SPANNER_INSTANCE", "your_spanner_instance")
t.Setenv("SPANNER_DATABASE", "your_spanner_db")
t.Setenv("ALLOYDB_POSTGRES_PROJECT", "your_gcp_project_id")
t.Setenv("ALLOYDB_POSTGRES_REGION", "your_gcp_region")
t.Setenv("ALLOYDB_POSTGRES_CLUSTER", "your_alloydb_cluster")
t.Setenv("ALLOYDB_POSTGRES_INSTANCE", "your_alloydb_instance")
t.Setenv("ALLOYDB_POSTGRES_DATABASE", "your_alloydb_db")
t.Setenv("ALLOYDB_POSTGRES_USER", "your_alloydb_user")
t.Setenv("ALLOYDB_POSTGRES_PASSWORD", "your_alloydb_password")
t.Setenv("ALLOYDB_OMNI_HOST", "localhost")
t.Setenv("ALLOYDB_OMNI_PORT", "5432")
t.Setenv("ALLOYDB_OMNI_DATABASE", "your_alloydb_db")
t.Setenv("ALLOYDB_OMNI_USER", "your_alloydb_user")
t.Setenv("ALLOYDB_OMNI_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")
t.Setenv("CLOUD_SQL_POSTGRES_REGION", "your_pg_region")
t.Setenv("CLOUD_SQL_POSTGRES_USER", "your_pg_user")
t.Setenv("CLOUD_SQL_POSTGRES_PASS", "your_pg_pass")
t.Setenv("CLOUD_SQL_MYSQL_PROJECT", "your_gcp_project_id")
t.Setenv("CLOUD_SQL_MYSQL_REGION", "your_gcp_region")
t.Setenv("CLOUD_SQL_MYSQL_INSTANCE", "your_instance")
t.Setenv("CLOUD_SQL_MYSQL_DATABASE", "your_cloudsql_mysql_db")
t.Setenv("CLOUD_SQL_MYSQL_USER", "your_cloudsql_mysql_user")
t.Setenv("CLOUD_SQL_MYSQL_PASSWORD", "your_cloudsql_mysql_password")
t.Setenv("CLOUD_SQL_MSSQL_PROJECT", "your_gcp_project_id")
t.Setenv("CLOUD_SQL_MSSQL_REGION", "your_gcp_region")
t.Setenv("CLOUD_SQL_MSSQL_INSTANCE", "your_cloudsql_mssql_instance")
t.Setenv("CLOUD_SQL_MSSQL_DATABASE", "your_cloudsql_mssql_db")
t.Setenv("CLOUD_SQL_MSSQL_IP_ADDRESS", "127.0.0.1")
t.Setenv("CLOUD_SQL_MSSQL_USER", "your_cloudsql_mssql_user")
t.Setenv("CLOUD_SQL_MSSQL_PASSWORD", "your_cloudsql_mssql_password")
t.Setenv("CLOUD_SQL_POSTGRES_PASSWORD", "your_cloudsql_pg_password")
t.Setenv("SERVERLESS_SPARK_PROJECT", "your_gcp_project_id")
t.Setenv("SERVERLESS_SPARK_LOCATION", "your_gcp_location")
t.Setenv("POSTGRES_HOST", "localhost")
t.Setenv("POSTGRES_PORT", "5432")
t.Setenv("POSTGRES_DATABASE", "your_postgres_db")
t.Setenv("POSTGRES_USER", "your_postgres_user")
t.Setenv("POSTGRES_PASSWORD", "your_postgres_password")
t.Setenv("MYSQL_HOST", "localhost")
t.Setenv("MYSQL_PORT", "3306")
t.Setenv("MYSQL_DATABASE", "your_mysql_db")
t.Setenv("MYSQL_USER", "your_mysql_user")
t.Setenv("MYSQL_PASSWORD", "your_mysql_password")
t.Setenv("MSSQL_HOST", "localhost")
t.Setenv("MSSQL_PORT", "1433")
t.Setenv("MSSQL_DATABASE", "your_mssql_db")
t.Setenv("MSSQL_USER", "your_mssql_user")
t.Setenv("MSSQL_PASSWORD", "your_mssql_password")
t.Setenv("MINDSDB_HOST", "localhost")
t.Setenv("MINDSDB_PORT", "47334")
t.Setenv("MINDSDB_DATABASE", "your_mindsdb_db")
t.Setenv("MINDSDB_USER", "your_mindsdb_user")
t.Setenv("MINDSDB_PASS", "your_mindsdb_password")
t.Setenv("LOOKER_BASE_URL", "https://your_company.looker.com")
t.Setenv("LOOKER_CLIENT_ID", "your_looker_client_id")
t.Setenv("LOOKER_CLIENT_SECRET", "your_looker_client_secret")
t.Setenv("LOOKER_VERIFY_SSL", "true")
t.Setenv("LOOKER_PROJECT", "your_project_id")
t.Setenv("LOOKER_LOCATION", "us")
t.Setenv("SQLITE_DATABASE", "test.db")
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")
t.Setenv("CLOUD_HEALTHCARE_PROJECT", "your_gcp_project_id")
t.Setenv("CLOUD_HEALTHCARE_REGION", "your_gcp_region")
t.Setenv("CLOUD_HEALTHCARE_DATASET", "your_healthcare_dataset")
t.Setenv("SNOWFLAKE_ACCOUNT", "your_account")
t.Setenv("SNOWFLAKE_USER", "your_username")
t.Setenv("SNOWFLAKE_PASSWORD", "your_pass")
t.Setenv("SNOWFLAKE_DATABASE", "your_db")
t.Setenv("SNOWFLAKE_SCHEMA", "your_schema")
t.Setenv("SNOWFLAKE_WAREHOUSE", "your_wh")
t.Setenv("SNOWFLAKE_ROLE", "your_role")
t.Setenv("ORACLE_USERNAME", "your_oracle_db_username")
t.Setenv("ORACLE_PASS", "your_oracle_db_password")
t.Setenv("ORACLE_HOST", "your_oracle_db_host")
t.Setenv("ORACLE_PORT", "your_oracle_db_port")
t.Setenv("ORACLE_SERVICE_NAME", "your_oracle_service_name")
t.Setenv("ORACLE_USE_OCI", "your_oracle_db_use_oci")
t.Setenv("ORACLE_WALLET_LOCATION", "your_path_to_oracldb_wallet")
t.Setenv("ORACLE_TNS_ADMIN", "your_path_to_tns_admin")
ctx, err := testutils.ContextWithNewLogger()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
tcs := []struct {
name string
in []byte
wantToolset server.ToolsetConfigs
}{
{
name: "alloydb omni prebuilt tools",
in: alloydb_omni_config,
wantToolset: server.ToolsetConfigs{
"alloydb_omni_database_tools": tools.ToolsetConfig{
Name: "alloydb_omni_database_tools",
ToolNames: []string{"execute_sql", "list_tables", "list_active_queries", "list_available_extensions", "list_installed_extensions", "list_autovacuum_configurations", "list_columnar_configurations", "list_columnar_recommended_columns", "list_memory_configurations", "list_top_bloated_tables", "list_replication_slots", "list_invalid_indexes", "get_query_plan", "list_views", "list_schemas", "database_overview", "list_triggers", "list_indexes", "list_sequences", "long_running_transactions", "list_locks", "replication_stats", "list_query_stats", "get_column_cardinality", "list_publication_tables", "list_tablespaces", "list_pg_settings", "list_database_stats", "list_roles", "list_table_stats", "list_stored_procedure"},
},
},
},
{
name: "alloydb postgres admin prebuilt tools",
in: alloydb_admin_config,
wantToolset: server.ToolsetConfigs{
"alloydb_postgres_admin_tools": tools.ToolsetConfig{
Name: "alloydb_postgres_admin_tools",
ToolNames: []string{"create_cluster", "wait_for_operation", "create_instance", "list_clusters", "list_instances", "list_users", "create_user", "get_cluster", "get_instance", "get_user"},
},
},
},
{
name: "cloudsql pg admin prebuilt tools",
in: cloudsqlpg_admin_config,
wantToolset: server.ToolsetConfigs{
"cloud_sql_postgres_admin_tools": tools.ToolsetConfig{
Name: "cloud_sql_postgres_admin_tools",
ToolNames: []string{"create_instance", "get_instance", "list_instances", "create_database", "list_databases", "create_user", "wait_for_operation", "postgres_upgrade_precheck", "clone_instance", "create_backup", "restore_backup"},
},
},
},
{
name: "cloudsql mysql admin prebuilt tools",
in: cloudsqlmysql_admin_config,
wantToolset: server.ToolsetConfigs{
"cloud_sql_mysql_admin_tools": tools.ToolsetConfig{
Name: "cloud_sql_mysql_admin_tools",
ToolNames: []string{"create_instance", "get_instance", "list_instances", "create_database", "list_databases", "create_user", "wait_for_operation", "clone_instance", "create_backup", "restore_backup"},
},
},
},
{
name: "cloudsql mssql admin prebuilt tools",
in: cloudsqlmssql_admin_config,
wantToolset: server.ToolsetConfigs{
"cloud_sql_mssql_admin_tools": tools.ToolsetConfig{
Name: "cloud_sql_mssql_admin_tools",
ToolNames: []string{"create_instance", "get_instance", "list_instances", "create_database", "list_databases", "create_user", "wait_for_operation", "clone_instance", "create_backup", "restore_backup"},
},
},
},
{
name: "alloydb prebuilt tools",
in: alloydb_config,
wantToolset: server.ToolsetConfigs{
"alloydb_postgres_database_tools": tools.ToolsetConfig{
Name: "alloydb_postgres_database_tools",
ToolNames: []string{"execute_sql", "list_tables", "list_active_queries", "list_available_extensions", "list_installed_extensions", "list_autovacuum_configurations", "list_memory_configurations", "list_top_bloated_tables", "list_replication_slots", "list_invalid_indexes", "get_query_plan", "list_views", "list_schemas", "database_overview", "list_triggers", "list_indexes", "list_sequences", "long_running_transactions", "list_locks", "replication_stats", "list_query_stats", "get_column_cardinality", "list_publication_tables", "list_tablespaces", "list_pg_settings", "list_database_stats", "list_roles", "list_table_stats", "list_stored_procedure"},
},
},
},
{
name: "bigquery prebuilt tools",
in: bigquery_config,
wantToolset: server.ToolsetConfigs{
"bigquery_database_tools": tools.ToolsetConfig{
Name: "bigquery_database_tools",
ToolNames: []string{"analyze_contribution", "ask_data_insights", "execute_sql", "forecast", "get_dataset_info", "get_table_info", "list_dataset_ids", "list_table_ids", "search_catalog"},
},
},
},
{
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", "list_tables"},
},
},
},
{
name: "cloudsqlpg prebuilt tools",
in: cloudsqlpg_config,
wantToolset: server.ToolsetConfigs{
"cloud_sql_postgres_database_tools": tools.ToolsetConfig{
Name: "cloud_sql_postgres_database_tools",
ToolNames: []string{"execute_sql", "list_tables", "list_active_queries", "list_available_extensions", "list_installed_extensions", "list_autovacuum_configurations", "list_memory_configurations", "list_top_bloated_tables", "list_replication_slots", "list_invalid_indexes", "get_query_plan", "list_views", "list_schemas", "database_overview", "list_triggers", "list_indexes", "list_sequences", "long_running_transactions", "list_locks", "replication_stats", "list_query_stats", "get_column_cardinality", "list_publication_tables", "list_tablespaces", "list_pg_settings", "list_database_stats", "list_roles", "list_table_stats", "list_stored_procedure"},
},
},
},
{
name: "cloudsqlmysql prebuilt tools",
in: cloudsqlmysql_config,
wantToolset: server.ToolsetConfigs{
"cloud_sql_mysql_database_tools": tools.ToolsetConfig{
Name: "cloud_sql_mysql_database_tools",
ToolNames: []string{"execute_sql", "list_tables", "get_query_plan", "list_active_queries", "list_tables_missing_unique_indexes", "list_table_fragmentation"},
},
},
},
{
name: "cloudsqlmssql prebuilt tools",
in: cloudsqlmssql_config,
wantToolset: server.ToolsetConfigs{
"cloud_sql_mssql_database_tools": tools.ToolsetConfig{
Name: "cloud_sql_mssql_database_tools",
ToolNames: []string{"execute_sql", "list_tables"},
},
},
},
{
name: "dataplex prebuilt tools",
in: dataplex_config,
wantToolset: server.ToolsetConfigs{
"dataplex_tools": tools.ToolsetConfig{
Name: "dataplex_tools",
ToolNames: []string{"search_entries", "lookup_entry", "search_aspect_types"},
},
},
},
{
name: "serverless spark prebuilt tools",
in: serverless_spark_config,
wantToolset: server.ToolsetConfigs{
"serverless_spark_tools": tools.ToolsetConfig{
Name: "serverless_spark_tools",
ToolNames: []string{"list_batches", "get_batch", "cancel_batch", "create_pyspark_batch", "create_spark_batch"},
},
},
},
{
name: "firestore prebuilt tools",
in: firestoreconfig,
wantToolset: server.ToolsetConfigs{
"firestore_database_tools": tools.ToolsetConfig{
Name: "firestore_database_tools",
ToolNames: []string{"get_documents", "add_documents", "update_document", "list_collections", "delete_documents", "query_collection", "get_rules", "validate_rules"},
},
},
},
{
name: "mysql prebuilt tools",
in: mysql_config,
wantToolset: server.ToolsetConfigs{
"mysql_database_tools": tools.ToolsetConfig{
Name: "mysql_database_tools",
ToolNames: []string{"execute_sql", "list_tables", "get_query_plan", "list_active_queries", "list_tables_missing_unique_indexes", "list_table_fragmentation"},
},
},
},
{
name: "mssql prebuilt tools",
in: mssql_config,
wantToolset: server.ToolsetConfigs{
"mssql_database_tools": tools.ToolsetConfig{
Name: "mssql_database_tools",
ToolNames: []string{"execute_sql", "list_tables"},
},
},
},
{
name: "looker prebuilt tools",
in: looker_config,
wantToolset: server.ToolsetConfigs{
"looker_tools": tools.ToolsetConfig{
Name: "looker_tools",
ToolNames: []string{"get_models", "get_explores", "get_dimensions", "get_measures", "get_filters", "get_parameters", "query", "query_sql", "query_url", "get_looks", "run_look", "make_look", "get_dashboards", "run_dashboard", "make_dashboard", "add_dashboard_element", "add_dashboard_filter", "generate_embed_url", "health_pulse", "health_analyze", "health_vacuum", "dev_mode", "get_projects", "get_project_files", "get_project_file", "create_project_file", "update_project_file", "delete_project_file", "validate_project", "get_connections", "get_connection_schemas", "get_connection_databases", "get_connection_tables", "get_connection_table_columns"},
},
},
},
{
name: "looker-conversational-analytics prebuilt tools",
in: lookerca_config,
wantToolset: server.ToolsetConfigs{
"looker_conversational_analytics_tools": tools.ToolsetConfig{
Name: "looker_conversational_analytics_tools",
ToolNames: []string{"ask_data_insights", "get_models", "get_explores"},
},
},
},
{
name: "postgres prebuilt tools",
in: postgresconfig,
wantToolset: server.ToolsetConfigs{
"postgres_database_tools": tools.ToolsetConfig{
Name: "postgres_database_tools",
ToolNames: []string{"execute_sql", "list_tables", "list_active_queries", "list_available_extensions", "list_installed_extensions", "list_autovacuum_configurations", "list_memory_configurations", "list_top_bloated_tables", "list_replication_slots", "list_invalid_indexes", "get_query_plan", "list_views", "list_schemas", "database_overview", "list_triggers", "list_indexes", "list_sequences", "long_running_transactions", "list_locks", "replication_stats", "list_query_stats", "get_column_cardinality", "list_publication_tables", "list_tablespaces", "list_pg_settings", "list_database_stats", "list_roles", "list_table_stats", "list_stored_procedure"},
},
},
},
{
name: "spanner prebuilt tools",
in: spanner_config,
wantToolset: server.ToolsetConfigs{
"spanner-database-tools": tools.ToolsetConfig{
Name: "spanner-database-tools",
ToolNames: []string{"execute_sql", "execute_sql_dql", "list_tables", "list_graphs"},
},
},
},
{
name: "spanner pg prebuilt tools",
in: spannerpg_config,
wantToolset: server.ToolsetConfigs{
"spanner_postgres_database_tools": tools.ToolsetConfig{
Name: "spanner_postgres_database_tools",
ToolNames: []string{"execute_sql", "execute_sql_dql", "list_tables"},
},
},
},
{
name: "mindsdb prebuilt tools",
in: mindsdb_config,
wantToolset: server.ToolsetConfigs{
"mindsdb-tools": tools.ToolsetConfig{
Name: "mindsdb-tools",
ToolNames: []string{"mindsdb-execute-sql", "mindsdb-sql"},
},
},
},
{
name: "sqlite prebuilt tools",
in: sqlite_config,
wantToolset: server.ToolsetConfigs{
"sqlite_database_tools": tools.ToolsetConfig{
Name: "sqlite_database_tools",
ToolNames: []string{"execute_sql", "list_tables"},
},
},
},
{
name: "neo4j prebuilt tools",
in: neo4jconfig,
wantToolset: server.ToolsetConfigs{
"neo4j_database_tools": tools.ToolsetConfig{
Name: "neo4j_database_tools",
ToolNames: []string{"execute_cypher", "get_schema"},
},
},
},
{
name: "alloydb postgres observability prebuilt tools",
in: alloydbobsvconfig,
wantToolset: server.ToolsetConfigs{
"alloydb_postgres_cloud_monitoring_tools": tools.ToolsetConfig{
Name: "alloydb_postgres_cloud_monitoring_tools",
ToolNames: []string{"get_system_metrics", "get_query_metrics"},
},
},
},
{
name: "cloudsql postgres observability prebuilt tools",
in: cloudsqlpgobsvconfig,
wantToolset: server.ToolsetConfigs{
"cloud_sql_postgres_cloud_monitoring_tools": tools.ToolsetConfig{
Name: "cloud_sql_postgres_cloud_monitoring_tools",
ToolNames: []string{"get_system_metrics", "get_query_metrics"},
},
},
},
{
name: "cloudsql mysql observability prebuilt tools",
in: cloudsqlmysqlobsvconfig,
wantToolset: server.ToolsetConfigs{
"cloud_sql_mysql_cloud_monitoring_tools": tools.ToolsetConfig{
Name: "cloud_sql_mysql_cloud_monitoring_tools",
ToolNames: []string{"get_system_metrics", "get_query_metrics"},
},
},
},
{
name: "cloudsql mssql observability prebuilt tools",
in: cloudsqlmssqlobsvconfig,
wantToolset: server.ToolsetConfigs{
"cloud_sql_mssql_cloud_monitoring_tools": tools.ToolsetConfig{
Name: "cloud_sql_mssql_cloud_monitoring_tools",
ToolNames: []string{"get_system_metrics"},
},
},
},
{
name: "cloud healthcare prebuilt tools",
in: cloudhealthcare_config,
wantToolset: server.ToolsetConfigs{
"cloud_healthcare_dataset_tools": tools.ToolsetConfig{
Name: "cloud_healthcare_dataset_tools",
ToolNames: []string{"get_dataset", "list_dicom_stores", "list_fhir_stores"},
},
"cloud_healthcare_fhir_tools": tools.ToolsetConfig{
Name: "cloud_healthcare_fhir_tools",
ToolNames: []string{"get_fhir_store", "get_fhir_store_metrics", "get_fhir_resource", "fhir_patient_search", "fhir_patient_everything", "fhir_fetch_page"},
},
"cloud_healthcare_dicom_tools": tools.ToolsetConfig{
Name: "cloud_healthcare_dicom_tools",
ToolNames: []string{"get_dicom_store", "get_dicom_store_metrics", "search_dicom_studies", "search_dicom_series", "search_dicom_instances", "retrieve_rendered_dicom_instance"},
},
},
},
{
name: "Snowflake prebuilt tool",
in: snowflake_config,
wantToolset: server.ToolsetConfigs{
"snowflake_tools": tools.ToolsetConfig{
Name: "snowflake_tools",
ToolNames: []string{"execute_sql", "list_tables"},
},
},
},
{
name: "Oracle prebuilt tool",
in: oracle_config,
wantToolset: server.ToolsetConfigs{
"oracle_tools": tools.ToolsetConfig{
Name: "oracle_tools",
ToolNames: []string{"execute_sql", "list_tables","list_active_sessions","list_top_sql_by_resource","get_query_plan","list_tablespace_usage"},
},
},
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
toolsFile, err := parseToolsFile(ctx, tc.in)
if err != nil {
t.Fatalf("failed to parse input: %v", err)
}
if diff := cmp.Diff(tc.wantToolset, toolsFile.Toolsets); diff != "" {
t.Fatalf("incorrect tools parse: diff %v", diff)
}
// Prebuilt configs do not have prompts, so assert empty maps.
if len(toolsFile.Prompts) != 0 {
t.Fatalf("expected empty prompts map for prebuilt config, got: %v", toolsFile.Prompts)
}
})
}
}
func TestMutuallyExclusiveFlags(t *testing.T) {
testCases := []struct {
desc string

View File

@@ -1,335 +0,0 @@
---
title: "Oracle using MCP"
type: docs
weight: 2
description: >
Connect your IDE to Oracle using Toolbox.
---
[Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) is
an open protocol for connecting Large Language Models (LLMs) to data sources
like Oracle. This guide covers how to use [MCP Toolbox for Databases][toolbox]
to expose your developer assistant tools to an Oracle 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 an Oracle instance.
1. Create or reuse a database user and have the username and password ready.
## 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.26.0+:
<!-- {x-release-please-start-version} -->
{{< tabpane persist=header >}}
{{< tab header="linux/amd64" lang="bash" >}}
curl -O https://storage.googleapis.com/genai-toolbox/v0.26.0/linux/amd64/toolbox
{{< /tab >}}
{{< tab header="darwin/arm64" lang="bash" >}}
curl -O https://storage.googleapis.com/genai-toolbox/v0.26.0/darwin/arm64/toolbox
{{< /tab >}}
{{< tab header="darwin/amd64" lang="bash" >}}
curl -O https://storage.googleapis.com/genai-toolbox/v0.26.0/darwin/amd64/toolbox
{{< /tab >}}
{{< tab header="windows/amd64" lang="bash" >}}
curl -O https://storage.googleapis.com/genai-toolbox/v0.26.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": {
"oracle": {
"command": "./PATH/TO/toolbox",
"args": ["--prebuilt","oracledb","--stdio"],
"env": {
"ORACLE_HOST": "",
"ORACLE_PORT": "1521",
"ORACLE_SERVICE": "",
"ORACLE_USER": "",
"ORACLE_PASSWORD": "",
"ORACLE_WALLET_LOCATION": "",
"ORACLE_USE_OCI": ""
}
}
}
}
```
1. Restart Claude code to apply the new configuration.
{{% /tab %}}
{{% tab header="Claude desktop" lang="en" %}}
1. Open Claude desktop 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": {
"oracle": {
"command": "./PATH/TO/toolbox",
"args": ["--prebuilt","oracledb","--stdio"],
"env": {
"ORACLE_HOST": "",
"ORACLE_PORT": "1521",
"ORACLE_SERVICE": "",
"ORACLE_USER": "",
"ORACLE_PASSWORD": "",
"ORACLE_WALLET_LOCATION": "",
"ORACLE_USE_OCI": ""
}
}
}
}
```
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 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": {
"oracle": {
"command": "./PATH/TO/toolbox",
"args": ["--prebuilt","oracledb","--stdio"],
"env": {
"ORACLE_HOST": "",
"ORACLE_PORT": "1521",
"ORACLE_SERVICE": "",
"ORACLE_USER": "",
"ORACLE_PASSWORD": "",
"ORACLE_WALLET_LOCATION": "",
"ORACLE_USE_OCI": ""
}
}
}
}
```
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": {
"oracle": {
"command": "./PATH/TO/toolbox",
"args": ["--prebuilt","oracledb","--stdio"],
"env": {
"ORACLE_HOST": "",
"ORACLE_PORT": "1521",
"ORACLE_SERVICE": "",
"ORACLE_USER": "",
"ORACLE_PASSWORD": "",
"ORACLE_WALLET_LOCATION": "",
"ORACLE_USE_OCI": ""
}
}
}
}
```
1. Cursor 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 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
{
"servers": {
"oracle": {
"command": "./PATH/TO/toolbox",
"args": ["--prebuilt","oracle","--stdio"],
"env": {
"ORACLE_HOST": "",
"ORACLE_PORT": "1521",
"ORACLE_SERVICE": "",
"ORACLE_USER": "",
"ORACLE_PASSWORD": ""
}
}
}
}
```
{{% /tab %}}
{{% tab header="Windsurf" lang="en" %}}
1. Open 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": {
"oracle": {
"command": "./PATH/TO/toolbox",
"args": ["--prebuilt","oracledb","--stdio"],
"env": {
"ORACLE_HOST": "",
"ORACLE_PORT": "1521",
"ORACLE_SERVICE": "",
"ORACLE_USER": "",
"ORACLE_PASSWORD": "",
"ORACLE_WALLET": "",
"ORACLE_WALLET_PASSWORD": ""
}
}
}
}
```
{{% /tab %}}
{{% tab header="Gemini CLI" lang="en" %}}
1. Install the Gemini CLI.
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": {
"oracle": {
"command": "./PATH/TO/toolbox",
"args": ["--prebuilt","oracledb","--stdio"],
"env": {
"ORACLE_HOST": "",
"ORACLE_PORT": "1521",
"ORACLE_SERVICE": "",
"ORACLE_USER": "",
"ORACLE_PASSWORD": ""
}
}
}
}
```
{{% /tab %}}
{{% tab header="Gemini Code Assist" lang="en" %}}
1. Install the Gemini Code Assist 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": {
"oracle": {
"command": "./PATH/TO/toolbox",
"args": ["--prebuilt","oracledb","--stdio"],
"env": {
"ORACLE_HOST": "",
"ORACLE_PORT": "1521",
"ORACLE_SERVICE": "",
"ORACLE_USER": "",
"ORACLE_PASSWORD": ""
}
}
}
}
```
{{% /tab %}}
{{< /tabpane >}}
## Use Tools
Your AI tool is now connected to Oracle using MCP. Try asking your AI
assistant to list tables, create a table, or define and execute other SQL
statements.
The following tools are available to the LLM:
1. **list_tables**: lists tables and descriptions
1. **execute_sql**: execute any SQL 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 >}}

View File

@@ -692,34 +692,6 @@ See [Usage Examples](../reference/cli.md#examples).
* `execute_cypher`: Executes a Cypher query.
* `get_schema`: Retrieves the schema of the Neo4j database.
## Oracle
* `--prebuilt` value: `oracle`
* **Environment Variables:**
* `ORACLE_HOST`: The hostname or IP address of the Oracle server.
* `ORACLE_PORT`: The port number for the Oracle server (Default: 1521).
* `ORACLE_CONNECTION_STRING`: The
* `ORACLE_USER`: The username for the Oracle DB instance.
* `ORACLE_PASSWORD`: The password for the Oracle DB instance
* `ORACLE_WALLET`: The path to Oracle DB Wallet file for the databases that support this authentication type
* `ORACLE_USE_OCI`: true or false, The flag if the Oracle Database is deployed in cloud deployment. Default is false.
* **Permissions:**
* Database-level permissions (e.g., `SELECT`, `INSERT`) are required to execute queries.
* **Tools:**
* `execute_sql`: Executes a SQL query.
* `list_tables`: Lists tables in the database.
* `list_active_sessions`: Lists active database sessions.
* `get_query_plan`: Gets the execution plan for a SQL statement.
* `list_top_sql_by_resource`: Lists top SQL statements by resource usage.
* `list_tablespace_usage`: Lists tablespace usage.
* `list_invalid_objects`: Lists invalid objects.
* `list_active_sessions`: Lists active database sessions.
* `get_query_plan`: Gets the execution plan for a SQL statement.
* `list_top_sql_by_resource`: Lists top SQL statements by resource usage.
* `list_tablespace_usage`: Lists tablespace usage.
* `list_invalid_objects`: Lists invalid objects.
## Google Cloud Healthcare API
* `--prebuilt` value: `cloud-healthcare`
* **Environment Variables:**

View File

@@ -87,41 +87,28 @@ using a TNS (Transparent Network Substrate) alias.
## Examples
### 1. Basic Connection (Host, Port, and Service Name)
This example demonstrates the four connection methods you could choose from:
```yaml
sources:
my-oracle-source:
kind: oracle
host: 127.0.0.1
port: 1521
serviceName: XEPDB1
user: ${USER_NAME}
password: ${PASSWORD}
```
kind: sources
name: my-oracle-source
type: oracle
### 2. Direct Connection String
# --- Choose one connection method ---
# 1. Host, Port, and Service Name
host: 127.0.0.1
port: 1521
serviceName: XEPDB1
```yaml
sources:
my-oracle-source:
kind: oracle
connectionString: "127.0.0.1:1521/XEPDB1"
user: ${USER_NAME}
password: ${PASSWORD}
```
# 2. Direct Connection String
connectionString: "127.0.0.1:1521/XEPDB1"
### 3. TNS Alias (requires tnsnames.ora)
# 3. TNS Alias (requires tnsnames.ora)
tnsAlias: "MY_DB_ALIAS"
tnsAdmin: "/opt/oracle/network/admin" # Optional: overrides TNS_ADMIN env var
```yaml
sources:
my-oracle-source:
kind: oracle
tnsAlias: "MY_DB_ALIAS"
tnsAdmin: "/opt/oracle/network/admin" # Optional: overrides TNS_ADMIN env var
user: ${USER_NAME}
password: ${PASSWORD}
useOCI: true # tnsAlias requires useOCI to be true
user: ${USER_NAME}
password: ${PASSWORD}
# Optional: Set to true to use the OCI-based driver for advanced features (Requires Oracle Instant Client)
```
@@ -181,4 +168,3 @@ instead of hardcoding your secrets into the configuration file.
| tnsAlias | string | false | A TNS alias from a `tnsnames.ora` file. Use as an alternative to `host`/`port` or `connectionString`. |
| tnsAdmin | string | false | Path to the directory containing the `tnsnames.ora` file. This overrides the `TNS_ADMIN` environment variable if it is set. |
| useOCI | bool | false | If true, uses the OCI-based driver (godror) which supports Oracle Wallet/Kerberos but requires the Oracle Instant Client libraries to be installed. Defaults to false (pure Go driver). |
| walletLocation | string | false | Path to the directory containing the wallet files for the pure Go driver (`useOCI: false`). |

View File

@@ -1,7 +0,0 @@
---
title: "OracleDB"
type: docs
weight: 1
description: >
How to get started with Toolbox using Oracle Database.
---

View File

@@ -47,7 +47,6 @@ var expectedToolSources = []string{
"mysql",
"neo4j",
"oceanbase",
"oracledb",
"postgres",
"serverless-spark",
"singlestore",
@@ -132,8 +131,6 @@ func TestGetPrebuiltTool(t *testing.T) {
neo4jconfig := getOrFatal(t, "neo4j")
healthcare_config := getOrFatal(t, "cloud-healthcare")
snowflake_config := getOrFatal(t, "snowflake")
oracle_config := getOrFatal(t,"oracledb")
if len(alloydb_omni_config) <= 0 {
t.Fatalf("unexpected error: could not fetch alloydb omni prebuilt tools yaml")
}
@@ -233,10 +230,6 @@ func TestGetPrebuiltTool(t *testing.T) {
if len(snowflake_config) <= 0 {
t.Fatalf("unexpected error: could not fetch snowflake prebuilt tools yaml")
}
if len(oracle_config) <= 0 {
t.Fatalf("unexpected error: could not fetch oracle prebuilt tools yaml")
}
}
func TestFailGetPrebuiltTool(t *testing.T) {

View File

@@ -1,121 +0,0 @@
# Copyright 2026 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:
oracle-source:
kind: "oracle"
connectionString: ${ORACLE_CONNECTION_STRING}
walletLocation: ${ORACLE_WALLET:}
user: ${ORACLE_USER}
password: ${ORACLE_PASSWORD}
useOCI: ${ORACLE_USE_OCI:false}
tools:
list_tables:
kind: oracle-sql
source: oracle-source
description: "Lists all user tables in the connected schema, including segment size, row count, and last analyzed date. Filters by a comma-separated list of names. If names are omitted, lists all tables in the current user's schema."
statement: SELECT table_name from user_tables;
list_active_sessions:
kind: oracle-sql
source: oracle-source
description: "List the top N (default 50) currently running database sessions (STATUS='ACTIVE'), showing SID, OS User, Program, and the current SQL statement text."
statement: SELECT
s.sid,
s.serial#,
s.username,
s.osuser,
s.program,
s.status,
s.wait_class,
s.event,
sql.sql_text
FROM
v$session s,
v$sql sql
WHERE
s.status = 'ACTIVE'
AND s.sql_id = sql.sql_id (+)
AND s.audsid != userenv('sessionid') -- Exclude current session
ORDER BY s.last_call_et DESC
FETCH FIRST COALESCE(10) ROWS ONLY;
get_query_plan:
kind: oracle-sql
source: oracle-source
description: "Generate a full execution plan for a single SQL statement. This can be used to analyze query performance without execution. Requires the SQL statement as input. following is an example EXPLAIN PLAN FOR {{&query}};"
statement: SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());
list_top_sql_by_resource:
kind: oracle-sql
source: oracle-source
description: "List the top N SQL statements from the library cache based on a chosen resource metric (CPU, I/O, or Elapsed Time), following is an example of the sql"
statement: SELECT
sql_id,
executions,
buffer_gets,
disk_reads,
cpu_time / 1000000 AS cpu_seconds,
elapsed_time / 1000000 AS elapsed_seconds
FROM
v$sql
FETCH FIRST 5 ROWS ONLY;
list_tablespace_usage:
kind: oracle-sql
source: oracle-source
description: "List tablespace names, total size, free space, and used percentage to monitor storage utilization."
statement: SELECT
t.tablespace_name,
TO_CHAR(t.total_bytes / 1024 / 1024, '99,999.00') AS total_mb,
TO_CHAR(SUM(d.bytes) / 1024 / 1024, '99,999.00') AS free_mb,
TO_CHAR((t.total_bytes - SUM(d.bytes)) / t.total_bytes * 100, '99.00') AS used_pct
FROM
(SELECT tablespace_name, SUM(bytes) AS total_bytes FROM dba_data_files GROUP BY tablespace_name) t,
dba_free_space d
WHERE
t.tablespace_name = d.tablespace_name (+)
GROUP BY
t.tablespace_name, t.total_bytes
ORDER BY
used_pct DESC;
list_invalid_objects:
kind: oracle-sql
source: oracle-source
description: "Lists all database objects that are in an invalid state, requiring recompilation (e.g., procedures, functions, views)."
statement: SELECT
owner,
object_type,
object_name,
status
FROM
dba_objects
WHERE
status = 'INVALID'
AND owner NOT IN ('SYS', 'SYSTEM') -- Exclude system schemas for clarity
ORDER BY
owner, object_type, object_name;
toolsets:
oracle_database_tools:
- execute_sql
- list_tables
- list_active_sessions
- get_query_plan
- list_top_sql_by_resource
- list_tablespace_usage
- list_invalid_objects

View File

@@ -1,5 +1,4 @@
// Copyright © 2025, Oracle and/or its affiliates.
package oracle
import (

View File

@@ -190,4 +190,4 @@ func TestFailParseFromYaml(t *testing.T) {
}
})
}
}
}

View File

@@ -0,0 +1,17 @@
cd server-darwin-arm64
npm pack .
npm publish --access public
cd ../server-darwin-x64
npm pack .
npm publish --access public
cd ../server-linux-x64
npm pack .
npm publish --access public
cd ../server-win32-x64
npm pack .
npm publish --access public
cd ..

View File

@@ -0,0 +1,7 @@
cd server
npm install --package-lock-only
git add package.json package-lock.json
git commit -m "update dep versions"
npm pack .
npm publish --access public

View File

@@ -0,0 +1,6 @@
# @toolbox-sdk/server-darwin-arm64
Platform-specific binary for the `toolbox` package on Darwin arm64.
This package is automatically installed by the main `@toolbox-sdk/server` package and is not intended to be installed directly.
For more information, visit the [toolbox npm package](https://www.npmjs.com/package/@toolbox-sdk/server).

View File

@@ -0,0 +1,19 @@
{
"name": "@toolbox-sdk/server-darwin-arm64",
"version": "0.27.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@toolbox-sdk/server-darwin-arm64",
"version": "0.27.0",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"os": [
"darwin"
]
}
}
}

View File

@@ -0,0 +1,20 @@
{
"name": "@toolbox-sdk/server-darwin-arm64",
"version": "0.27.0",
"license": "Apache-2.0",
"author": "Google LLC",
"os": [
"darwin"
],
"cpu": [
"arm64"
],
"main": "bin/toolbox",
"repository": "googleapis/genai-toolbox",
"scripts": {
"prepack": "node scripts/downloadBinary.js darwin arm64"
},
"files": [
"bin/toolbox"
]
}

View File

@@ -0,0 +1,85 @@
const fs = require('fs');
const path = require('path');
const https = require('https');
const { execSync } = require('child_process');
// 1. Configuration
const PLATFORM_MAP = {
'linux': 'linux',
'darwin': 'darwin',
'win32': 'windows'
};
const ARCH_MAP = {
'x64': 'amd64',
'arm64': 'arm64'
};
const args = process.argv.slice(2);
if (args.length < 2) {
console.error("Usage: node download-binary.js <platform> <arch>");
process.exit(1);
}
const [targetPlatform, targetArch] = args;
// 2. Determine Version
const version = fs.readFileSync(path.join(process.cwd(), 'version.txt'), 'utf8').trim();
// 3. Construct URL
const gcsPlatform = PLATFORM_MAP[targetPlatform];
const gcsArch = ARCH_MAP[targetArch];
if (!gcsPlatform || !gcsArch) {
console.error(`Unsupported platform/arch: ${targetPlatform}/${targetArch}`);
process.exit(1);
}
const extension = targetPlatform === 'win32' ? '.exe' : '';
const binaryName = `toolbox${extension}`;
const url = `https://storage.googleapis.com/genai-toolbox/v${version}/${gcsPlatform}/${gcsArch}/${binaryName}`;
// 4. Prepare Output
const binDir = path.join(process.cwd(), 'bin');
if (!fs.existsSync(binDir)) {
fs.mkdirSync(binDir, { recursive: true });
}
const destPath = path.join(binDir, binaryName);
if (fs.existsSync(destPath)) {
console.log(`[Skipped] Binary already exists at ${destPath}`);
process.exit(0);
}
console.log(`[Prepack] Downloading ${binaryName} for ${targetPlatform}/${targetArch}...`);
console.log(`[Source] ${url}`);
// 5. Download Function
const file = fs.createWriteStream(destPath);
https.get(url, function(response) {
if (response.statusCode !== 200) {
console.error(`❌ Failed to download. Status Code: ${response.statusCode}`);
fs.unlink(destPath, () => {}); // Delete partial file
process.exit(1);
}
response.pipe(file);
file.on('finish', () => {
file.close(() => {
// 6. Make executable (Unix only)
if (targetPlatform !== 'win32') {
try {
execSync(`chmod +x "${destPath}"`);
} catch (err) {
console.warn("⚠️ Could not set executable permissions (chmod failed).");
}
}
console.log(`✅ Success! Binary saved to ${destPath}`);
});
});
}).on('error', function(err) {
fs.unlink(destPath, () => {});
console.error(`❌ Download Error: ${err.message}`);
process.exit(1);
});

View File

@@ -0,0 +1 @@
0.27.0

View File

@@ -0,0 +1,6 @@
# @toolbox-sdk/server-darwin-x64
Platform-specific binary for the `toolbox` package on Darwin x64.
This package is automatically installed by the main `@toolbox-sdk/server` package and is not intended to be installed directly.
For more information, visit the [toolbox npm package](https://www.npmjs.com/package/@toolbox-sdk/server).

View File

@@ -0,0 +1,19 @@
{
"name": "@toolbox-sdk/server-darwin-x64",
"version": "0.27.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@toolbox-sdk/server-darwin-x64",
"version": "0.27.0",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"os": [
"darwin"
]
}
}
}

View File

@@ -0,0 +1,20 @@
{
"name": "@toolbox-sdk/server-darwin-x64",
"version": "0.27.0",
"license": "Apache-2.0",
"author": "Google LLC",
"os": [
"darwin"
],
"cpu": [
"x64"
],
"main": "bin/toolbox",
"repository": "googleapis/genai-toolbox",
"scripts": {
"prepack": "node scripts/downloadBinary.js darwin x64"
},
"files": [
"bin/toolbox"
]
}

View File

@@ -0,0 +1,85 @@
const fs = require('fs');
const path = require('path');
const https = require('https');
const { execSync } = require('child_process');
// 1. Configuration
const PLATFORM_MAP = {
'linux': 'linux',
'darwin': 'darwin',
'win32': 'windows'
};
const ARCH_MAP = {
'x64': 'amd64',
'arm64': 'arm64'
};
const args = process.argv.slice(2);
if (args.length < 2) {
console.error("Usage: node download-binary.js <platform> <arch>");
process.exit(1);
}
const [targetPlatform, targetArch] = args;
// 2. Determine Version
const version = fs.readFileSync(path.join(process.cwd(), 'version.txt'), 'utf8').trim();
// 3. Construct URL
const gcsPlatform = PLATFORM_MAP[targetPlatform];
const gcsArch = ARCH_MAP[targetArch];
if (!gcsPlatform || !gcsArch) {
console.error(`Unsupported platform/arch: ${targetPlatform}/${targetArch}`);
process.exit(1);
}
const extension = targetPlatform === 'win32' ? '.exe' : '';
const binaryName = `toolbox${extension}`;
const url = `https://storage.googleapis.com/genai-toolbox/v${version}/${gcsPlatform}/${gcsArch}/${binaryName}`;
// 4. Prepare Output
const binDir = path.join(process.cwd(), 'bin');
if (!fs.existsSync(binDir)) {
fs.mkdirSync(binDir, { recursive: true });
}
const destPath = path.join(binDir, binaryName);
if (fs.existsSync(destPath)) {
console.log(`[Skipped] Binary already exists at ${destPath}`);
process.exit(0);
}
console.log(`[Prepack] Downloading ${binaryName} for ${targetPlatform}/${targetArch}...`);
console.log(`[Source] ${url}`);
// 5. Download Function
const file = fs.createWriteStream(destPath);
https.get(url, function(response) {
if (response.statusCode !== 200) {
console.error(`❌ Failed to download. Status Code: ${response.statusCode}`);
fs.unlink(destPath, () => {}); // Delete partial file
process.exit(1);
}
response.pipe(file);
file.on('finish', () => {
file.close(() => {
// 6. Make executable (Unix only)
if (targetPlatform !== 'win32') {
try {
execSync(`chmod +x "${destPath}"`);
} catch (err) {
console.warn("⚠️ Could not set executable permissions (chmod failed).");
}
}
console.log(`✅ Success! Binary saved to ${destPath}`);
});
});
}).on('error', function(err) {
fs.unlink(destPath, () => {});
console.error(`❌ Download Error: ${err.message}`);
process.exit(1);
});

View File

@@ -0,0 +1 @@
0.27.0

View File

@@ -0,0 +1,7 @@
# @toolbox-sdk/server-linux-x64
Platform-specific binary for the `toolbox` package on Linux x64.
This package is automatically installed by the main `@toolbox-sdk/server` package and is not intended to be installed directly.
For more information, visit the [toolbox npm package](https://www.npmjs.com/package/@toolbox-sdk/server).

View File

@@ -0,0 +1,19 @@
{
"name": "@toolbox-sdk/server-linux-x64",
"version": "0.27.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@toolbox-sdk/server-linux-x64",
"version": "0.27.0",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"os": [
"linux"
]
}
}
}

View File

@@ -0,0 +1,20 @@
{
"name": "@toolbox-sdk/server-linux-x64",
"version": "0.27.0",
"license": "Apache-2.0",
"author": "Google LLC",
"os": [
"linux"
],
"cpu": [
"x64"
],
"main": "bin/toolbox",
"repository": "googleapis/genai-toolbox",
"scripts": {
"prepack": "node scripts/downloadBinary.js linux x64"
},
"files": [
"bin/toolbox"
]
}

View File

@@ -0,0 +1,85 @@
const fs = require('fs');
const path = require('path');
const https = require('https');
const { execSync } = require('child_process');
// 1. Configuration
const PLATFORM_MAP = {
'linux': 'linux',
'darwin': 'darwin',
'win32': 'windows'
};
const ARCH_MAP = {
'x64': 'amd64',
'arm64': 'arm64'
};
const args = process.argv.slice(2);
if (args.length < 2) {
console.error("Usage: node download-binary.js <platform> <arch>");
process.exit(1);
}
const [targetPlatform, targetArch] = args;
// 2. Determine Version
const version = fs.readFileSync(path.join(process.cwd(), 'version.txt'), 'utf8').trim();
// 3. Construct URL
const gcsPlatform = PLATFORM_MAP[targetPlatform];
const gcsArch = ARCH_MAP[targetArch];
if (!gcsPlatform || !gcsArch) {
console.error(`Unsupported platform/arch: ${targetPlatform}/${targetArch}`);
process.exit(1);
}
const extension = targetPlatform === 'win32' ? '.exe' : '';
const binaryName = `toolbox${extension}`;
const url = `https://storage.googleapis.com/genai-toolbox/v${version}/${gcsPlatform}/${gcsArch}/${binaryName}`;
// 4. Prepare Output
const binDir = path.join(process.cwd(), 'bin');
if (!fs.existsSync(binDir)) {
fs.mkdirSync(binDir, { recursive: true });
}
const destPath = path.join(binDir, binaryName);
if (fs.existsSync(destPath)) {
console.log(`[Skipped] Binary already exists at ${destPath}`);
process.exit(0);
}
console.log(`[Prepack] Downloading ${binaryName} for ${targetPlatform}/${targetArch}...`);
console.log(`[Source] ${url}`);
// 5. Download Function
const file = fs.createWriteStream(destPath);
https.get(url, function(response) {
if (response.statusCode !== 200) {
console.error(`❌ Failed to download. Status Code: ${response.statusCode}`);
fs.unlink(destPath, () => {}); // Delete partial file
process.exit(1);
}
response.pipe(file);
file.on('finish', () => {
file.close(() => {
// 6. Make executable (Unix only)
if (targetPlatform !== 'win32') {
try {
execSync(`chmod +x "${destPath}"`);
} catch (err) {
console.warn("⚠️ Could not set executable permissions (chmod failed).");
}
}
console.log(`✅ Success! Binary saved to ${destPath}`);
});
});
}).on('error', function(err) {
fs.unlink(destPath, () => {});
console.error(`❌ Download Error: ${err.message}`);
process.exit(1);
});

View File

@@ -0,0 +1 @@
0.27.0

View File

@@ -0,0 +1,7 @@
# @toolbox-sdk/server-win32-x64
Platform-specific binary for the `toolbox` package on Windows x64.
This package is automatically installed by the main `@toolbox-sdk/server` package and is not intended to be installed directly.
For more information, visit the [toolbox npm package](https://www.npmjs.com/package/@toolbox-sdk/server).

View File

@@ -0,0 +1,19 @@
{
"name": "@toolbox-sdk/server-win32-x64",
"version": "0.27.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@toolbox-sdk/server-win32-x64",
"version": "0.27.0",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"os": [
"win32"
]
}
}
}

View File

@@ -0,0 +1,20 @@
{
"name": "@toolbox-sdk/server-win32-x64",
"version": "0.27.0",
"license": "Apache-2.0",
"author": "Google LLC",
"os": [
"win32"
],
"cpu": [
"x64"
],
"main": "bin/toolbox.exe",
"repository": "googleapis/genai-toolbox",
"scripts": {
"prepack": "node scripts/downloadBinary.js win32 x64"
},
"files": [
"bin/toolbox.exe"
]
}

View File

@@ -0,0 +1,85 @@
const fs = require('fs');
const path = require('path');
const https = require('https');
const { execSync } = require('child_process');
// 1. Configuration
const PLATFORM_MAP = {
'linux': 'linux',
'darwin': 'darwin',
'win32': 'windows'
};
const ARCH_MAP = {
'x64': 'amd64',
'arm64': 'arm64'
};
const args = process.argv.slice(2);
if (args.length < 2) {
console.error("Usage: node download-binary.js <platform> <arch>");
process.exit(1);
}
const [targetPlatform, targetArch] = args;
// 2. Determine Version
const version = fs.readFileSync(path.join(process.cwd(), 'version.txt'), 'utf8').trim();
// 3. Construct URL
const gcsPlatform = PLATFORM_MAP[targetPlatform];
const gcsArch = ARCH_MAP[targetArch];
if (!gcsPlatform || !gcsArch) {
console.error(`Unsupported platform/arch: ${targetPlatform}/${targetArch}`);
process.exit(1);
}
const extension = targetPlatform === 'win32' ? '.exe' : '';
const binaryName = `toolbox${extension}`;
const url = `https://storage.googleapis.com/genai-toolbox/v${version}/${gcsPlatform}/${gcsArch}/${binaryName}`;
// 4. Prepare Output
const binDir = path.join(process.cwd(), 'bin');
if (!fs.existsSync(binDir)) {
fs.mkdirSync(binDir, { recursive: true });
}
const destPath = path.join(binDir, binaryName);
if (fs.existsSync(destPath)) {
console.log(`[Skipped] Binary already exists at ${destPath}`);
process.exit(0);
}
console.log(`[Prepack] Downloading ${binaryName} for ${targetPlatform}/${targetArch}...`);
console.log(`[Source] ${url}`);
// 5. Download Function
const file = fs.createWriteStream(destPath);
https.get(url, function(response) {
if (response.statusCode !== 200) {
console.error(`❌ Failed to download. Status Code: ${response.statusCode}`);
fs.unlink(destPath, () => {}); // Delete partial file
process.exit(1);
}
response.pipe(file);
file.on('finish', () => {
file.close(() => {
// 6. Make executable (Unix only)
if (targetPlatform !== 'win32') {
try {
execSync(`chmod +x "${destPath}"`);
} catch (err) {
console.warn("⚠️ Could not set executable permissions (chmod failed).");
}
}
console.log(`✅ Success! Binary saved to ${destPath}`);
});
});
}).on('error', function(err) {
fs.unlink(destPath, () => {});
console.error(`❌ Download Error: ${err.message}`);
process.exit(1);
});

View File

@@ -0,0 +1 @@
0.27.0

69
packages/server/README.md Normal file
View File

@@ -0,0 +1,69 @@
# Toolbox
A CLI tool for running a toolbox server.
## Installation
You can install the toolbox globally:
```bash
npm install -g @toolbox-sdk/server
```
Or run it directly using npx:
```bash
npx @toolbox-sdk/server
```
## Configuration
The toolbox requires a `tools.yaml` file in the current working directory to define sources, tools, and prompts.
### Example `tools.yaml`
```yaml
sources:
my-pg-source:
kind: postgres
host: 127.0.0.1
port: 5432
database: toolbox_db
user: postgres
password: password
tools:
search-hotels-by-name:
kind: postgres-sql
source: my-pg-source
description: Search for hotels based on name.
parameters:
- name: name
type: string
description: The name of the hotel.
statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%';
prompts:
code-review:
description: "Asks the LLM to analyze code quality and suggest improvements."
messages:
- role: "user"
content: "Please review the following code for quality, correctness, and potential improvements: \n\n{{.code}}"
arguments:
- name: "code"
description: "The code to review"
required: true
```
To learn more on how to configure your toolbox, visit the [official docsite](https://googleapis.github.io/genai-toolbox/getting-started/configure/).
## Platform Support
The toolbox automatically handles platform-specific binaries. Supported platforms include:
- macOS (arm64, x64)
- Linux (x64)
- Windows (x64)
## Resources
For more information, visit the
- [MCP Toolbox repository](https://github.com/googleapis/genai-toolbox)
- [Official Documentation](https://googleapis.github.io/genai-toolbox/getting-started/introduction/)

49
packages/server/bin/run.js Executable file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/env node
const { spawn } = require('child_process');
const path = require('path');
const os = require('os');
const fs = require('fs');
const PLATFORMS = {
'darwin-arm64': '@toolbox-sdk/server-darwin-arm64',
'darwin-x64': '@toolbox-sdk/server-darwin-x64',
'linux-x64': '@toolbox-sdk/server-linux-x64',
'win32-x64': '@toolbox-sdk/server-win32-x64'
};
const currentKey = `${os.platform()}-${os.arch()}`;
const pkgName = PLATFORMS[currentKey];
if (!pkgName) {
console.error(`Unsupported platform: ${currentKey}`);
process.exit(1);
}
let binPath;
try {
const pkgJsonPath = require.resolve(`${pkgName}/package.json`);
const pkgDir = path.dirname(pkgJsonPath);
const binName = os.platform() === 'win32' ? 'toolbox.exe' : 'toolbox';
binPath = path.join(pkgDir, 'bin', binName);
} catch (e) {
console.error(`Binary for ${currentKey} not found. Installation failed?`);
process.exit(1);
}
if (os.platform() !== 'win32') {
try {
fs.chmodSync(binPath, 0o755);
if (os.platform() === 'darwin') {
const { execSync } = require('child_process');
try {
execSync(`xattr -d com.apple.quarantine "${binPath}"`, { stdio: 'ignore' });
} catch (e) {
}
}
} catch (e) {
console.warn(`Could not set execute permissions on ${binPath}: ${e.message}`);
}
}
spawn(binPath, process.argv.slice(2), { stdio: 'inherit' })
.on('exit', process.exit);

74
packages/server/package-lock.json generated Normal file
View File

@@ -0,0 +1,74 @@
{
"name": "@toolbox-sdk/server",
"version": "0.27.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@toolbox-sdk/server",
"version": "0.27.0",
"license": "Apache-2.0",
"bin": {
"toolbox": "bin/run.js"
},
"optionalDependencies": {
"@toolbox-sdk/server-darwin-arm64": "0.27.0",
"@toolbox-sdk/server-darwin-x64": "0.27.0",
"@toolbox-sdk/server-linux-x64": "0.27.0",
"@toolbox-sdk/server-win32-x64": "0.27.0"
}
},
"node_modules/@toolbox-sdk/server-darwin-arm64": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/@toolbox-sdk/server-darwin-arm64/-/server-darwin-arm64-0.27.0.tgz",
"integrity": "sha512-qGP7t4JCS9TgQTySA7WnFbrebc9CgZNfQUdlmHdCVw1ZbH+xE5eABalLkeMvDJUmevpTy51G3osxRyh3eVDCnQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@toolbox-sdk/server-darwin-x64": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/@toolbox-sdk/server-darwin-x64/-/server-darwin-x64-0.27.0.tgz",
"integrity": "sha512-ZdHHSbJRt4YmKteuFXRQzixpzHz3q5xqQFv1KUQlLDpjIw8duOTFoA22EZtDssSh74oxVlU/X5yWPT9ED59W2g==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@toolbox-sdk/server-linux-x64": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/@toolbox-sdk/server-linux-x64/-/server-linux-x64-0.27.0.tgz",
"integrity": "sha512-XJoUBIFoi02KQuiv7X8XP/eZAigk3sPnfBCtQVZ8zIl5NdbxGKyIYMUj0I8aYwpSk/8pAzow4YqryiIWeMP9aA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@toolbox-sdk/server-win32-x64": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/@toolbox-sdk/server-win32-x64/-/server-win32-x64-0.27.0.tgz",
"integrity": "sha512-xedHjbIRtpxn/x64D8Us8APEGuiXTqABWsQfubcDr4KOD+pnH1vyBZbiCgXRFIEKAeUSYVEMgDPxwUTV6TOlKg==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
]
}
}
}

View File

@@ -0,0 +1,19 @@
{
"name": "@toolbox-sdk/server",
"version": "0.27.0",
"license": "Apache-2.0",
"author": "Google LLC",
"bin": {
"toolbox": "./bin/run.js"
},
"files": [
"bin/run.js"
],
"repository": "googleapis/genai-toolbox",
"optionalDependencies": {
"@toolbox-sdk/server-darwin-arm64": "0.27.0",
"@toolbox-sdk/server-darwin-x64": "0.27.0",
"@toolbox-sdk/server-linux-x64": "0.27.0",
"@toolbox-sdk/server-win32-x64": "0.27.0"
}
}

91
packages/testing.md Normal file
View File

@@ -0,0 +1,91 @@
# How to test on different platforms
1. Create a local test registry. We are using Verdaccio. During the actual process, we publish to npm instead.
```sh
# install
npm install -g verdaccio
# start server
verdaccio
```
The output will show the config file location and the URL. Open your browser to:
http://localhost:4873
> Note: You can use `npm unpublish @toolbox-sdk/server --force --registry http://localhost:4873` to unpublish the package.
2. Pack all 4 packages and publish them to the local registry. Go in each package (eg. server-darwin-arm64) and run
```sh
npm ci --force
npm pack .
```
Then publish to the local registry
```sh
npm publish --registry http://localhost:4873
```
3. Go to the server package and run
```sh
npm ci --force
npm pack .
npm publish --registry http://localhost:4873
```
Now, you have published your package.
4. Now create a new folder (let's call it testing.) Add a tools.yaml file to the folder. It should look like this:
```yaml
sources:
my-pg-source:
kind: postgres
host: 127.0.0.1
port: 5432
database: toolbox_db
user: postgres
password: password
tools:
search-hotels-by-name:
kind: postgres-sql
source: my-pg-source
description: Search for hotels based on name.
parameters:
- name: name
type: string
description: The name of the hotel.
statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%';
prompts:
code-review:
description: "Asks the LLM to analyze code quality and suggest improvements."
messages:
- role: "user"
content: "Please review the following code for quality, correctness, and potential improvements: \n\n{{.code}}"
arguments:
- name: "code"
description: "The code to review"
required: true
```
Note: Do not test this directly to the server folder. The registry might pick up local packages instead of global installation.
Use a separate testing folder outside the server folder for this testing.
6. From the testing folder, run
```sh
npx --registry=http://localhost:4873/ -y @toolbox-sdk/server
```
This should start up the toolbox server with the tools.yaml file.
7. Run the command to verify that the tools are available:
```sh
curl --location 'http://127.0.0.1:5000/mcp' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "tools/list",
"params": {},
"id": 1
}'
```

23
packages/update_dep_packages.sh Executable file
View File

@@ -0,0 +1,23 @@
cd server-darwin-arm64
npm install --force
rm -rf bin/
git add version.txt package.json package-lock.json
cd ../server-darwin-x64
npm install --force
rm -rf bin/
git add version.txt package.json package-lock.json
cd ../server-linux-x64
npm install --force
rm -rf bin/
git add version.txt package.json package-lock.json
cd ../server-win32-x64
npm install --force
rm -rf bin/
git add version.txt package.json package-lock.json
cd ..

View File

@@ -9,31 +9,23 @@ import (
"os"
"regexp"
"strings"
"strconv"
"testing"
"time"
"github.com/google/uuid"
"github.com/googleapis/genai-toolbox/internal/sources/oracle"
"github.com/googleapis/genai-toolbox/internal/testutils"
"github.com/googleapis/genai-toolbox/tests"
)
var (
OracleSourceType = "oracle"
OracleToolType = "oracle-sql"
OracleHost = os.Getenv("ORACLE_HOST")
OraclePort = os.Getenv("ORACLE_PORT")
OracleUser = os.Getenv("ORACLE_USER")
OraclePass = os.Getenv("ORACLE_PASS")
OracleServerName = os.Getenv("ORACLE_SERVER_NAME")
OracleUseOCI = os.Getenv("ORACLE_USE_OCI")
OracleWalletLocation = os.Getenv("ORACLE_WALLET_LOCATION")
OracleTnsAdmin = os.Getenv("ORACLE_TNS_ADMIN")
OracleConnStr = fmt.Sprintf(
"%s:%s/%s", OracleHost, "1521", OracleServerName) // Default port 1521??
"%s:%s/%s", OracleHost, "1521", OracleServerName)
)
func getOracleVars(t *testing.T) map[string]any {
@@ -51,77 +43,12 @@ func getOracleVars(t *testing.T) map[string]any {
return map[string]any{
"type": OracleSourceType,
"connectionString": OracleConnStr,
"useOCI": OracleUseOCI,
"walletLocation": OracleWalletLocation,
"tnsAdmin": OracleTnsAdmin,
"host": OracleHost,
"port": OraclePort,
"service": OracleServerName,
"useOCI": true,
"user": OracleUser,
"password": OraclePass,
}
}
// getOracleConfigFromEnv constructs an oracle.Config from environment variables.
func getOracleConfigFromEnv(t *testing.T) oracle.Config {
t.Helper()
vars := getOracleVars(t)
port, err := strconv.Atoi(vars["port"].(string))
if err != nil && vars["port"].(string) != "" {
t.Fatalf("invalid ORACLE_PORT: %v", err)
}
useOCI, err := strconv.ParseBool(vars["useOCI"].(string))
if err != nil && vars["useOCI"].(string) != "" {
useOCI = false
}
return oracle.Config{
Name: "test-oracle-instance",
Kind: vars["type"].(string),
User: vars["user"].(string),
Password: vars["password"].(string),
Host: vars["host"].(string),
Port: port,
ServiceName: vars["service"].(string),
WalletLocation: vars["walletLocation"].(string),
TnsAdmin: vars["tnsAdmin"].(string),
UseOCI: useOCI,
}
}
// setOracleEnv sets Oracle-related environment variables for testing and returns a cleanup function.
func setOracleEnv(t *testing.T, host, user, password, service, port, connStr, tnsAlias, tnsAdmin, walletLocation string, useOCI bool) func() {
t.Helper()
original := map[string]string{
"ORACLE_HOST": os.Getenv("ORACLE_HOST"),
"ORACLE_USER": os.Getenv("ORACLE_USER"),
"ORACLE_PASSWORD": os.Getenv("ORACLE_PASSWORD"),
"ORACLE_SERVICE": os.Getenv("ORACLE_SERVICE"),
"ORACLE_PORT": os.Getenv("ORACLE_PORT"),
"ORACLE_TNS_ADMIN": os.Getenv("ORACLE_TNS_ADMIN"),
"ORACLE_WALLET_LOCATION": os.Getenv("ORACLE_WALLET_LOCATION"),
"ORACLE_USE_OCI": os.Getenv("ORACLE_USE_OCI"),
}
os.Setenv("ORACLE_HOST", host)
os.Setenv("ORACLE_USER", user)
os.Setenv("ORACLE_PASSWORD", password)
os.Setenv("ORACLE_SERVICE", service)
os.Setenv("ORACLE_PORT", port)
os.Setenv("ORACLE_TNS_ADMIN", tnsAdmin)
os.Setenv("ORACLE_WALLET_LOCATION", walletLocation)
os.Setenv("ORACLE_USE_OCI", fmt.Sprintf("%v", useOCI))
return func() {
for k, v := range original {
os.Setenv(k, v)
}
}
}
// Copied over from oracle.go
func initOracleConnection(ctx context.Context, user, pass, connStr string) (*sql.DB, error) {
// Build the full Oracle connection string for godror driver
@@ -141,9 +68,7 @@ func initOracleConnection(ctx context.Context, user, pass, connStr string) (*sql
return db, nil
}
// TestOracleSimpleToolEndpoints tests Oracle SQL tool endpoints
func TestOracleSimpleToolEndpoints(t *testing.T) {
sourceConfig := getOracleVars(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
@@ -210,130 +135,6 @@ func TestOracleSimpleToolEndpoints(t *testing.T) {
tests.RunToolInvokeWithTemplateParameters(t, tableNameTemplateParam)
}
// TestOracleConnectionPureGoWithWallet tests pure Go driver connection with wallet
func TestOracleConnectionPureGoWithWallet(t *testing.T) {
t.Parallel()
// This test expects the connection to fail because the wallet file won't exist.
// It verifies that the walletLocation parameter is correctly passed to the pure Go driver.
// Save original env vars and restore them at the end
cleanup := setOracleEnv(t,
OracleHost, OracleUser, OraclePass, OracleServerName, OraclePort, // Use existing base connection details
"", // connectionString
"", // tnsAlias
"", // tnsAdmin
"/tmp/nonexistent_wallet", // walletLocation
false, // useOCI
)
defer cleanup()
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
cfg := getOracleConfigFromEnv(t)
_, err := cfg.Initialize(ctx, nil) // Pass nil for tracer as it's not critical for this test
if err == nil {
t.Fatalf("Expected connection to fail with non-existent wallet, but it succeeded")
}
// Check for error message indicating wallet usage or connection failure related to wallet
// The exact error message might vary depending on the go-ora version and OS.
// We are looking for an error that suggests the wallet path was attempted.
expectedErrorSubstring := "wallet"
if !strings.Contains(strings.ToLower(err.Error()), expectedErrorSubstring) {
t.Errorf("Expected error message to contain '%s' (case-insensitive) but got: %v", expectedErrorSubstring, err)
}
t.Logf("Connection failed as expected (Pure Go with Wallet): %v", err)
}
// TestOracleConnectionOCI tests OCI driver connection without wallet
func TestOracleConnectionOCI(t *testing.T) {
t.Parallel()
// This test verifies that the useOCI=true parameter is correctly passed to the OCI driver.
// It will likely fail if Oracle Instant Client is not installed or configured.
// Save original env vars and restore them at the end
cleanup := setOracleEnv(t,
OracleHost, OracleUser, OraclePass, OracleServerName, OraclePort, // Use existing base connection details
"", // connectionString
"", // tnsAlias
"", // tnsAdmin
"", // walletLocation
true, // useOCI
)
defer cleanup()
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
cfg := getOracleConfigFromEnv(t)
_, err := cfg.Initialize(ctx, nil)
if err == nil {
t.Fatalf("Expected connection to fail (OCI driver without Instant Client), but it succeeded")
}
// Check for error message indicating OCI driver usage or connection failure related to OCI.
// Common errors include "OCI environment not initialized", "driver: bad connection", etc.
expectedErrorSubstrings := []string{"oci", "driver", "connection"}
foundExpectedError := false
for _, sub := range expectedErrorSubstrings {
if strings.Contains(strings.ToLower(err.Error()), sub) {
foundExpectedError = true
break
}
}
if !foundExpectedError {
t.Errorf("Expected error message to contain one of %v (case-insensitive) but got: %v", expectedErrorSubstrings, err)
}
t.Logf("Connection failed as expected (OCI Driver): %v", err)
}
// TestOracleConnectionOCIWithWallet tests OCI driver connection with TNS Admin and Wallet
func TestOracleConnectionOCIWithWallet(t *testing.T) {
t.Parallel()
// This test verifies that useOCI=true and tnsAdmin parameters are correctly passed for OCI wallet.
// It will likely fail due to missing tnsnames.ora and wallet files.
// Save original env vars and restore them at the end
cleanup := setOracleEnv(t,
"", OracleUser, OraclePass, "", "", // Unset host/port/service for TNS alias, but keep user/pass
"", // connectionString
"MY_TNS_ALIAS", // tnsAlias
"/tmp/nonexistent_tns_admin", // tnsAdmin
"", // walletLocation
true, // useOCI
)
defer cleanup()
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
cfg := getOracleConfigFromEnv(t)
_, err := cfg.Initialize(ctx, nil)
if err == nil {
t.Fatalf("Expected connection to fail (OCI driver with TNS Admin/Wallet), but it succeeded")
}
// Check for error message indicating TNS Admin/Wallet usage or connection failure.
expectedErrorSubstrings := []string{"tns", "wallet", "oci", "driver", "connection"}
foundExpectedError := false
for _, sub := range expectedErrorSubstrings {
if strings.Contains(strings.ToLower(err.Error()), sub) {
foundExpectedError = true
break
}
}
if !foundExpectedError {
t.Errorf("Expected error message to contain one of %v (case-insensitive) but got: %v", expectedErrorSubstrings, err)
}
t.Logf("Connection failed as expected (OCI Driver with TNS Admin/Wallet): %v", err)
}
//test utils
func setupOracleTable(t *testing.T, ctx context.Context, pool *sql.DB, createStatement, insertStatement, tableName string, params []any) func(*testing.T) {
err := pool.PingContext(ctx)
if err != nil {
@@ -440,4 +241,4 @@ func dropAllUserTables(t *testing.T, ctx context.Context, db *sql.DB) {
t.Logf("failed to drop table %s: %v", tableName, err)
}
}
}
}

View File

@@ -1,248 +0,0 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package oracle_test
import (
"strings"
"testing"
yaml "github.com/goccy/go-yaml"
"github.com/google/go-cmp/cmp"
"github.com/googleapis/genai-toolbox/internal/server"
"github.com/googleapis/genai-toolbox/internal/sources/oracle"
"github.com/googleapis/genai-toolbox/internal/testutils"
)
func TestParseFromYamlOracle(t *testing.T) {
tcs := []struct {
desc string
in string
want server.SourceConfigs
}{
{
desc: "connection string and useOCI=true",
in: `
sources:
my-oracle-cs:
kind: oracle
connectionString: "my-host:1521/XEPDB1"
user: my_user
password: my_pass
useOCI: true
`,
want: server.SourceConfigs{
"my-oracle-cs": oracle.Config{
Name: "my-oracle-cs",
Kind: oracle.SourceKind,
ConnectionString: "my-host:1521/XEPDB1",
User: "my_user",
Password: "my_pass",
UseOCI: true,
},
},
},
{
desc: "host/port/serviceName and default useOCI=false",
in: `
sources:
my-oracle-host:
kind: oracle
host: my-host
port: 1521
serviceName: ORCLPDB
user: my_user
password: my_pass
`,
want: server.SourceConfigs{
"my-oracle-host": oracle.Config{
Name: "my-oracle-host",
Kind: oracle.SourceKind,
Host: "my-host",
Port: 1521,
ServiceName: "ORCLPDB",
User: "my_user",
Password: "my_pass",
UseOCI: false,
},
},
},
{
desc: "tnsAlias and TnsAdmin specified with explicit useOCI=true",
in: `
sources:
my-oracle-tns-oci:
kind: oracle
tnsAlias: FINANCE_DB
tnsAdmin: /opt/oracle/network/admin
user: my_user
password: my_pass
useOCI: true
`,
want: server.SourceConfigs{
"my-oracle-tns-oci": oracle.Config{
Name: "my-oracle-tns-oci",
Kind: oracle.SourceKind,
TnsAlias: "FINANCE_DB",
TnsAdmin: "/opt/oracle/network/admin",
User: "my_user",
Password: "my_pass",
UseOCI: true,
},
},
},
{
desc: "connection string and walletLocation",
in: `
sources:
my-oracle-wallet:
kind: oracle
connectionString: "my-host:1521/XEPDB1"
user: my_user
password: my_pass
walletLocation: "/path/to/wallet"
`,
want: server.SourceConfigs{
"my-oracle-wallet": oracle.Config{
Name: "my-oracle-wallet",
Kind: oracle.SourceKind,
ConnectionString: "my-host:1521/XEPDB1",
User: "my_user",
Password: "my_pass",
WalletLocation: "/path/to/wallet",
},
},
},
}
for _, tc := range tcs {
t.Run(tc.desc, func(t *testing.T) {
got := struct {
Sources server.SourceConfigs `yaml:"sources"`
}{}
err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got)
if err != nil {
t.Fatalf("unable to unmarshal: %s", err)
}
if !cmp.Equal(tc.want, got.Sources) {
t.Fatalf("incorrect parse:\nwant: %v\ngot: %v\ndiff: %s", tc.want, got.Sources, cmp.Diff(tc.want, got.Sources))
}
})
}
}
func TestFailParseFromYamlOracle(t *testing.T) {
tcs := []struct {
desc string
in string
err string
}{
{
desc: "extra field",
in: `
sources:
my-oracle-instance:
kind: oracle
host: my-host
serviceName: ORCL
user: my_user
password: my_pass
extraField: value
`,
err: "unable to parse source \"my-oracle-instance\" as \"oracle\": [1:1] unknown field \"extraField\"\n> 1 | extraField: value\n ^\n 2 | host: my-host\n 3 | kind: oracle\n 4 | password: my_pass\n 5 | ",
},
{
desc: "missing required password field",
in: `
sources:
my-oracle-instance:
kind: oracle
host: my-host
serviceName: ORCL
user: my_user
`,
err: "unable to parse source \"my-oracle-instance\" as \"oracle\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag",
},
{
desc: "missing connection method fields (validate fails)",
in: `
sources:
my-oracle-instance:
kind: oracle
user: my_user
password: my_pass
`,
err: "unable to parse source \"my-oracle-instance\" as \"oracle\": invalid Oracle configuration: must provide one of: 'tns_alias', 'connection_string', or both 'host' and 'service_name'",
},
{
desc: "multiple connection methods provided (validate fails)",
in: `
sources:
my-oracle-instance:
kind: oracle
host: my-host
serviceName: ORCL
connectionString: "my-host:1521/XEPDB1"
user: my_user
password: my_pass
`,
err: "unable to parse source \"my-oracle-instance\" as \"oracle\": invalid Oracle configuration: provide only one connection method: 'tns_alias', 'connection_string', or 'host'+'service_name'",
},
{
desc: "fail on tnsAdmin with useOCI=false",
in: `
sources:
my-oracle-fail:
kind: oracle
tnsAlias: FINANCE_DB
tnsAdmin: /opt/oracle/network/admin
user: my_user
password: my_pass
useOCI: false
`,
err: "unable to parse source \"my-oracle-fail\" as \"oracle\": invalid Oracle configuration: `tnsAdmin` can only be used when `UseOCI` is true, or use `walletLocation` instead",
},
{
desc: "fail on walletLocation with useOCI=true",
in: `
sources:
my-oracle-fail:
kind: oracle
connectionString: "my-host:1521/XEPDB1"
user: my_user
password: my_pass
walletLocation: "/path/to/wallet"
useOCI: true
`,
err: "unable to parse source \"my-oracle-fail\" as \"oracle\": invalid Oracle configuration: when using an OCI driver, use `tnsAdmin` to specify credentials file location instead",
},
}
for _, tc := range tcs {
t.Run(tc.desc, func(t *testing.T) {
got := struct {
Sources server.SourceConfigs `yaml:"sources"`
}{}
err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got)
if err == nil {
t.Fatalf("expect parsing to fail")
}
errStr := strings.ReplaceAll(err.Error(), "\r", "")
if errStr != tc.err {
t.Fatalf("unexpected error:\ngot:\n%q\nwant:\n%q\n", errStr, tc.err)
}
})
}
}