๐ŸŽฏ What You’re Going to Build Link to heading

Imagine being able to ask your computer:

“Find all unread emails from this week about invoices” “Summarize yesterday’s important emails for me” “List suspicious emails received this month”

That’s exactly what you’ll build in this tutorial! We’re going to create a personal assistant that can analyze your Gmail emails using Claude Code, all in read-only mode for maximum security.

Why this tutorial? Link to heading

  • โœ… Simple: 30-minute setup
  • โœ… Secure: Read-only access only
  • โœ… Free: Uses free Gmail API
  • โœ… Powerful: Artificial intelligence to analyze your emails
  • โœ… Revocable: You can cut access with 1 click

What you need Link to heading

  • A Gmail account
  • A Linux computer (Ubuntu, Debian, Fedora, etc.)
  • 30 minutes of your time
  • No programming skills required!

๐Ÿš€ Overview: How Does It Work? Link to heading

    Your Gmail Emails
          โ†“
   [Gmail API - Read Only]
          โ†“
     [MCP Server]
          โ†“
     [Claude Code]
          โ†“
  Intelligent Analysis!

The idea: Claude can “read” your emails (but not modify them) and help you analyze them with artificial intelligence.

Important: We start with zero risk - Claude can ONLY read. No deletion, no sending, no modification.

๐Ÿ“‹ Part 1: Setting Up Google Cloud (15 minutes) Link to heading

Step 1.1: Create Your Project Link to heading

This is like creating a “folder” for your project in Google Cloud.

  1. Go to: console.cloud.google.com
  2. Log in with your Gmail account
  3. Click on the project dropdown menu (at the top)
  4. Click on “New project”

Fill in:

  • Name: My Email Assistant (or whatever you want)
  • Click “Create”

โฑ๏ธ Wait 20 seconds… and there you go, your project is created!

Step 1.2: Enable the Gmail API Link to heading

Now we “turn on” the Gmail API to be able to read your emails.

  1. In the menu โ˜ฐ โ†’ Click “APIs & Services” โ†’ “Library”
  2. Search for: Gmail API
  3. Click on it
  4. Click on the big blue “ENABLE” button

โœ… Done! You’ll see “API enabled”

Step 1.3: Configure Permissions (Important!) Link to heading

Here we tell Google: “I only want to READ my emails, nothing else”.

Navigation: Menu โ˜ฐ โ†’ APIs & Services โ†’ OAuth consent screen

Choose:

  • Type: External โœ…
  • Click “Create”

Page 1 - Basic info:

Simply fill in:

The rest? Leave it blank!

Click “Save and continue”

Page 2 - Permissions (THE important part!):

  1. Click “Add or remove scopes”
  2. A window opens
  3. Search for: gmail.readonly
  4. Check ONLY this box:
    โœ… https://www.googleapis.com/auth/gmail.readonly
    

๐Ÿ”ด SUPER IMPORTANT: Only check that one! This is your guarantee that Claude can only READ.

  1. Click “Update”
  2. Click “Save and continue”

Page 3 - Add yourself as a tester:

  1. Click “+ Add users”
  2. Enter your Gmail address
  3. Click “Add”
  4. Click “Save and continue”

Page 4 - Summary:

Check that everything is correct, then “Back to dashboard”

Step 1.4: Download Your “Key” Link to heading

Now we get a file that allows your computer to connect.

  1. Menu โ˜ฐ โ†’ APIs & Services โ†’ Credentials
  2. Click the big “+ CREATE CREDENTIALS” button
  3. Choose “OAuth 2.0 Client ID”

Configure:

  • Application type: Desktop app
  • Name: Local Email Assistant
  • Click “Create”

A window appears:

  • Click “DOWNLOAD JSON”
  • The file downloads (named something like client_secret_xxx.json)
  • Click “OK”

๐ŸŽ‰ Congratulations! Google Cloud part finished. The hardest part is done!


๐Ÿ’ป Part 2: Installation on Your Computer (10 minutes) Link to heading

