DEV Community

Cover image for I Built a Mental Health Journal Using MCP, Claude Desktop and NVIDIA NIM — Here's How
Isaac Natarajan
Isaac Natarajan

Posted on

I Built a Mental Health Journal Using MCP, Claude Desktop and NVIDIA NIM — Here's How

I've been exploring Model Context Protocol (MCP) recently and wanted to build something that was actually useful in my day-to-day life — not just another todo app or weather tool.

Mental health journaling is something I've always wanted to be consistent with, but the friction of opening an app, typing out my thoughts in a structured way, and then getting no real feedback always stopped me.

So I built a Mental Health Journal MCP — where I just talk to Claude naturally about my day and it handles everything else automatically. Logging, detecting cognitive distortions, tracking mood trends, suggesting coping strategies — all from a single conversation.
Here's the full story of how I built it.

What is MCP?
Before diving in, let me quickly explain Model Context Protocol (MCP) for those who haven't heard of it.

MCP is an open protocol by Anthropic that lets you connect AI models like Claude to external tools and data sources. Think of it like giving Claude the ability to call functions — read from a database, call an API, write files — anything you want.

You build an MCP server that exposes a set of tools, and an MCP client (like Claude Desktop) connects to it and uses those tools automatically during conversation.

It's a game changer for building AI-powered personal tools.

The Problem I Wanted to Solve
Traditional journaling apps require:

  • Opening an app
  • Filling structured forms (date, mood, text)
  • Getting no intelligent feedback

I wanted to just say:

I had a really stressful day today, kept worrying about my project deadlines and felt like everything was falling apart.

And have the system:

  1. Log the entry automatically
  2. Detect thinking patterns (cognitive distortions)
  3. Suggest coping strategies
  4. Track my mood over time

That's exactly what this project does.

Architecture

Claude Desktop (MCP Client)
        ↓
MCP Server (Python + FastMCP)
        ↓
NVIDIA NIM — meta/llama-4-maverick-17b-128e-instruct (AI Judge)
        ↓
SQLite (Local Storage)
Enter fullscreen mode Exit fullscreen mode

The key design decision here is the dual-model pattern:

  • Claude handles the conversational layer — empathy, responses, deciding which tool to call
  • NVIDIA NIM (Llama 4 Maverick) acts as the AI judge — focused tasks like detecting cognitive distortions and generating reports

This keeps each model doing what it's best at.

Tools I Built

Tool What it does
log_journal_entry Logs date, text, and mood score to SQLite
detect_cognitive_distortions Uses Llama 4 Maverick to analyze thinking patterns
analyze_mood_trends Queries database and calculates mood statistics over a date range
get_stress_triggers Identifies low mood entries and uses AI to detect patterns
suggest_coping_strategy Generates personalized coping advice using AI
generate_weekly_report Creates a full weekly mental health summary
set_intention Sets a daily intention
check_intention_reflection Reflects on how well the intention was followed

Setting Up the Project

Dependencies

mkdir mental-health-journal-mcp
cd mental-health-journal-mcp
python -m venv venv
venv\Scripts\activate
pip install uv
uv pip install mcp httpx python-dotenv
Enter fullscreen mode Exit fullscreen mode

Database Setup (db.py)

import sqlite3
import os

DB_PATH = os.path.join(os.path.dirname(__file__), "data", "journal.db")

def get_connection():
    os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    return conn

def init_db():
    conn = get_connection()
    cursor = conn.cursor()

    cursor.executescript("""
        CREATE TABLE IF NOT EXISTS journal_entries (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            date TEXT NOT NULL,
            text TEXT NOT NULL,
            mood_score INTEGER NOT NULL,
            distortions TEXT,
            triggers TEXT,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        );

        CREATE TABLE IF NOT EXISTS intentions (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            date TEXT NOT NULL,
            intention TEXT NOT NULL,
            reflection TEXT,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        );
    """)

    conn.commit()
    conn.close()
Enter fullscreen mode Exit fullscreen mode

Building the MCP Server

Server Skeleton (server.py)

from mcp.server.fastmcp import FastMCP
from db import init_db, get_connection
from dotenv import load_dotenv
import httpx
import os

load_dotenv()
init_db()

