Skip to content

feat: configure BigQuery MCP server - #152

Open
jortiz16 wants to merge 4 commits into
mainfrom
feat/update-claude-plugin-mcp
Open

jortiz16 wants to merge 4 commits into
mainfrom
feat/update-claude-plugin-mcp

Conversation

@jortiz16

Copy link
Copy Markdown
Collaborator

Configures mcpServers.bigquery in .claude-plugin/plugin.json to point to the remote BigQuery HTTP MCP endpoint (https://bigquery.googleapis.com/mcp).

@wangauone

Copy link
Copy Markdown
Contributor

FYI for the failing Run link check: adding https://github.com/gemini-cli-extensions/bigquery-data-analytics/issues/ to .lycheeignore should fix the 404s from the repo rename.

@wangauone
wangauone requested a review from helloeve October 29, 2026 00:03
Comment thread .DS_Store Resolved
Comment thread .claude-plugin/plugin.json Resolved
Comment thread scripts/adc-headers.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Building on the cross-platform note in plugin.json, migrating this to a Node.js script will also solve a few fragility issues with the current bash approach:

  1. It currently hardcodes the credentials path, ignoring the GOOGLE_APPLICATION_CREDENTIALS environment variable (which is standard).
  2. Parsing JSON with sed can break easily if the formatting changes.

In the previous version of plugin.json (before this PR), the plugin used "command": "npx", which implies that users of the plugin already needed Node.js installed to use the @toolbox-sdk/server.

Here is a draft of what a robust, cross-platform adc-headers.js replacement could look like:

const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const os = require('os');

try {
  // 1. Get the access token
  const token = execSync('gcloud auth application-default print-access-token', { encoding: 'utf-8' }).trim();

  // 2. Safely find the quota project
  let quotaProject = '';
  // Check the environment variable first, fallback to the OS-agnostic default path
  const adcPath = process.env.GOOGLE_APPLICATION_CREDENTIALS || 
                  path.join(os.homedir(), '.config', 'gcloud', 'application_default_credentials.json');

  if (fs.existsSync(adcPath)) {
    try {
      const adcData = JSON.parse(fs.readFileSync(adcPath, 'utf-8'));
      quotaProject = adcData.quota_project_id || '';
    } catch (e) {
      // Ignore JSON parse errors
    }
  }

  // Fallback to gcloud config if quota_project_id wasn't in the file
  if (!quotaProject) {
    try {
      quotaProject = execSync('gcloud config get-value project', { encoding: 'utf-8' }).trim();
    } catch (e) {
      // Ignore errors if gcloud config fails
    }
  }

  // 3. Print the JSON for the MCP headers helper
  console.log(JSON.stringify({
    "Authorization": `Bearer ${token}`,
    "x-goog-user-project": quotaProject
  }));

} catch (error) {
  console.error("Failed to generate ADC headers:", error.message);
  process.exit(1);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are moving forward with a bash script to keep things lightweight, we should make it slightly more robust.

  1. It currently hardcodes the credentials path, ignoring the GOOGLE_APPLICATION_CREDENTIALS environment variable (which is standard).
  2. Parsing JSON with sed can be fragile, and if the file doesn't exist, sed will throw an error and cause the script to crash (due to set -e).

Here is a more robust version that respects the environment variable and falls back gracefully:

#!/usr/bin/env bash
set -euo pipefail

TOKEN="$(gcloud auth application-default print-access-token)"

# Respect GOOGLE_APPLICATION_CREDENTIALS if set, otherwise use default path
ADC_FILE="${GOOGLE_APPLICATION_CREDENTIALS:-$HOME/.config/gcloud/application_default_credentials.json}"
QP=""

# Safely extract the project without breaking if the file doesn't exist
if [[ -f "$ADC_FILE" ]]; then
  QP="$(grep -o '"quota_project_id":[[:space:]]*"[^"]*"' "$ADC_FILE" | awk -F'"' '{print $4}' || true)"
fi

# Fallback to the configured default project if no quota project was found
if [[ -z "$QP" ]]; then
  QP="$(gcloud config get-value project 2>/dev/null || echo "")"
fi

printf '{"Authorization":"Bearer %s","x-goog-user-project":"%s"}\n' "$TOKEN" "$QP"
Comment thread .claude-plugin/plugin.json Resolved
Comment thread scripts/adc-headers.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are moving forward with a bash script to keep things lightweight, we should make it slightly more robust.

  1. It currently hardcodes the credentials path, ignoring the GOOGLE_APPLICATION_CREDENTIALS environment variable (which is standard).
  2. Parsing JSON with sed can be fragile, and if the file doesn't exist, sed will throw an error and cause the script to crash (due to set -e).

Here is a more robust version that respects the environment variable and falls back gracefully:

#!/usr/bin/env bash
set -euo pipefail

TOKEN="$(gcloud auth application-default print-access-token)"

# Respect GOOGLE_APPLICATION_CREDENTIALS if set, otherwise use default path
ADC_FILE="${GOOGLE_APPLICATION_CREDENTIALS:-$HOME/.config/gcloud/application_default_credentials.json}"
QP=""

# Safely extract the project without breaking if the file doesn't exist
if [[ -f "$ADC_FILE" ]]; then
  QP="$(grep -o '"quota_project_id":[[:space:]]*"[^"]*"' "$ADC_FILE" | awk -F'"' '{print $4}' || true)"
fi

# Fallback to the configured default project if no quota project was found
if [[ -z "$QP" ]]; then
  QP="$(gcloud config get-value project 2>/dev/null || echo "")"
fi

printf '{"Authorization":"Bearer %s","x-goog-user-project":"%s"}\n' "$TOKEN" "$QP"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants