Build a Daily Briefing AI Agent

Combine Gmail, Google Calendar, Yahoo Finance, weather, and web search MCP tools into one agent that delivers a personalized morning briefing.

Jun 19, 20267 min readFollow

Topics You Will Master

Authenticating and configuring the Gmail MCP server
Orchestrating five tool sources in a single agent
Filtering out destructive email tools for safety
Producing one organized morning briefing with memory

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:

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):

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:

BASH
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.

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()

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:

PYTHON
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:

PYTHON
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:

PYTHON
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:

POWERSHELL
python "03 AI Projects/05_daily_briefing_agent/daily_briefing_agent.py"
OUTPUT
You: Give me my daily briefing:
     1. Today's weather
     2. Today's calendar events
     3. Summary of unread emails
     4. Top news headlines
PYTHON
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.

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