Build a Google Sheets Analysis Agent with MCP

Connect Google Sheets and Yahoo Finance MCP servers so an agent can read spreadsheets, analyze data, and report financial insights from the terminal.

Jun 19, 20268 min readFollow

Topics You Will Master

Configuring Google Sheets and Yahoo Finance MCP servers with uvx
Filtering out model-incompatible tools before binding them
Combining a spreadsheet server with a live finance server
Running an agent that reads and analyzes your spreadsheets

This lesson builds a Google Sheets analysis agent. It connects two MCP servers — Google Sheets for reading and writing spreadsheets and Yahoo Finance for live market data — so the agent can answer questions like "summarize my portfolio sheet and compare it to today's prices."

You will configure both servers, learn to filter out tools that a given model cannot call, and run an agent with memory that operates on your real spreadsheets.

Note

The Google Sheets server uses the same OAuth credentials you created for the Calendar server. If you have not set that up, follow the Google Cloud OAuth steps in Build a Travel Planner Agent with MCP first.

Configuring the MCP Servers

Both servers run through uvx (part of uv). The Google Sheets server points at your OAuth credentials and a token file; Yahoo Finance needs no auth. Add these entries to scripts/mcp_config.json:

JSON
{
  "google-sheets": {
    "command": "uvx",
    "args": ["mcp-google-sheets@latest"],
    "env": {
      "CREDENTIALS_PATH": "C:\\Users\\your-username\\.gmail-mcp\\gcp-oauth.keys.json",
      "TOKEN_PATH": "C:\\Users\\your-username\\.gmail-mcp\\token.json"
    },
    "transport": "stdio"
  },
  "yahoo-finance": {
    "command": "uvx",
    "args": ["yahoo-finance-mcp-server"],
    "transport": "stdio"
  }
}

Important

Replace your-username in both paths with your actual Windows username. On Linux/macOS, use forward-slash paths like /home/your-username/.gmail-mcp/gcp-oauth.keys.json and /home/your-username/.gmail-mcp/token.json.

Note

Google Sheets authentication completes automatically the first time you use it. Ask the agent "List my spreadsheets," approve the browser OAuth prompt, and the token is saved to token.json for future runs.

Building the Agent

The structure mirrors the travel planner — async tool loading, a model, and a checkpointer — with one new technique: removing tools the model struggles with.

PYTHON
import sys
import os

root_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(root_dir)

from dotenv import load_dotenv
load_dotenv()

from langchain_google_genai import ChatGoogleGenerativeAI
from langchain.agents import create_agent
from langchain.messages import HumanMessage
from langgraph.checkpoint.memory import InMemorySaver
from langchain_mcp_adapters.client import MultiServerMCPClient
import asyncio

from scripts import base_tools, prompts, utils

if sys.platform == "win32":
    sys.stdout.reconfigure(encoding="utf-8")

model = ChatGoogleGenerativeAI(model="gemini-2.5-flash")
checkpointer = InMemorySaver()

Tip

This agent uses gemini-2.5-flash rather than a Gemini 3 preview. Spreadsheet workflows involve many small, structured tool calls, and the 2.5 Flash model is fast and cost-effective for that pattern.

Filtering Incompatible Tools

Some MCP tools expose schemas that a particular model cannot call reliably. Here the update_cells tool is filtered out so it is never offered to the model, avoiding malformed calls:

PYTHON
async def get_tools():
    mcp_config = utils.load_mcp_config("google-sheets", "yahoo-finance")
    client = MultiServerMCPClient(mcp_config)

    mcp_tools = await client.get_tools()
    tools = mcp_tools + [base_tools.web_search, base_tools.get_weather]

    # Filter tools that don't work well with Gemini
    problematic_tools = ['update_cells']
    safe_tools = [tool for tool in tools if tool.name not in problematic_tools]

    print(f"Loaded {len(safe_tools)} Tools")
    print(f"Tools Available\n{[tool.name for tool in safe_tools]}")
    return safe_tools

Warning

If an agent throws schema or argument errors on a specific tool, filtering it out by name (as shown) is a quick, reliable fix. Reintroduce it once you confirm the model can call it correctly.

The System Prompt

The prompt keeps the agent grounded in the available Sheets tools and insists it actually call them instead of guessing:

PYTHON
GOOGLE_SHEETS_PROMPT = """You are a helpful Google Sheets assistant.

You have access to Google Sheets tools. When the user asks about spreadsheets:
- Use the list_spreadsheets tool to list all spreadsheets
- Use get_sheet_data to read sheet data
- Use create_spreadsheet to create new sheets

IMPORTANT: You MUST use the available tools to complete user requests.
Do not try to answer without using tools."""

Wiring and Running

Create the agent with the filtered tools, the prompt, and a checkpointer, then expose a chat loop:

PYTHON
async def google_sheet_agent(query, thread_id="default"):
    tools = await get_tools()

    agent = create_agent(model=model,
                         tools=tools,
                         system_prompt=prompts.GOOGLE_SHEETS_PROMPT,
                         checkpointer=checkpointer)

    config = {"configurable": {"thread_id": thread_id}}
    result = await agent.ainvoke({'messages': [HumanMessage(query)]}, config=config)

    response = result['messages'][-1].text
    print("\n============== Output =============")
    print(response)


async def ask():
    print("\nChat mode started. Type 'q' or 'quite' to exit.\n")
    while True:
        query = input("You: ").strip()
        if query.lower() in ["q", "quite"]:
            print("Exiting chat mode.")
            break
        await google_sheet_agent(query)


if __name__ == "__main__":
    asyncio.run(ask())

Running the Agent

Start the script and ask it to discover your spreadsheets first:

POWERSHELL
python "03 AI Projects/04_gsheet_analysis_agent/gsheet_analysis_agent.py"

On Linux/macOS: the command is identical.

PLAINTEXT
You: list all my spreadsheets
PLAINTEXT
Loaded 12 Tools
Tools Available
['list_spreadsheets', 'get_sheet_data', 'create_spreadsheet', ..., 'get_stock_info', 'web_search', 'get_weather']

============== Output =============
Here are the spreadsheets in your Google Drive:
1. Portfolio Tracker
2. Monthly Budget
3. Sales Q1 2024

Because the agent has memory, you can drill into a sheet and then enrich it with live finance data:

PLAINTEXT
You: read the Portfolio Tracker sheet and compare my holdings to today's prices
PLAINTEXT
============== Output =============
Your Portfolio Tracker holds AAPL, MSFT, and GOOGL. Using live Yahoo Finance data:
- AAPL: bought at $180, now ~$260 (+44%)
- MSFT: bought at $410, now ~$462 (+13%)
- GOOGL: bought at $140, now ~$165 (+18%)
Overall your tracked holdings are up across the board.

The agent listed spreadsheets and read data through the Google Sheets server, then pulled current quotes through the Yahoo Finance server — combining your private data with live market data in one conversation.

Tip

Try "create a new sheet called Watchlist with columns Ticker, Target Price, Notes" — the agent uses create_spreadsheet to build it. Keep write operations under human review for anything important.

Next, we combine several servers into a single morning assistant in Build a Daily Briefing AI Agent.

Found this useful? Keep building with me.

New tutorials every week on YouTube — or go deeper with a full structured course.

Find this tutorial useful?

Subscribe to our YouTube channels for more practical production walk-throughs.

Discussion & Comments