This lesson assembles everything from the previous projects into one practical assistant: a daily briefing agent. In a single request it fetches the weather, reads today's Google Calendar events, summarizes unread Gmail, and pulls news from web search and Yahoo Finance — then presents it all as one organized update.
The new piece is the Gmail MCP server, and the key safety technique is filtering out destructive tools so the agent can read and summarize mail but never delete it.
Note
This project reuses the Google OAuth credentials and the mcp_config.json pattern from earlier lessons. Set those up via Build a Travel Planner Agent with MCP before continuing.
Configuring and Authenticating Gmail
The Gmail server runs through npx and uses the same gcp-oauth.keys.json credentials. Add it to scripts/mcp_config.json:
{
"gmail": {
"command": "npx",
"args": ["@gongrzhe/server-gmail-autoauth-mcp"],
"transport": "stdio"
}
}
Authenticate once. Make sure your credentials file is in place, then run the server's auth command:
Windows (PowerShell):
mkdir ~/.gmail-mcp
# Move your gcp-oauth.keys.json into C:\Users\your-username\.gmail-mcp\ first
npx @gongrzhe/server-gmail-autoauth-mcp auth
Important
Replace your-username with your actual Windows username. The credentials file must be named gcp-oauth.keys.json and live in the .gmail-mcp folder.
On Linux/macOS:
mkdir -p ~/.gmail-mcp
mv gcp-oauth.keys.json ~/.gmail-mcp/
npx @gongrzhe/server-gmail-autoauth-mcp auth
A browser opens for Gmail OAuth — sign in, click Allow, and the credentials are saved to ~/.gmail-mcp/credentials.json.
Note
Search "GongRzhe Gmail-MCP-Server GitHub" for the server's source and the full list of supported tools.
Building the Briefing Agent
The agent loads three MCP servers plus the two local tools, then strips out anything destructive.
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()
Loading Tools and Removing Dangerous Ones
load_mcp_config pulls the Gmail, Calendar, and Yahoo Finance servers. We then filter out every tool that could destroy data — deletes and batch modifications — so the briefing agent is read-only by construction:
async def get_tools():
mcp_config = utils.load_mcp_config("gmail", "google-calendar", "yahoo-finance")
client = MultiServerMCPClient(mcp_config)
mcp_tools = await client.get_tools()
tools = mcp_tools + [base_tools.web_search, base_tools.get_weather]
# Remove destructive email tools — the briefing agent should never delete mail
filter_tools = ['delete_email', 'batch_modify_emails', 'batch_delete_emails',
'delete_label', 'delete_filter']
safe_tools = [tool for tool in tools if tool.name not in filter_tools]
print(f"Loaded {len(safe_tools)} Tools")
print(f"Tools Available\n{[tool.name for tool in safe_tools]}")
return safe_tools
Caution
Whenever you connect an agent to mail, calendars, or files, explicitly remove destructive tools — or guard them with human-in-the-loop approval (covered in LangChain Agent Fundamentals). A read-only briefing agent should not have the ability to delete anything.
A Date- and Location-Aware Prompt
The briefing prompt injects today's date and a default location, and lists exactly what to gather and how to present it:
from datetime import datetime
def get_daily_briefing_prompt():
"""Generate daily briefing prompt with current date context."""
today = datetime.now()
return f"""You are a daily briefing assistant.
Default Location: Mumbai, India
Today: {str(today.date())}
Tools: Gmail, Yahoo Finance, Google Calendar, weather, web search
Instructions:
- Fetch today's weather
- Read today's calendar events from Google Calendar
- Summarize unread emails from Gmail
- Show top news headlines using web_search and yahoo finance news
- Present information in a clear, organized format"""
Wiring and Running
Assemble the agent and add a chat loop:
async def get_briefing(query, thread_id='default'):
tools = await get_tools()
system_prompt = prompts.get_daily_briefing_prompt()
agent = create_agent(
model=model,
tools=tools,
system_prompt=system_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 get_briefing(query)
if __name__ == "__main__":
asyncio.run(ask())
Running the Briefing
Start the script and ask for your morning update:
python "03 AI Projects/05_daily_briefing_agent/daily_briefing_agent.py"
You: Give me my daily briefing:
1. Today's weather
2. Today's calendar events
3. Summary of unread emails
4. Top news headlines
Loaded 18 Tools
============== Output =============
Good morning! Here is your briefing for today:
Weather (Mumbai): 30°C, partly cloudy, light winds — comfortable day ahead.
Calendar:
- 10:30 Team standup
- 14:00 Client review call
- 18:00 Gym
Unread email (5):
- 2 newsletters (AI Weekly, Product Hunt)
- 1 invoice from your hosting provider (due Friday)
- 2 replies on the Q1 report thread — both approve the draft
Top headlines:
- Markets steady ahead of earnings season
- Major cloud provider announces new AI chips
- <additional items from web_search and Yahoo Finance>
In one request the agent called five different tools — weather, calendar, Gmail, web search, and Yahoo Finance — and synthesized them into a single, scannable briefing. This is the payoff of MCP: many services, one agent, one conversation.
Tip
Schedule this script to run each morning (Task Scheduler on Windows, cron on Linux/macOS) and pipe the output to a file or notification for a hands-free daily briefing.
So far every agent has run in your terminal. The remaining lessons make agents available over the network — starting with Deploy AI Agents with FastAPI.