Step 2.1: Check Prerequisites Link to heading

Open a terminal and type:

# Check Node.js (should display v18 or higher)
node --version

# Check pnpm
pnpm --version

# Check Claude Code
claude --version

Not installed? Don’t panic:

# Install Node.js via nvm (recommended)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc
nvm install --lts

# Install pnpm
curl -fsSL https://get.pnpm.io/install.sh | sh -
source ~/.bashrc

# Install Claude Code
npm install -g @anthropic-ai/claude-code

Step 2.2: Create the Folders Link to heading

We create a “home” for our project:

# Create folders
mkdir -p ~/my-email-assistant
mkdir -p ~/.config/gmail-assistant/creds

# Secure (no one else can see)
chmod 700 ~/.config/gmail-assistant

Step 2.3: Move the Downloaded File Link to heading

Remember the client_secret_xxx.json file? Let’s put it away:

# Move it (adjust the path if needed)
mv ~/Downloads/client_secret_*.json \
   ~/.config/gmail-assistant/creds/credentials.json

# Protect it (read-only for you)
chmod 600 ~/.config/gmail-assistant/creds/credentials.json

# Verify
ls -la ~/.config/gmail-assistant/creds/
# You should see: -rw------- credentials.json

Step 2.4: Create the Server Code Link to heading

We’re going to create a small program that bridges Claude and Gmail.

cd ~/my-email-assistant

# Create the configuration file
cat > package.json << 'EOF'
{
  "name": "email-assistant",
  "version": "1.0.0",
  "type": "module",
  "dependencies": {
    "googleapis": "^140.0.0",
    "@modelcontextprotocol/sdk": "^0.5.0"
  }
}
EOF

# Install dependencies
pnpm install

Create the server (copy-paste this entire block):

cat > server.js << 'EOFSRV'
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { google } from 'googleapis';
import { readFile, writeFile } from 'fs/promises';
import { join } from 'path';
import { homedir } from 'os';

// READ ONLY - This is our security guarantee!
const SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'];
const TOKEN_PATH = join(homedir(), '.config/gmail-assistant/creds/token.json');
const CREDENTIALS_PATH = join(homedir(), '.config/gmail-assistant/creds/credentials.json');

class EmailAssistant {
  constructor() {
    this.server = new Server(
      { name: 'email-assistant', version: '1.0.0' },
      { capabilities: { tools: {} } }
    );
    this.setupTools();
    this.gmail = null;
  }

  async authorize() {
    const credentials = JSON.parse(await readFile(CREDENTIALS_PATH));
    const { client_secret, client_id, redirect_uris } = credentials.installed;
    const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);

