DEV Community

Cover image for Building an AI-Native Data Interface with Google ADK, MCP, and BigQuery

Building an AI-Native Data Interface with Google ADK, MCP, and BigQuery

Introduction

For many years, enterprise data interaction has followed a predictable pattern. Engineers write SQL, teams build dashboards, and organizations rely on BI tools to understand system behavior, business performance, and costs. While these approaches remain useful, they are increasingly insufficient in modern cloud environments where scale, velocity, and operational complexity demand faster, more intelligent decision-making.

From an SRE, platform engineering, and FinOps perspective, the challenge is no longer just accessing data. The challenge is enabling safe, governed, and intelligent interaction with data that supports reliability, cost optimization, and continuous cloud transformation.

To address this, I tried a fully working proof of concept (PoC) using Google ADK, Model Context Protocol (MCP), and BigQuery, strictly based on Google’s official documentation and extended with production-grade engineering considerations. This was not a conceptual exercise or a demo-only prototype. The system runs end-to-end and reflects architectural patterns suitable for real enterprise platforms.

In this article, I describe what I built, why this architecture matters for modern cloud organizations, and how Google ADK and MCP fundamentally change how AI systems can support SRE, platform, and FinOps workflows at scale.

What This PoC Is Really About

At its core, this PoC explores a simple but powerful idea:
What if AI agents interacted with enterprise data the same way production-grade cloud systems are expected to?

Rather than embedding SQL logic into prompts or granting broad database access, this PoC demonstrates how an AI agent can:

  • Reason about operational, financial, or analytical questions
  • Discover approved tools dynamically
  • Access BigQuery through a governed, auditable interface
  • Receive structured results suitable for reliable downstream reasoning

The agent never improvises data access. Every interaction is explicit, policy-aligned, and traceable, which is essential in SRE- and FinOps-driven environments.

Why This Problem Is Worth Solving

Many AI + data examples appear impressive but fail under real operational constraints. Common issues include hardcoded SQL in prompts, excessive permissions, and no separation between reasoning logic and execution logic.

From an SRE and platform engineering standpoint, these patterns introduce unacceptable risk. From a FinOps standpoint, they obscure cost attribution, accountability, and governance.

This PoC takes a different approach. Data access is treated as a platform capability, not a prompt-level shortcut. This distinction is critical for organizations focused on reliability, security, cost efficiency, and sustainable cloud transformation.

A Quick Introduction to Google ADK

Google ADK (Agent Development Kit) provides a structured framework for building agentic systems that align well with cloud-native engineering principles. Instead of focusing solely on prompts, ADK formalizes agents, tools, reasoning loops, and context boundaries.

For senior engineers and platform architects, ADK feels intuitive. It mirrors how reliable systems are designed: with explicit contracts, modular components, and controlled execution paths. You are not instructing a model to respond once; you are defining how it reasons, when it acts, and what platform capabilities it may invoke.

This makes ADK particularly relevant for production systems supporting SRE automation, FinOps analysis, and large-scale cloud operations.

Understanding MCP (Model Context Protocol)

MCP is a critical architectural component of this solution.

Rather than allowing AI models to directly manipulate external systems, MCP introduces a formal protocol for tool-based interaction. Tools expose schemas, models discover capabilities, and all inputs and outputs are structured and validated.

In practice, the model does not need to understand BigQuery's internals. It only needs to understand the operational contract defined by the MCP tool.

This design closely aligns with platform engineering best practices and enables AI systems to operate within the same governance boundaries as other production services.

MCP and BigQuery: Why This Combination Matters

Google’s official MCP support for BigQuery is especially impactful because BigQuery is often the system of record for analytics, operational metrics, and cost data.

By exposing BigQuery through MCP:

  • Access can be tightly scoped and governed
  • Queries are executed only through approved interfaces
  • Permissions remain centralized and auditable

The AI agent never becomes a privileged database user. Instead, it behaves as a controlled platform consumer, consistent with how SRE and FinOps systems are expected to operate.

High-Level Architecture

At a high level, the PoC architecture looks like this:

AI Agent (Google ADK)
        |
        |  Structured MCP tool calls
        v
MCP Server (BigQuery)
        |
        v
BigQuery datasets
Enter fullscreen mode Exit fullscreen mode

The most important takeaway here is the separation of concerns.

  • Reasoning happens in the agent.
  • Execution happens in BigQuery.
  • MCP sits cleanly in between.

How you can try this PoC in your local env

Local Config Setup

#clone my github repo:
git clone https://github.com/karthidec/google-adk-mcp-bigquery.git

#authenticate with google cloud
gcloud config set project [YOUR-PROJECT-ID]
gcloud auth application-default login

#enable bigquery mcp server in your google project
gcloud beta services mcp enable bigquery.googleapis.com --project=PROJECT_ID

# Create virtual environment
python3 -m venv .venv

# Activate virtual environment
source .venv/bin/activate

# Install ADK
pip install google-adk

# Navigate to the app directory
cd bq_mcp/

# Run the ADK web interface
adk web
Enter fullscreen mode Exit fullscreen mode

Defining the Agent

The agent is created using Google ADK primitives. It includes a reasoning loop and the ability to discover and invoke MCP tools.

