<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mohammed Faizan Momin</title>
    <description>The latest articles on DEV Community by Mohammed Faizan Momin (@mohammed_faizanmomin_61e).</description>
    <link>https://dev.to/mohammed_faizanmomin_61e</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4093602%2F326fd88a-5f8a-4389-9747-b4e77f607aff.gif</url>
      <title>DEV Community: Mohammed Faizan Momin</title>
      <link>https://dev.to/mohammed_faizanmomin_61e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mohammed_faizanmomin_61e"/>
    <language>en</language>
    <item>
      <title>Serverless BigQuery MCP Agent with Gemini" published: true tags: googlecloud, gemini, ai, python</title>
      <dc:creator>Mohammed Faizan Momin</dc:creator>
      <pubDate>Tue, 25 Aug 2026 07:16:22 +0000</pubDate>
      <link>https://dev.to/mohammed_faizanmomin_61e/building-a-serverless-bigquery-mcp-agent-with-gemini-google-adk-58j</link>
      <guid>https://dev.to/mohammed_faizanmomin_61e/building-a-serverless-bigquery-mcp-agent-with-gemini-google-adk-58j</guid>
      <description>&lt;h1&gt;
  
  
  Demystifying Data Decisions: Building a Serverless BigQuery MCP Agent with Gemini &amp;amp; Google ADK
&lt;/h1&gt;




&lt;p&gt;title: "Demystifying Data Decisions: Building a Serverless BigQuery MCP Agent with Gemini &amp;amp; Google ADK"&lt;br&gt;
published: true&lt;br&gt;
tags: googlecloud, gemini, ai, python&lt;/p&gt;
&lt;h2&gt;
  
  
  description: "Learn how to build and deploy a serverless BigQuery MCP data agent using Google ADK, Gemini, BigQuery, and Cloud Run."
&lt;/h2&gt;

&lt;p&gt;In today's data-driven world, the gap between having raw business data and extracting strategic value is often wider than it should be. Traditionally, analyzing business data required deep SQL expertise, context switching between tools, and manual dashboard creation.&lt;/p&gt;

&lt;p&gt;But what if you could interact with your database using natural language, allowing a specialized AI agent to formulate plans, write SQL, dry-run queries, and extract insights automatically?&lt;/p&gt;

&lt;p&gt;In this post, I will walk you through how I built and deployed a &lt;strong&gt;BigQuery Model Context Protocol (MCP) Agent&lt;/strong&gt; using Google's &lt;strong&gt;Agent Development Kit (ADK)&lt;/strong&gt; and &lt;strong&gt;Gemini&lt;/strong&gt;, running entirely serverless on &lt;strong&gt;Google Cloud Run&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Architecture: Bringing Gemini to BigQuery via MCP
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; is an open standard that allows large language models (LLMs) like Gemini to interface securely with external data sources.&lt;/p&gt;

&lt;p&gt;Instead of writing custom API wrappers for every database operation, we configure the agent with an MCP toolset pointing to the Google BigQuery MCP server.&lt;/p&gt;