    try {
      const token = await readFile(TOKEN_PATH);
      oAuth2Client.setCredentials(JSON.parse(token));
    } catch (err) {
      return await this.getNewToken(oAuth2Client);
    }
    return oAuth2Client;
  }

  async getNewToken(oAuth2Client) {
    const authUrl = oAuth2Client.generateAuthUrl({
      access_type: 'offline',
      scope: SCOPES,
    });

    console.error('\n๐Ÿ” First connection - Authorization required\n');
    console.error('1. Open this URL in your browser:');
    console.error(`   ${authUrl}\n`);
    console.error('2. Log in and authorize');
    console.error('3. Copy the code you receive\n');
    console.error('Enter the code here: ');

    const readline = await import('readline');
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stderr,
    });

    return new Promise((resolve, reject) => {
      rl.question('', async (code) => {
        rl.close();
        try {
          const { tokens } = await oAuth2Client.getToken(code);
          oAuth2Client.setCredentials(tokens);
          await writeFile(TOKEN_PATH, JSON.stringify(tokens));
          console.error('\nโœ… Perfect! You are connected.\n');
          resolve(oAuth2Client);
        } catch (err) {
          console.error('\nโŒ Oops, error:', err.message);
          reject(err);
        }
      });
    });
  }

  setupTools() {
    this.server.setRequestHandler('tools/list', async () => ({
      tools: [
        {
          name: 'list_emails',
          description: 'List your Gmail emails',
          inputSchema: {
            type: 'object',
            properties: {
              count: { type: 'number', description: 'Number of emails (max 100)', default: 10 },
              query: { type: 'string', description: 'Gmail search query (e.g., "is:unread")' },
            },
          },
        },
        {
          name: 'search_emails',
          description: 'Search for specific emails',
          inputSchema: {
            type: 'object',
            properties: {
              query: { type: 'string', description: 'Your search query' },
              count: { type: 'number', default: 10 },
            },
            required: ['query'],
          },
        },
      ],
    }));

    this.server.setRequestHandler('tools/call', async (request) => {
      if (!this.gmail) {
        const auth = await this.authorize();
        this.gmail = google.gmail({ version: 'v1', auth });
      }

      const args = request.params.arguments;
      const maxResults = Math.min(args.count || args.maxResults || 10, 100);
      const query = args.query || '';

      const res = await this.gmail.users.messages.list({
        userId: 'me',
        maxResults,
        q: query,
      });

      const messages = res.data.messages || [];
      const details = await Promise.all(
        messages.map(async (msg) => {
          const detail = await this.gmail.users.messages.get({
            userId: 'me',
            id: msg.id,
            format: 'metadata',
            metadataHeaders: ['From', 'Subject', 'Date'],
          });

          const headers = detail.data.payload.headers;
          return {
            id: msg.id,
            from: headers.find((h) => h.name === 'From')?.value,
            subject: headers.find((h) => h.name === 'Subject')?.value,
            date: headers.find((h) => h.name === 'Date')?.value,
          };
        })
      );

      return {
        content: [{ type: 'text', text: JSON.stringify(details, null, 2) }],
      };
    });
  }

  async run() {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
    console.error('๐Ÿš€ Email Assistant ready (read-only)\n');
  }
}

const assistant = new EmailAssistant();
assistant.run().catch(console.error);
EOFSRV

# Make executable
chmod +x server.js

๐Ÿ”— Part 3: Connect to Claude (5 minutes) Link to heading

Step 3.1: Just One Command! Link to heading

This is the simplest part. Just one command line:

claude mcp add gmail /usr/bin/node ~/my-email-assistant/server.js

Check that it worked:

claude mcp list

# You should see:
# gmail: /usr/bin/node /home/[you]/my-email-assistant/server.js

Step 3.2: First Connection Link to heading

Launch Claude:

claude

What will happen:

  1. A message displays with a long URL
  2. You copy this URL
  3. You open it in your browser
  4. You log in to Gmail
  5. Google tells you: “Warning, unverified application”
    • Click “Advanced settings”
    • Click “Go to [your app] (unsafe)”
  6. Google shows: “View your email” โœ… (this is READ ONLY)
  7. Click “Allow”
  8. Google gives you a code
  9. You copy it
  10. You paste it in the Claude terminal
  11. Press Enter

Success message:

โœ… Perfect! You are connected.
๐Ÿš€ Email Assistant ready (read-only)

๐ŸŽฎ Part 4: Using Your Assistant (The Fun Part!) Link to heading

First Test: Simple List Link to heading

In Claude, simply type:

List my last 5 emails

Result: Claude shows you your last 5 emails with sender and subject!

Practical Examples Link to heading

๐Ÿ“ง Find an Email Link to heading

Find Marie's email from last week

๐Ÿ“Š Daily Summary Link to heading

Summarize today's important emails for me
Search all unread emails containing "invoice"

๐Ÿ“… Organization Link to heading

List this week's emails, grouped by sender

๐Ÿšจ Simple Detection Link to heading

Are there any suspicious emails received today?

More Advanced Prompts Link to heading

Once comfortable, try:

Analyze my last 20 emails and tell me:
1. Which ones require an urgent response
2. Which ones are newsletters
3. Which ones contain attachments

Make a small summary for each category.

Or:

Among my emails from this week:
- Find those that mention meetings
- Extract the dates and times mentioned
- Make me a schedule