import os
import dotenv
from pathlib import Path
from . import tools
from google.adk.agents import Agent

# Load environment variables relative to this file
dotenv.load_dotenv(Path(__file__).parent / ".env")

PROJECT_ID = os.getenv('GOOGLE_CLOUD_PROJECT', 'project_not_set')

# Initialize the toolset
bigquery_toolset = tools.get_bigquery_mcp_toolset()

# Define the Agent
root_agent = Agent(
    model='gemini-2.5-flash', # Leveraging a fast, reasoning-capable model
    name='root_agent',
    instruction=f"""
                Help the user answer questions by strategically combining insights from two sources:

                1.  **BigQuery toolset:** Access demographic (inc. foot traffic index), 
                    product pricing, and historical sales data in the mcp_bakery dataset. 
                    Do not use any other dataset.

                Run all query jobs from project id: {PROJECT_ID}. 
                Give list of zipcodes or any general query user wants to know. 
            """,
    tools=[bigquery_toolset]
)
Enter fullscreen mode Exit fullscreen mode

This structure makes the agent predictable and easier to extend over time.

Registering BigQuery as an MCP Tool

Next, BigQuery is exposed through an MCP server. The server defines exactly what operations are available and how requests should be shaped.

import os
import dotenv
import google.auth
import google.auth.transport.requests
from pathlib import Path
from typing import Dict, Optional, Any

# We use Any here to avoid strict dependency issues if ADK isn't fully typed in your env
try:
    from google.adk.agents.readonly_context import ReadonlyContext
except ImportError:
    ReadonlyContext = Any

from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams

# Robustly load .env from the script's directory
dotenv.load_dotenv(Path(__file__).parent / ".env")

BIGQUERY_MCP_URL = "https://bigquery.googleapis.com/mcp"

def get_auth_headers() -> Dict[str, str]:
    """
    Generates fresh authentication headers. 
    Crucial for long-running agents where tokens might expire.
    """
    credentials, project_id = google.auth.default(
        scopes=["https://www.googleapis.com/auth/bigquery"]
    )

    # Fallback if default auth doesn't pick up the project ID
    if not project_id:
        project_id = os.getenv("GOOGLE_CLOUD_PROJECT")

    # Force a token refresh to ensure validity
    auth_req = google.auth.transport.requests.Request()
    credentials.refresh(auth_req)
    oauth_token = credentials.token

    return {
        "Authorization": f"Bearer {oauth_token}",
        "x-goog-user-project": project_id if project_id else "",
        "Content-Type": "application/json"
    }

def auth_header_provider(context: Optional[ReadonlyContext]) -> Dict[str, str]:
    """Callback function used by the MCP Client to inject headers."""
    return get_auth_headers()

def get_bigquery_mcp_toolset():
    # Initial headers for the handshake
    initial_headers = get_auth_headers()

    # We use StreamableHTTPConnectionParams for efficient data transfer
    tools = MCPToolset(
        connection_params=StreamableHTTPConnectionParams(
            url=BIGQUERY_MCP_URL,
            headers=initial_headers
        ),
        # This provider is the secret sauce for handling token expiry
        header_provider=auth_header_provider
    )
    return tools
Enter fullscreen mode Exit fullscreen mode

This step is where governance really comes into play. The tool definition becomes the contract.

The response is structured, predictable, and easy for the agent to interpret.

Why This PoC Goes Beyond a Demo

The value of this PoC lies not only in functionality, but in architectural discipline.

It demonstrates:

  • Agentic reasoning aligned with SRE decision workflows
  • Tool-based execution instead of brittle SQL-in-prompt patterns
  • Enterprise-grade governance and security
  • A realistic path from PoC to production

For SRE, platform engineering, and FinOps leaders, these characteristics are essential.

Practical Use Cases

This architectural pattern supports multiple high-impact use cases:

  • FinOps assistants for cost visibility and optimization
  • SRE copilots for reliability, incident analysis, and capacity planning
  • Platform analytics agents with strict access controls
  • Executive decision systems grounded in governed cloud data

The same design scales naturally as organizational maturity grows.

Key Takeaways

Building this PoC reinforced several core principles:

  • MCP is foundational for governed, enterprise AI
  • Google ADK aligns well with platform engineering practices
  • BigQuery is a natural backend for SRE and FinOps intelligence
  • Separation of reasoning and execution is non-negotiable

Conclusion

This PoC demonstrates that AI-native cloud platforms have moved beyond experimentation. With Google ADK and MCP, it is now possible to build intelligent agents that support reliability engineering, platform operations, and financial governance in a secure and scalable way.

For organizations undergoing cloud digital transformation, this approach provides a disciplined foundation for integrating AI into core operational workflows rather than treating it as an isolated experiment.

Happy building 🚀

PoC Shot

References

Key Challenge Faced: Authentication & Session Management

During this PoC, the biggest technical hurdle was authentication. Standard HTTP connections often use static headers. However, Google Cloud OAuth tokens are short-lived (usually 1 hour). If your agent runs longer than that, a static token results in a 403 Forbidden error.

To solve this, I implemented a Dynamic Header Provider. Instead of passing a fixed string, I pass a function that regenerates the OAuth token whenever the MCP session establishes a connection or refreshes its token.

Top comments (0)