Skip to main content
Glama
saipavanbg

mcp-integrated-ai-assistant

by saipavanbg
README.md
# AI Assistant — Merged Project (Chrono + AI-MCP-ASSISTANT)

## Merge notes (read this first)

This project is the result of merging two separate projects into one app:

1. **`fastmcp_ai_assistant_updated`** ("Chrono") — the base of this merge.
   Clock, stopwatch, alarms, reminders, sign-in/sign-up, email
   notifications, profile management, and product-price comparison.
2. **`AI-MCP-ASSISTANT`** ("mcp-assistant") — contributed three tools that
   didn't exist in Chrono, now merged into this codebase:
   - **YouTube search** (`tools/youtube_tool.py`) — YouTube Data API v3.
   - **AI trip planner** (`tools/trip_planner_tool.py` + `tools/serp_service.py`)
     — real flights/hotels/places via SerpAPI, formatted into a day-wise
     itinerary by Groq.
   - **Notes** (`tools/notes_tool.py`) — add / delete / list / summarize
     (summarization via Groq), using this project's existing `sqlite3` +
     `server/utils.connect_db` pattern, so no new DB dependency was added.

**Search**: the merged app keeps *Chrono's* SerpAPI-based `google_search`
(`tools/search_tool.py`) as the one and only search tool. AI-MCP-ASSISTANT's
DuckDuckGo-based search (`ddgs` library) was **not** carried over, to avoid
having two different, inconsistent search implementations side by side.

**What was intentionally left behind / not merged**, to keep a single,
consistent architecture instead of running two backends side by side:
- AI-MCP-ASSISTANT's separate Node/Express backend and Flask API
  (`backend/server.js`, `server/api.py`) — this project already has a
  single FastAPI backend (`server/api_server.py`) that both the React
  frontend and the FastMCP tool server call into; the new tools were
  added there instead of standing up a second backend stack.
- AI-MCP-ASSISTANT's Gemini-based MCP Host/Client CLI
  (`host/main.py`, `client/mcp_client.py`) — this project's own
  `server/server.py` (FastMCP) already serves the same purpose (exposing
  tools to any MCP-speaking LLM client), just with a different LLM/client
  pattern (Groq for trip-planner/notes formatting instead of Gemini for
  tool-selection). The new tools were added as `@mcp.tool()`s there.
- The "History" activity-feed page/table from AI-MCP-ASSISTANT was
  replaced by this project's existing per-feature history tables in
  `database/history.db` (`search_history`, plus new `youtube_history` and
  `trip_history` tables added during the merge).

---

## 1. Features at a glance