Format: clear and simple list

๐Ÿ›ก๏ธ Security: What You Need to Know Link to heading

โœ… What Claude CAN Do Link to heading

  • Read your emails
  • Search in your inbox
  • Analyze content
  • Make summaries for you

โŒ What Claude CANNOT Do Link to heading

  • Send emails โŒ
  • Delete emails โŒ
  • Modify emails โŒ
  • Forward emails โŒ
  • Create drafts โŒ

Why? Because we configured gmail.readonly - read-only!

๐Ÿ”“ Revoke Access (If Needed) Link to heading

Want to cut access? 2 clicks:

  1. Go to: myaccount.google.com/permissions
  2. Find “My Email Assistant”
  3. Click “Remove access”

โšก Immediate effect - Claude can no longer read your emails.

๐Ÿ“Š See What’s Happening Link to heading

Google shows you everything:

  • When Claude accesses your emails
  • How many times
  • What type of access (always “read”)

Check it out at: console.cloud.google.com โ†’ APIs & Services โ†’ Dashboard


๐ŸŽ“ Practical Use Cases Link to heading

1. Daily Productivity Link to heading

In the morning:

Summarize important emails received overnight

End of day:

Which emails are still waiting for a response?

2. Organization Link to heading

Find all emails from my boss this month and
summarize the action items requested
In 2024, how many emails did I receive from [company]?
What was the main topic?

4. Cleanup Link to heading

List all newsletters I receive regularly.
Show me the ones I never open.

5. Simple Analysis Link to heading

Among my last 50 emails, which ones look weird or suspicious?
Explain why for each one.

๐Ÿ”ง Troubleshooting Link to heading

Problem: Claude doesn’t see Gmail Link to heading

Solution:

# Check the config
claude mcp list

# If empty, redo:
claude mcp add gmail /usr/bin/node ~/my-email-assistant/server.js

Problem: “Token expired” Link to heading

Solution:

# Delete the token
rm ~/.config/gmail-assistant/creds/token.json

# Restart Claude
claude
# The authorization process starts again

Problem: “Permission denied” Link to heading

Solution:

# Check permissions
chmod 600 ~/.config/gmail-assistant/creds/credentials.json
chmod +x ~/my-email-assistant/server.js

๐Ÿ’ก Tips and Tricks Link to heading

Make Claude More Effective Link to heading

Be specific:

  • โŒ “Find my emails”
  • โœ… “Find this week’s emails with ‘project’ in the subject”

Ask for formats:

List my emails in table format with:
- Date
- Sender
- Short subject

Iterate:

First request: "List my emails from today"
Refinement: "Now, show only those from client X"

Create Routines Link to heading

Morning routine:

Give me my email briefing for the day:
1. Total number of new emails
2. Top 3 most important ones
3. Those that require a quick response
4. Newsletters to read later

Format: concise and actionable

Friday routine:

Week summary:
- What topics came up often?
- Who emailed me the most?
- Are there any unanswered emails?

โœ… Final Checklist Link to heading

You succeeded if:

  • Project created on Google Cloud
  • Gmail API enabled
  • OAuth configured (read-only only)
  • Credentials downloaded and secured
  • MCP server installed
  • Claude connected (claude mcp list works)
  • First test successful (email list)
  • You know how to revoke access if needed

๐ŸŽ‰ Congratulations! Link to heading

You’ve created your own email analysis assistant with AI!

You now know how to:

  • โœ… Configure the Gmail API in read-only mode
  • โœ… Connect Claude Code to your emails
  • โœ… Analyze your emails with artificial intelligence
  • โœ… Control access and security

Next steps:

  1. Experiment with different prompts
  2. Create your own routines
  3. Share your discoveries

Need help?


Author: Xavier GUERET & claude Date: January 18, 2025 License: MIT

Tags: #tutorial #claude-code #gmail #ai #automation #beginner


This tutorial shows you how to access your own Gmail data securely. Always respect others’ privacy and the terms of service of the services.