A remote MCP server that turns Claude into a personal assistant — tracks habits, tasks, finances, goals, documents, and memory with semantic search. Built on OAuth 2.0 + PKCE, deployed serverless on Vercel with 41 MCP tools across 6 domains.
41 MCP tools across Habits, Tasks, Finance, Goals, Documents, and Memory
OAuth 2.0 with PKCE (S256) for secure remote MCP client authentication
Hybrid semantic + full-text search on memories using pgvector and GIN indexes
Duplicate memory detection at 0.9 cosine similarity threshold
Document wallet with chunked embeddings (OpenAI text-embedding-ada-002, 1536 dims)
Habit streak tracking and completion analytics with IST-aware date handling
Spending categorization with uncategorized-transaction surfacing
Goal tracking with milestone sub-steps and progress reviews
Stateless serverless architecture — new MCP instance per request
SHA-256 hashed OAuth tokens, service-role Supabase access server-side
Dashboard UI for all 6 domains alongside MCP access
MCP protocol typically assumes persistent connections, but Vercel functions can't hold state between requests. Built a fresh MCP server instance on every POST /api/mcp call — no module-level state, no singletons — so it scales horizontally with zero warm-up coupling.
Claude.ai and other MCP clients require OAuth for remote servers — no API key auth. Implemented full /oauth/authorize, /token, /register, /revoke flow with PKCE S256, and SHA-256 hashed tokens in Supabase so raw tokens never hit the DB.
Pure vector search missed exact keyword hits like names, dates, and IDs. Built a pa_hybrid_search RPC combining pgvector cosine similarity with Postgres full-text search over a GIN-indexed search_vector column, giving the best of both worlds.
Sathi coexists with an earlier memory-mcp server on the same Supabase instance. Namespaced every Sathi table with a pa_ prefix (pa_memory_items, pa_memory_spaces, pa_memory_access_log) to keep schemas isolated and migrations conflict-free.
Streaks and daily filters kept going off-by-one because server default was UTC. Standardized everything on Asia/Kolkata via IST helpers in types/index.ts — all display, filtering, and habit-completion logic now uses IST consistently.
Next.js 16 + Supabase (pgvector) + MCP SDK + OAuth 2.0 PKCE, deployed on Vercel serverless
Next Project