Thaddeus
A local, JARVIS-style personal assistant that orchestrates custom MCP servers for memory, calendar, weather, Notion, Claude Code, web search, and Strava, running primarily offline with Ollama.
README
Thaddeus
A local, JARVIS-style personal assistant, developed by Thach Ngo (Thomas Ngo). Its mission is to run fully locally and boost working efficiency and productivity. A Python orchestrator drives a local Ollama model (Qwen2.5 32B, tool-calling) which calls out to custom MCP servers over stdio for memory, calendar/reminders, weather, Notion task tracking, Claude Code delegation (planning/implementation/review), web search, IELTS grading/practice question generation, and running (Strava data + a local race tracker).
Privacy / network boundary
Most of this runs fully locally — Ollama inference, SQLite memory, macOS Calendar/Reminders access via AppleScript. Several servers are explicit, accepted exceptions that reach the network:
- weather — plain HTTPS GET to open-meteo.com, no API key, no personal data (just coordinates or a city name).
- notion — talks to the Notion API with your integration token, to read and manage your task database.
- claude — the one server that reaches an LLM in the cloud (Anthropic's
API via the
claudeCLI). Every call runs with--permission-mode planfor read-only tasks oracceptEdits+ an explicit git push/commit denylist forimplement_from_plan— verified live, never commits or pushes regardless of what's asked. - web_search — queries a self-hosted SearXNG instance (see
searxng/). No API key or account of yours reaches a third party, but SearXNG itself still queries upstream engines (Google, Bing, etc.) over the network to gather results, as any metasearch aggregator does. Two alternatives were tried and rejected: Brave Search API requires a credit card on file even for its free tier, and Google's Custom Search API is closed to new signups as of 2025.
notion and claude degrade gracefully — if their .env secret isn't
set, that one server is skipped with a warning and everything else still
starts fine. web_search needs no secret, but does need the SearXNG
container actually running.
strava is fully local — it reads your own free personal data export
(activities.csv) rather than calling Strava's live API, since that now
costs $11.99/month for Standard-tier access (confirmed June 2026 policy
change). Not real-time; re-export periodically from Strava's account
settings to refresh. Its race tracker and find_races (web search for
candidate upcoming races, since Strava's API never had race data even
before the paywall) work with no Strava export at all.
Strava export automation
Requesting the export itself needs a live logged-in Strava browser session,
so that part can't be automated — but everything after you download the
ZIP can be. A LaunchAgent (scripts/install_strava_automation.sh) runs
scripts/strava_automation.py daily, which:
- watches
~/Downloadsfor a Strava export ZIP (detected by checking foractivities.csvinside it, not by guessing Strava's exact filename) and auto-extracts it todata/strava_export/— no manual unzip/move step - creates a Reminders.app reminder every ~14 days nudging you to go re-request the export, since that step still needs you
Both halves are idempotent (tracked via marker files in data/), so the
daily run is a no-op on days there's nothing to do. Uninstall:
launchctl bootout gui/$(id -u)/com.thachngo.thaddeus.strava-automation
then remove the plist from ~/Library/LaunchAgents/.
Setup
ollama serve(if not already running), then pull a tool-calling-capable Qwen2.5 32B build (seeOLLAMA_MODELin.envfor the exact tag in use)python3 -m venv .venv && source .venv/bin/activatepip install -e ".[dev]"cp .env.example .envand fill inWEATHER_DEFAULT_LAT/WEATHER_DEFAULT_LONpython scripts/sanity_check_sdk.py— confirms the installedmcpSDK's actual API surface before anything else is built against itpython scripts/init_db.pycd searxng && docker compose up -d && cd ..— starts the local search backend (one-time; it stays running across restarts)- Optional, for running tools beyond the race tracker: request a Strava
data export (account Settings > My Account > Download or Delete Your
Account > Request Your Archive), extract it to
data/strava_export/once it arrives by email, thenpython scripts/inspect_strava_export.pyto sanity-check the real column names/units against whatstrava_server.pyassumes python -m orchestrator.main
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.