&lt;p&gt;Here's how the flow works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TD
    User([User Question]) --&amp;gt; ChatUI[Cloud Run Web UI]
    ChatUI --&amp;gt; Agent[Gemini Agent]
    Agent --&amp;gt; MCP[BigQuery MCP Toolset]
    MCP --&amp;gt; BQ[BigQuery API]
    BQ --&amp;gt; Insights[Structured Insights / Table]
    Insights --&amp;gt; User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Natural Language Query:&lt;/strong&gt; The user asks a business question, such as &lt;em&gt;"Where should we place coffee trucks based on ride-sharing patterns?"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Schema Investigation:&lt;/strong&gt; The agent calls &lt;code&gt;list_table_ids&lt;/code&gt; and &lt;code&gt;get_table_info&lt;/code&gt; to inspect the available datasets and understand their schemas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan &amp;amp; Query Generation:&lt;/strong&gt; The agent formulates a plan, performs a dry run to verify SQL correctness, and executes the query using &lt;code&gt;execute_sql_readonly&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insight Synthesis:&lt;/strong&gt; The results are interpreted and returned to the user as a clean Markdown response with tables, recommendations, and reasoning.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 1: Writing the Agent Logic (&lt;code&gt;agent.py&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Using Google ADK, we can bundle authentication, the MCP connection, and model configuration into a relatively small Python application.&lt;/p&gt;

&lt;p&gt;We use &lt;strong&gt;Application Default Credentials (ADC)&lt;/strong&gt; to establish an IAM identity context, ensuring the agent can only access Google Cloud resources that its identity is authorized to use.&lt;/p&gt;

&lt;p&gt;Here is the core &lt;code&gt;agent.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;google.auth&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.auth.transport.requests&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.adk.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LlmAgent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.adk.tools.mcp_tool.mcp_toolset&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;McpToolset&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.adk.tools.mcp_tool.mcp_session_manager&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;StreamableHTTPConnectionParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# 1. Authenticate using ADC (Application Default Credentials)
&lt;/span&gt;&lt;span class="n"&gt;_application_default_credentials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;_application_default_credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GOOGLE_CLOUD_PROJECT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_adc_auth_header_provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;_application_default_credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;_application_default_credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_application_default_credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-goog-user-project&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;# 2. Connect the BigQuery MCP Toolset
&lt;/span&gt;&lt;span class="n"&gt;bigquery_toolset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;McpToolset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;connection_params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;StreamableHTTPConnectionParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://bigquery.googleapis.com/mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tool_filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_dataset_info&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list_table_ids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_table_info&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execute_sql_readonly&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;header_provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_adc_auth_header_provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# 3. Define the agent's reasoning flow
&lt;/span&gt;&lt;span class="n"&gt;system_instruction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
You are a helpful assistant that can answer questions about data in BigQuery.

Your data is in the `bigquery-public-data.new_york_citibike` dataset
(NYC Citi Bike trips).

Plan of action:
0. Analyze the dataset schema.
1. Formulate a plan and run a Dry Run to verify SQL correctness.
2. Query the data using execute_sql_readonly.
3. Retrieve the data and display a clean Markdown summary.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;


&lt;span class="n"&gt;root_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3.6-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data_agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;system_instruction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A helpful assistant that can answer questions using BigQuery data.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bigquery_toolset&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our &lt;code&gt;requirements.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;google-adk==2.4.*
mcp==1.29.*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part here is the &lt;code&gt;McpToolset&lt;/code&gt;. Instead of giving the model unrestricted access to BigQuery, we explicitly expose the tools it needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;get_dataset_info&lt;/code&gt; — inspect dataset metadata&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;list_table_ids&lt;/code&gt; — discover available tables&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_table_info&lt;/code&gt; — inspect table schemas&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;execute_sql_readonly&lt;/code&gt; — execute read-only SQL queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives the agent enough capability to investigate the dataset and answer questions without needing a custom BigQuery API wrapper.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Deploying the Agent to Google Cloud Run
&lt;/h2&gt;

&lt;p&gt;Now that the agent works, we need a way for users to interact with it.&lt;/p&gt;

&lt;p&gt;Instead of maintaining our own servers, we can deploy the application to &lt;strong&gt;Google Cloud Run&lt;/strong&gt;, keeping the architecture serverless.&lt;/p&gt;

&lt;p&gt;The Google ADK CLI simplifies the deployment process. With a single command, ADK can package and deploy the application.&lt;/p&gt;

&lt;p&gt;During deployment, the workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generates the container configuration&lt;/li&gt;
&lt;li&gt;Builds the container image using &lt;strong&gt;Cloud Build&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Stores the image in &lt;strong&gt;Artifact Registry&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Deploys the container to &lt;strong&gt;Cloud Run&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Provides a chat UI using the &lt;code&gt;--with_ui&lt;/code&gt; option&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the deployment command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv tool run &lt;span class="nt"&gt;--from&lt;/span&gt; google-adk&lt;span class="o"&gt;==&lt;/span&gt;2.4.0 &lt;span class="se"&gt;\&lt;/span&gt;
  adk deploy cloud_run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--with_ui&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project&lt;/span&gt; &lt;span class="nv"&gt;$GOOGLE_CLOUD_PROJECT&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="nv"&gt;$GOOGLE_CLOUD_REGION&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--service_name&lt;/span&gt; track2-data-agent &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--app_name&lt;/span&gt; data_agent &lt;span class="se"&gt;\&lt;/span&gt;
  data_agent &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allow-unauthenticated&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--max-instances&lt;/span&gt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the deployment finishes, Cloud Run provides a URL where we can interact with the agent through the browser.&lt;/p&gt;

&lt;p&gt;This means users don't need to know Python, SQL, BigQuery, or even how the agent works internally. They simply ask questions in natural language.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Extracting Insights from Public Data
&lt;/h2&gt;

&lt;p&gt;Once deployed, it was time to put the agent to the test.&lt;/p&gt;

&lt;p&gt;For this example, we're working with the &lt;strong&gt;NYC Citi Bike public dataset&lt;/strong&gt;, which contains millions of trip records with information about start stations, end stations, timestamps, and user types.&lt;/p&gt;

&lt;p&gt;I gave the agent the following business-oriented prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"We want to find the best city bike stations to place our 3 coffee trucks based on trip data. Which stations do you recommend?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of manually inspecting the schema and writing SQL, the agent handled the analysis workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the Agent Solved It
&lt;/h3&gt;

&lt;p&gt;The agent first inspected the dataset to understand what information was available.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Schema Check
&lt;/h4&gt;

&lt;p&gt;It examined the &lt;code&gt;citibike_trips&lt;/code&gt; table and identified fields related to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start and end stations&lt;/li&gt;
&lt;li&gt;Trip timestamps&lt;/li&gt;
&lt;li&gt;Trip volume&lt;/li&gt;
&lt;li&gt;User type&lt;/li&gt;
&lt;li&gt;Subscriber vs. customer activity&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. SQL Formulation
&lt;/h4&gt;

&lt;p&gt;Based on the available fields, the agent constructed a read-only query to analyze station activity.&lt;/p&gt;

&lt;p&gt;The analysis considered factors such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Overall trip volume&lt;/li&gt;
&lt;li&gt;Morning activity&lt;/li&gt;
&lt;li&gt;Commuter-oriented usage&lt;/li&gt;
&lt;li&gt;Subscriber activity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this example, the morning commute window was defined as &lt;strong&gt;6:00 AM to 10:00 AM&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Insight Generation
&lt;/h4&gt;

&lt;p&gt;Based on the resulting trip activity, the analysis identified three strong candidates for coffee-truck placement:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Midtown East / Grand Central
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Station:&lt;/strong&gt; E 42 St &amp;amp; Vanderbilt Ave&lt;/p&gt;

&lt;p&gt;The station showed extremely high overall activity along with substantial morning usage, making the Grand Central area a strong candidate for reaching commuters.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Midtown South / Union Square &amp;amp; Flatiron
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Station:&lt;/strong&gt; E 17 St &amp;amp; Broadway&lt;/p&gt;

&lt;p&gt;Its combination of high trip volume and central location makes it another promising candidate, particularly for reaching riders moving through the Union Square and Flatiron area.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Midtown West / Penn Station
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Station:&lt;/strong&gt; 8 Ave &amp;amp; W 33 St&lt;/p&gt;

&lt;p&gt;The station showed strong morning activity and overall usage around one of Manhattan's major transportation hubs.&lt;/p&gt;

&lt;p&gt;The resulting analysis looked like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rank&lt;/th&gt;
&lt;th&gt;Station Name&lt;/th&gt;
&lt;th&gt;Major Corridor&lt;/th&gt;
&lt;th&gt;Total Trip Volume&lt;/th&gt;
&lt;th&gt;Morning Rush Trips (6–10 AM)&lt;/th&gt;
&lt;th&gt;Subscriber %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;E 42 St &amp;amp; Vanderbilt Ave&lt;/td&gt;
&lt;td&gt;Grand Central Terminal&lt;/td&gt;
&lt;td&gt;1,062,097&lt;/td&gt;
&lt;td&gt;301,192&lt;/td&gt;
&lt;td&gt;93.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;E 17 St &amp;amp; Broadway&lt;/td&gt;
&lt;td&gt;Union Square / Flatiron&lt;/td&gt;
&lt;td&gt;867,794&lt;/td&gt;
&lt;td&gt;146,548&lt;/td&gt;
&lt;td&gt;91.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8 Ave &amp;amp; W 33 St&lt;/td&gt;
&lt;td&gt;Penn Station / Midtown West&lt;/td&gt;
&lt;td&gt;639,039&lt;/td&gt;
&lt;td&gt;157,272&lt;/td&gt;
&lt;td&gt;92.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Based on total trip volume and morning peak activity, these stations emerged as strong candidates from the available trip data.&lt;/p&gt;

&lt;p&gt;Of course, trip volume alone doesn't guarantee coffee sales. A production analysis could incorporate additional signals such as pedestrian traffic, nearby competitors, office density, weather, permits, and historical sales.&lt;/p&gt;

&lt;p&gt;That's also where an agent-based approach becomes interesting: additional datasets can be connected and incorporated into the analysis without changing how the end user asks questions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use MCP Here?
&lt;/h2&gt;

&lt;p&gt;One of the most interesting parts of this architecture is that the agent isn't limited to generating text.&lt;/p&gt;

&lt;p&gt;Through MCP, Gemini can interact with tools that expose actual capabilities.&lt;/p&gt;

&lt;p&gt;In our case, the flow becomes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User question → Gemini reasoning → MCP tool call → BigQuery → Gemini interpretation → User&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The model can inspect the database before attempting to answer the question.&lt;/p&gt;

&lt;p&gt;This is particularly useful because database schemas change. Instead of hard-coding every table and column into the application, the agent can use tools such as &lt;code&gt;list_table_ids&lt;/code&gt; and &lt;code&gt;get_table_info&lt;/code&gt; to understand what data is available.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;p&gt;Giving an AI agent access to a production data warehouse requires careful permission management.&lt;/p&gt;

&lt;p&gt;This implementation uses &lt;strong&gt;Application Default Credentials (ADC)&lt;/strong&gt;, which means access can be controlled through Google Cloud IAM rather than embedding credentials directly in the application.&lt;/p&gt;

&lt;p&gt;The agent also uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;execute_sql_readonly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for querying data.&lt;/p&gt;

&lt;p&gt;That distinction is important: an analytics agent should generally not need permission to modify or delete warehouse data.&lt;/p&gt;

&lt;p&gt;In a production environment, I would also recommend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Following the principle of least privilege&lt;/li&gt;
&lt;li&gt;Restricting the service account to required datasets&lt;/li&gt;
&lt;li&gt;Avoiding hard-coded credentials&lt;/li&gt;
&lt;li&gt;Keeping query execution read-only&lt;/li&gt;
&lt;li&gt;Monitoring BigQuery usage and query costs&lt;/li&gt;
&lt;li&gt;Requiring authentication for applications that expose sensitive company data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this demonstration, &lt;code&gt;--allow-unauthenticated&lt;/code&gt; makes the UI easy to access. For an application connected to private company data, authentication and authorization should be configured before exposing the service.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Serverless?
&lt;/h2&gt;

&lt;p&gt;Cloud Run is a good fit for this architecture because the application doesn't need a permanently running VM.&lt;/p&gt;

&lt;p&gt;The overall stack stays relatively simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
  ↓
Cloud Run
  ↓
Google ADK + Gemini
  ↓
BigQuery MCP Server
  ↓
BigQuery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cloud Run handles the application runtime, while BigQuery handles the analytical workload.&lt;/p&gt;

&lt;p&gt;That leaves the application focused primarily on the agent logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion &amp;amp; Next Steps
&lt;/h2&gt;

&lt;p&gt;Using Google's ADK and the BigQuery MCP server, we can build a natural-language interface over analytical data without creating a large custom API layer.&lt;/p&gt;

&lt;p&gt;The agent can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inspect BigQuery schemas&lt;/li&gt;
&lt;li&gt;Understand available tables and fields&lt;/li&gt;
&lt;li&gt;Formulate an analysis plan&lt;/li&gt;
&lt;li&gt;Generate SQL&lt;/li&gt;
&lt;li&gt;Validate queries&lt;/li&gt;
&lt;li&gt;Execute read-only queries&lt;/li&gt;
&lt;li&gt;Interpret the results&lt;/li&gt;
&lt;li&gt;Present the findings in readable Markdown&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Application Default Credentials provide the IAM identity used to access Google Cloud resources, while Cloud Run gives us a serverless deployment target and ADK provides the agent framework.&lt;/p&gt;

&lt;p&gt;Most importantly, the end user doesn't need to think about any of this infrastructure.&lt;/p&gt;

&lt;p&gt;They can simply ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Where should we place our coffee trucks?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the agent can turn that business question into a structured data-analysis workflow.&lt;/p&gt;

&lt;p&gt;The same architecture could be extended to use internal sales data, customer analytics, inventory information, operational metrics, or other datasets stored in BigQuery.&lt;/p&gt;

&lt;p&gt;That's where MCP-powered data agents become especially useful: &lt;strong&gt;turning natural-language business questions into controlled, tool-driven analytical workflows.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built as part of the Google Cloud Cohort 3 Challenge.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>gemini</category>
      <category>python</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