| Area | What it does |
|---|---|
| **Clock** | Live clock card. Tapping it opens a slide-in **sidebar** with Stopwatch and Alarm (they're intentionally *not* in the top ribbon — see below). |
| **News panel** | Sits right under the clock card. Shows today's top headlines (NewsAPI, with an automatic Google News RSS fallback that needs no API key). |
| **Stopwatch / Alarm** | Live only inside the clock's sidebar now — custom ringtones, repeat, weekdays, snooze. |
| **Reminders** | Title/description/date/time, "notify" options, full-screen alert + email when due. |
| **Sign up / Sign in / Forgot password** | Email+password auth (PBKDF2 hashed). Forgot-password verifies identity via name+email match (no OTP system), then lets you set a new password. |
| **Profile** (Settings → *Edit profile*) | **GET** current profile, **PUT** to edit name/email/password, **DELETE** with two modes: **soft** (status flips to `deleted`, data kept) and **hard** (user + all their alarms/reminders permanently erased). |
| **Search** | SerpAPI-backed web search. |
| **Compare** | Two-product side-by-side price comparison (SerpAPI). |
| **YouTube** | Search YouTube videos (YouTube Data API v3). |
| **Trip planner** | Origin/destination/days → real flights/hotels/places (SerpAPI) formatted into an itinerary (Groq). |
| **Notes** | Add / list / delete / AI-summarize notes (Groq). |
| **About** | Header button (top-right, next to your name) — project summary. |
| **Settings** | Account info, "Edit profile" (opens the Profile modal), sign out, and a **Send test email** button to verify email delivery instantly. |

### Header / navigation layout
The top ribbon tabs are: `Clock · Reminder · Search · Compare · YouTube ·
Trip planner · Notes · Settings`. **Stopwatch and Alarm are not ribbon
tabs** — they live inside the sidebar opened by tapping the clock. **About**
is a small button in the top-right corner of the header, next to your
signed-in name. **Profile** is not a ribbon tab either — it opens as a
modal from the **Settings** tab ("Edit profile" button).

---

## 2. Backend setup

```bash
# from the project root
python -m venv venv
venv\Scripts\activate        # Windows
# source venv/bin/activate   # macOS/Linux

pip install -r requirements.txt

# create/upgrade the sqlite databases (safe to re-run any time)
python server/init_db.py
```

No new pip packages were needed for sign-in — it uses only Python's
standard library (`hashlib`, `secrets`).

### `.env` file (project root)

There's no checked-in `.env.example` in this copy of the project — create a
plain text file named **`.env`** in the project root yourself with the
variables below (only fill in the ones for features you want working;
everything else degrades gracefully instead of crashing):

```
# ---- Search / price comparison ----
SERPAPI_KEY=your_serpapi_key

# ---- YouTube search ----
YOUTUBE_API_KEY=your_youtube_data_api_v3_key

# ---- Trip planner itinerary + notes summarization ----
GROQ_API_KEY=your_groq_key

# ---- News under the clock (optional - falls back to Google News RSS,
#      which needs no key at all, if this is left blank) ----
NEWSAPI_KEY=
NEWS_COUNTRY=in

# ---- Email: configure Resend AND/OR SMTP - see note below ----
RESEND_API_KEY=re_your_key_here
RESEND_FROM_EMAIL=onboarding@resend.dev

SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_USER=your_email@gmail.com
SMTP_PASSWORD=your_16_character_app_password
SMTP_FROM_NAME=Chrono Assistant
```

**How email backend selection actually works** (`server/email_service.py`):
Resend is tried first (it sends over plain HTTPS/443, so it works even on
networks that block SMTP ports). On Resend's free tier without a verified
domain, Resend only delivers to the address you personally signed up to
Resend with — every other recipient gets a 403 "testing mode" rejection.
When that specific rejection happens **and** SMTP is also configured, the
code automatically retries that email via SMTP instead — so if you want
every signed-up user to get alerts at *their own* inbox (not just yours),
configure both, or configure SMTP alone.

**Setting up Resend (2 minutes, no credit card):** sign up free at
https://resend.com → Dashboard → API Keys → create one → paste as
`RESEND_API_KEY`.

**Setting up Gmail SMTP:** Google Account → Security → 2-Step Verification
(turn on) → App passwords → generate one → paste that 16-character value
into `SMTP_PASSWORD`. If port 465 times out, try `SMTP_PORT=587` (the app
automatically switches to STARTTLS for any non-465 port).

If neither Resend nor SMTP is configured, the app still works exactly the
same (in-app full-screen alert + sound) — it just skips the email step and
prints a warning in the terminal instead of crashing.

### How to verify email is actually working (don't wait for a real alarm!)

1. Start the backend: `python -m server.api_server`.
2. In the frontend, sign in → **Settings** tab.
3. Click **"Send test email"** (`POST /api/test-email`) — emails your
   signed-in address immediately and shows the exact success/error message
   on screen.
4. Once the test email arrives, alarms and reminders will email you the
   same way automatically when they trigger.

**Windows Notepad users:** if you get "not configured" even after filling
in `.env` correctly, Notepad may have saved the file as UTF-16, which
python-dotenv can't read. Fix it in PowerShell:
```powershell
(Get-Content .env -Raw) | Out-File -FilePath .env -Encoding ascii -NoNewline
```

### Run the backend

```bash
python -m server.api_server
```

This starts on **http://127.0.0.1:8000**. Leave this terminal running.

---

## 3. REST API reference (`server/api_server.py`)

### Auth & profile
| Method | Path | Purpose |
|---|---|---|
| POST | `/api/auth/signup` | `{name, email, password}` → creates account, auto signs in, returns `{token, user}` |
| POST | `/api/auth/login` | `{email, password}` → `{token, user}` |
| POST | `/api/auth/logout` | Invalidates the current token |
| POST | `/api/auth/forgot-password` | `{name, email, new_password}` → identity check via name+email match, then resets password and signs out all sessions |
| GET | `/api/auth/me` | Resolves the current token back to a user |
| POST | `/api/test-email` | Sends a test email to the signed-in user right now |
| GET | `/api/profile` | Current user's profile |
| PUT | `/api/profile` | `{name?, email?, password?}` → update any subset of fields |
| DELETE | `/api/profile?mode=soft\|hard` | `soft` (default): flips `status` to `deleted`, keeps all data. `hard`: permanently deletes the user + all their alarms/reminders |

### Clock, alarms, reminders
| Method | Path | Purpose |
|---|---|---|
| GET | `/api/time` | Current server time |
| GET | `/api/meta` | Sound options, etc. for the frontend |
| POST/GET | `/api/stopwatch/start`, `/stop`, `/delete`, `GET /status` | Stopwatch control (single shared instance) |
| POST | `/api/alarms` | Create an alarm (requires sign-in) |
| GET | `/api/alarms` | List your own alarms |
| DELETE | `/api/alarms/{id}` | Delete your own alarm |
| POST | `/api/alarms/{id}/stop` | Stop a ringing alarm |
| POST | `/api/alarms/{id}/snooze` | Snooze a ringing alarm |
| POST | `/api/reminders` | Create a reminder (requires sign-in) |
| GET | `/api/reminders` | List your own reminders |
| DELETE | `/api/reminders/{id}` | Delete your own reminder |
| POST | `/api/reminders/{id}/stop` | Dismiss a due reminder |
| POST | `/api/reminders/{id}/remind_later` | Snooze a reminder |
| GET | `/api/notifications` | Polled every second by the frontend for due alarms/reminders |

### News, search, compare, YouTube, trip planner, notes
| Method | Path | Purpose |
|---|---|---|
| GET | `/api/news` | Today's top headlines for the Clock page's News panel |
| POST | `/api/search` | Web search (SerpAPI) |
| POST | `/api/ecommerce` | Single-product price search |
| POST | `/api/ecommerce/compare` | `{product1, product2}` → both products' results side by side |
| GET | `/api/youtube?query=...&max_results=5` | YouTube search |
| POST | `/api/trip-planner` | `{origin, destination, days, departure_date?}` → itinerary |
| GET | `/api/notes` | List notes |
| POST | `/api/notes` | `{title?, content}` → add a note |
| DELETE | `/api/notes/{id}` | Delete a note |
| POST | `/api/notes/summary` | `{note_ids?}` → AI summary of notes |

**Access notes:** `/api/time`, `/api/stopwatch/*`, `/api/search`,
`/api/ecommerce*`, `/api/news`, `/api/youtube`, `/api/trip-planner` are open
(no sign-in required). Alarms, reminders, and profile endpoints require an
`Authorization: Bearer <token>` header, since that's who gets emailed and
whose data it is.

MCP tools exposed by `server/server.py`: `youtube_search`, `trip_planner`,
`notes_add`, `notes_delete`, `notes_list`, `notes_summarize`, plus the
original clock/alarm/reminder/search/ecommerce tools.

---

## 4. Frontend setup

```bash
cd frontend
npm install
npm run dev
```

Open **http://localhost:5173**.

### Frontend structure

```
frontend/src/
  api.js                     -> fetch() wrapper; auto-attaches the auth token
  context/AuthContext.jsx    -> signup/login/logout state, persisted in localStorage
  App.jsx                    -> Sign in/up/Forgot-password when logged out; main app when logged in
  components/
    SignInPage.jsx             -> email + password (+ "Forgot password?" link)
    SignUpPage.jsx              -> name + email + password -> auto signs in
    ForgotPasswordPage.jsx       -> name + email + new password -> resets & signs out old sessions
    Header.jsx                    -> ribbon tabs + "About" button + signed-in name
    ClockPage.jsx                   -> rotating-ring clock card, tap to open the sidebar; renders NewsPanel below it
    NewsPanel.jsx                    -> today's headlines under the clock
    Sidebar.jsx                       -> slide-in panel (opened from the clock) holding Stopwatch + Alarm
    StopwatchPage.jsx                  -> HH:MM:SS:MS input, live countdown (lives in the sidebar)
    AlarmPage.jsx                       -> HH:MM AM/PM, repeat, weekdays, sound, list (lives in the sidebar)
    ReminderPage.jsx                     -> title/description/date/time, notify dropdown, list
    SearchPage.jsx                        -> query box -> tools/search_tool.py
    EcommercePage.jsx                      -> TWO product boxes -> side-by-side price compare
    YouTubePage.jsx                         -> query box -> tools/youtube_tool.py
    TripPlannerPage.jsx                      -> origin/destination/days -> tools/trip_planner_tool.py
    NotesPage.jsx                             -> add/list/delete/summarize -> tools/notes_tool.py
    AboutPage.jsx                              -> project summary (opened via the header's About button)
    ProfilePage.jsx                             -> GET/PUT/DELETE profile modal (opened from Settings)
    SettingsPage.jsx                             -> account info, "Edit profile", sign out, send-test-email
    AlertOverlay.jsx                              -> full-screen alert (Stop/Delete, Snooze, Remind later)
```

---

## 5. Quick demo checklist

1. `python server/init_db.py` then `python -m server.api_server`
2. `cd frontend && npm run dev`
3. Open http://localhost:5173 → you land on **Sign up** → create an
   account → you're redirected straight into the app.
4. Tap the **clock** → sidebar slides in with Stopwatch/Alarm tabs.
5. Scroll down on the Clock page → today's news headlines appear below it.
6. Go to **Settings** → **Edit profile** → try updating your name, then try
   both delete modes (soft vs hard) on a throwaway test account.
7. Set an alarm 1–2 minutes in the future. If `.env` has valid email
   settings, check that inbox when it rings.
8. Go to **Compare**, type two product names, click *Compare prices* — both
   products' results appear side by side.
9. Try **YouTube**, **Trip planner**, and **Notes** tabs.
10. Click **About** (top-right of the header) to see the project summary.