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:
{
"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.
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:
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:
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:
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:
python "03 AI Projects/04_gsheet_analysis_agent/gsheet_analysis_agent.py"
On Linux/macOS: the command is identical.
You: list all my spreadsheets
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:
You: read the Portfolio Tracker sheet and compare my holdings to today's prices
============== 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.