mcp = FastMCP("Mental Health Journal")
Enter fullscreen mode Exit fullscreen mode

Logging Journal Entries

@mcp.tool()
def log_journal_entry(date: str, text: str, mood_score: int) -> str:
    """Log a journal entry with date, text and mood score (1-10)"""

    if not 1 <= mood_score <= 10:
        return "Mood score must be between 1 and 10"

    conn = get_connection()
    cursor = conn.cursor()

    cursor.execute("""
        INSERT INTO journal_entries (date, text, mood_score)
        VALUES (?, ?, ?)
    """, (date, text, mood_score))

    conn.commit()
    conn.close()

    return f"Journal entry logged for {date} with mood score {mood_score}/10"

Enter fullscreen mode Exit fullscreen mode

Detecting Cognitive Distortions (The AI Judge)

This is where it gets interesting. I use NVIDIA NIM's Llama 4 Maverick as a focused AI judge to analyze journal text:

@mcp.tool()
def detect_cognitive_distortions(entry_text: str) -> str:
    """Analyze journal entry text and detect cognitive distortions using AI"""

    api_key = os.getenv("NVIDIA_API_KEY")

    prompt = f"""You are a cognitive behavioral therapy expert. Analyze this journal entry and detect any cognitive distortions present.

Journal entry: {entry_text}

List the cognitive distortions found (e.g. catastrophizing, all-or-nothing thinking, mind reading, overgeneralization etc.) and briefly explain why. Be concise and empathetic."""

    response = httpx.post(
        "https://integrate.api.nvidia.com/v1/chat/completions",
        headers={"Authorization": f"Bearer {api_key}"},
        json={
            "model": "meta/llama-4-maverick-17b-128e-instruct",
            "messages": [{"role": "user", "content": prompt}],
            "max_tokens": 300
        }
    )

    return response.json()["choices"][0]["message"]["content"]
Enter fullscreen mode Exit fullscreen mode

Here's a real output I got:

I've identified two cognitive distortions: Catastrophizing — expecting the worst-case scenario without considering other outcomes. Fortune Telling — predicting future failure without concrete evidence.

That's genuinely useful feedback from a journal entry.

Making it Feel Natural

The real magic happens with a system prompt in Claude Desktop. I created a Project and added these instructions:

You are a compassionate mental health journal assistant.
When the user shares how they are feeling or talks about their day:

  1. Always automatically log a journal entry using the log_journal_entry tool with today's date
  2. If the user doesn't mention a mood score, estimate it from their tone (1-10)
  3. After logging, automatically run detect_cognitive_distortions on their entry
  4. Respond empathetically and suggest coping strategies if mood score is 4 or below When the user asks about their mood, week, patterns or triggers:
  5. Use analyze_mood_trends, get_stress_triggers or generate_weekly_report automatically Always be warm, non-judgmental and supportive.

Now I just talk naturally and everything happens automatically. No commands, no forms, no friction.

Connecting to Claude Desktop

Add this to your claude_desktop_config.json:

{
  "mcpServers": {
    "mental-health-journal": {
      "command": "C:\\path\\to\\venv\\Scripts\\python.exe",
      "args": ["C:\\path\\to\\server.py"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

On Windows the config file is located at:

C:\Users\<username>\AppData\Local\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.json
Enter fullscreen mode Exit fullscreen mode

Restart Claude Desktop and your tools show up automatically.

What I Learned

1. MCP is incredibly powerful for personal tools — the ability to give Claude access to your own data and functions opens up so many possibilities.
2. The dual-model pattern works well — using a lighter, focused model (Llama 4 Maverick) for specific analysis tasks keeps things efficient and consistent.
3. System prompts are the UX layer — the difference between a tool that feels robotic and one that feels natural is entirely in how you prompt the client model.
4. SQLite is underrated — for personal local tools, SQLite is perfect. Zero setup, fast, private.

Source Code

The full source code is available on GitHub: https://github.com/IsaacNatarajan/Mental-Health-Journal/

If you're exploring MCP and want to build something practical, I highly recommend starting with a personal tool like this. The feedback loop of actually using what you build makes learning so much faster.

Have questions or want to share what you're building with MCP? Drop a comment below! 👇

Top comments (0)