Your personal knowledge layer — one API for everything you've ever touched.
Connect Gmail, Drive, Calendar, GitHub, Notion, Spotify, and Slack into a single searchable, chat-ready platform with real-time sync, vector search, and MCP tool support.
Live Demo · API Docs · MCP Health · Report Bug
- Overview
- Architecture
- Features
- Tech Stack
- Getting Started
- Configuration
- API Reference
- Data Model
- Workers & Queues
- Testing
- Production Checklist
- Troubleshooting
- Contributing
- Team
Personal data is fragmented across dozens of apps. PersonalAPI solves this by providing a unified ingestion, indexing, and retrieval layer over your connected services — exposing it all through clean REST APIs, a chat interface, real-time WebSocket notifications, and an MCP tool server for AI clients like Claude.
You ask: "What did I discuss with Ansh last Tuesday?"
PersonalAPI: searches Gmail + Slack + Calendar → returns a grounded answer with citations
| Capability | Description |
|---|---|
| Multi-source ingestion | OAuth + token-based connectors for 7 platforms |
| Unified item model | Normalized schema across all sources |
| Hybrid retrieval | pgvector (semantic) + pg_trgm (lexical) search |
| Chat with citations | RAG-powered responses grounded in your data |
| Real-time sync | Queue-based workers with WebSocket push notifications |
| Developer APIs | API key management for programmatic access |
| MCP server | First-class tool server for external AI clients |
flowchart LR
FE[Next.js Dashboard] --> API[FastAPI API]
MCPClient[External MCP Client] --> MCP[MCP Sub-Application]
MCP --> API
API --> PG[(PostgreSQL\npgvector · pg_trgm)]
API --> REDIS[(Redis\nBroker · Cache)]
API --> WS[WebSocket Channel]
API --> CELERY[Celery Router]
CELERY --> WG[Google Worker]
CELERY --> WGH[GitHub Worker]
CELERY --> WN[Notion Worker]
CELERY --> WSPO[Spotify Worker]
CELERY --> WSL[Slack Worker]
CELERY --> WFW[File Watcher]
CELERY --> WEMB[Embedding Worker]
CELERY --> WBEAT[Beat Scheduler]
WG --> GAPI[Google APIs]
WGH --> GHAPI[GitHub API]
WN --> NAPI[Notion API]
WSPO --> SAPI[Spotify API]
WSL --> SLAPI[Slack API]
WG & WGH & WN & WSPO & WSL & WFW --> FS[User Storage\nFilesystem]
WFW & WEMB --> PG
1. User authenticates → connects external service via OAuth / token
2. Backend stores connector metadata + provider credentials
3. Sync task is dispatched to platform-specific Celery queue
4. Worker fetches records → normalizes → writes user files → upserts items
5. File Watcher + Embedding workers chunk text and generate vector embeddings
6. Search, Chat, Dashboard, and MCP clients query the indexed data
🔌 Connectors
| Platform | Auth | Notes |
|---|---|---|
| Gmail | OAuth 2.0 | Full email ingestion |
| Google Drive | OAuth 2.0 | Document sync |
| Google Calendar | OAuth 2.0 | Events and scheduling |
| GitHub | OAuth 2.0 | Repos, issues, PRs with webhook matching |
| Notion | OAuth + token | Pages and databases |
| Spotify | OAuth 2.0 | Listening history with refresh-token handling |
| Slack | OAuth 2.0 | Messages and channels |
🔍 Search & Retrieval
- Hybrid search — pgvector for semantic similarity + pg_trgm for fuzzy text matching
- Chunked indexing — documents split into retrieval-ready chunks with embeddings
- Source citations — every answer includes traceable source references
- Related documents — surfaced alongside chat responses
💬 Chat
- Session-based multi-turn conversations
- Grounded answers with source entries and file links
- Configurable LLM backend (local or remote via
RAG_LLM_*settings)
⚡ Real-time
- JWT-authenticated WebSocket channel per user
- Events:
connection,sync_started,sync_completed,sync_failed
🛠 MCP Server
Mountable as a sub-app or run standalone on port 8001. Developer-key authenticated.
| Tool | Description |
|---|---|
search |
Semantic + lexical search over indexed items |
ask |
RAG-powered question answering |
get_item |
Fetch a specific item by ID |
list_connectors |
List connected services for a user |
get_profile |
Retrieve user profile information |
| Layer | Technology |
|---|---|
| Framework | FastAPI, Pydantic v2 |
| ORM | SQLAlchemy + psycopg |
| Task queue | Celery + Redis |
| Vector search | pgvector |
| Text search | pg_trgm |
| HTTP client | httpx |
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| UI | React 19, Tailwind CSS 4 |
| State | TanStack Query |
| HTTP | Axios |
| Language | TypeScript |
| Component | Technology |
|---|---|
| Database | PostgreSQL 16 |
| Cache / Broker | Redis 7 |
| Containerization | Docker + Compose |
| Tool | Minimum Version |
|---|---|
| Python | 3.11 |
| Node.js | 20 |
| PostgreSQL | 16 (with pgvector + pg_trgm) |
| Redis | 7 |
| Docker Desktop | Latest (optional, recommended) |
git clone https://github.com/const-nishant/personalapi.git
cd personalapicd backend
python -m venv .venv
# macOS / Linux
source .venv/bin/activate
# Windows PowerShell
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txtCopy and populate the environment file:
cp .env.example .env
# Edit .env with your credentials — see Configuration sectionRun database migrations:
psql -U postgres -h localhost -d personalapi -f migrations/001_initial.sql
psql -U postgres -h localhost -d personalapi -f migrations/002_item_chunks.sqlStart the API:
uvicorn api.main:app --reload --host 0.0.0.0 --port 8000cd frontend
npm install
npm run dev# Google connector
celery -A workers.celery_app:celery_app worker --loglevel=INFO \
--queues=connector.google --hostname=worker-google@%h
# GitHub connector
celery -A workers.celery_app:celery_app worker --loglevel=INFO \
--queues=connector.github --hostname=worker-github@%h
# Notion connector
celery -A workers.celery_app:celery_app worker --loglevel=INFO \
--queues=connector.notion --hostname=worker-notion@%h
# Spotify connector
celery -A workers.celery_app:celery_app worker --loglevel=INFO \
--queues=connector.spotify --hostname=worker-spotify@%h
# Slack connector
celery -A workers.celery_app:celery_app worker --loglevel=INFO \
--queues=connector.slack --hostname=worker-slack@%h
# File watcher pipeline
celery -A workers.celery_app:celery_app worker --loglevel=INFO \
--queues=pipeline.file-watcher --hostname=worker-file-watcher@%h
# Embedding pipeline
celery -A workers.celery_app:celery_app worker --loglevel=INFO \
--queues=pipeline.embedding --hostname=worker-embedding@%h
# Beat scheduler (auto-sync)
celery -A workers.celery_app:celery_app beat --loglevel=INFO| Endpoint | Expected |
|---|---|
http://localhost:3000 |
Frontend dashboard |
http://127.0.0.1:8000/health |
{"status": "ok"} |
http://127.0.0.1:8000/health/llm |
LLM backend status |
http://127.0.0.1:8000/docs |
Swagger UI |
http://127.0.0.1:8000/mcp/health |
MCP server status |
The full backend stack (API + all workers + DB + Redis) is orchestrated via Compose.
cd backend
docker compose up --buildServices started:
db · redis · api · worker-google · worker-github · worker-notion · worker-spotify · worker-slack · worker-file-watcher · worker-embedding · worker-beat
Hybrid mode — Docker for infrastructure only, Python processes run locally:
cd backend
docker compose up -d db redisStandalone MCP server:
uvicorn mcp.server:app --host 0.0.0.0 --port 8001 --reloadAll configuration is managed via environment variables or a .env file. A template is provided at backend/.env.example.
| Variable | Description | Default |
|---|---|---|
APP_NAME |
Application name | PersonalAPI |
APP_VERSION |
API version string | — |
API_PREFIX |
Route prefix | /v1 |
DEBUG |
Enable debug mode | false |
CORS_ORIGINS |
Allowed frontend origins (comma-separated) | — |
FRONTEND_APP_URL |
Frontend base URL | — |
USER_DATA_ROOT |
Root path for user file storage | — |
ENABLE_INLINE_SYNC_FALLBACK |
Fallback sync mode flag | false |
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
DATABASE_SSL_MODE |
disable / require (use require in production) |
DATABASE_CONNECT_TIMEOUT |
Connection timeout in seconds |
REDIS_URL |
Redis connection string |
AUTO_SYNC_ENABLED |
Enable Celery beat auto-sync |
| Variable | Description |
|---|---|
SECRET_KEY |
JWT signing secret — replace immediately |
ALGORITHM |
JWT algorithm (HS256) |
ACCESS_TOKEN_EXPIRE_MINUTES |
Token TTL |
| Variable | Description |
|---|---|
RAG_LLM_ENABLED |
Enable LLM-powered chat responses |
RAG_LLM_PROVIDER |
LLM provider identifier |
RAG_LLM_BASE_URL |
Provider base URL |
RAG_LLM_MODEL |
Model name |
RAG_LLM_TIMEOUT_SECONDS |
Request timeout |
RAG_LLM_TEMPERATURE |
Sampling temperature |
RAG_LLM_MAX_TOKENS |
Max tokens per response |
| Variable | Description |
|---|---|
GOOGLE_CLIENT_ID |
OAuth 2.0 client ID |
GOOGLE_CLIENT_SECRET |
OAuth 2.0 client secret |
GOOGLE_ALLOWED_CLIENT_IDS |
Comma-separated allowed client IDs |
GOOGLE_AUTH_REDIRECT_URI |
Auth redirect URI |
GOOGLE_REDIRECT_URI |
Token exchange redirect URI |
GOOGLE_TOKEN_INFO_URL |
Token introspection URL |
Spotify, Slack, Notion
Each follows the same {PROVIDER}_CLIENT_ID, {PROVIDER}_CLIENT_SECRET, {PROVIDER}_REDIRECT_URI pattern.
Full interactive docs available at /docs (Swagger) and /redoc.
GET /health
GET /health/llm
GET /mcp/health
GET /mcp/manifest
PersonalAPI now exposes a JSON-RPC MCP-compatible endpoint for external AI clients.
POST /mcp/rpc
POST /mcp/ # root alias
Auth header (either one):
X-API-Key: pk_live_...
Authorization: Bearer pk_live_...
Supported MCP methods:
initialize
ping
tools/list
tools/call
SSE transport (for stream-oriented MCP clients):
GET /mcp/sse
POST /mcp/message?session_id=<session_id>
POST /mcp/sse/message?session_id=<session_id>
SSE flow:
- Open
GET /mcp/sseand read the firstendpointevent. - Extract
session_idfrom the event payload. - Send JSON-RPC payloads to
/mcp/message?session_id=<session_id>. - Read
messageevents on the SSE stream for JSON-RPC responses.
Example: list tools
curl -X POST http://127.0.0.1:8000/mcp/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'Example: call search tool
curl -X POST http://127.0.0.1:8000/mcp/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer pk_live_your_key" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search","arguments":{"query":"project roadmap","top_k":5}}}'POST /auth/register
POST /auth/login
POST /auth/google
GET /auth/google/connect
GET /auth/google/callback
GET /auth/me
GET /v1/emails/
GET /v1/documents/
GET /v1/search/
| Action | Method | Description |
|---|---|---|
| List connectors | GET / |
All connectors for the current user |
| Get by platform | GET /{platform} |
Single connector details |
| Trigger sync | POST /{platform}/sync |
Enqueue a sync job |
| Update auto-sync | PATCH /{platform} |
Toggle auto-sync on/off |
| Disconnect | DELETE /{platform} |
Remove connector + credentials |
| Connect | GET /{platform}/connect |
Initiate OAuth flow |
| OAuth callback | GET /{platform}/callback |
Handle provider callback |
POST /v1/chat/message
GET /v1/chat/{session_id}/history
Chat response shape:
{
"answer": "string",
"sources": [...],
"related_document_ids": [...],
"file_links": [...]
}POST /v1/developer/api-keys
GET /v1/developer/api-keys
POST /v1/developer/api-keys/{api_key_id}/revoke
GET /ws?token=<jwt>
Events: connection · sync_started · sync_completed · sync_failed
users
└── connectors # per-platform OAuth state + cursor
└── items # normalized records from all sources
└── item_chunks # text chunks + vector embeddings
└── chat_sessions
└── chat_messages
└── api_keys # SHA-256 hashed developer keys
└── access_logs
| Store | Contents |
|---|---|
| PostgreSQL | Normalized items, connector state, chat history, embeddings, access control |
| Redis | Celery broker, result backend, dead-letter queue |
Filesystem (backend/storage/users) |
User-owned source artifacts and snapshots |
| Queue | Worker | Responsibility |
|---|---|---|
connector.google |
worker-google |
Gmail, Drive, Calendar ingestion |
connector.github |
worker-github |
GitHub repos, issues, PRs |
connector.notion |
worker-notion |
Notion pages and databases |
connector.spotify |
worker-spotify |
Spotify listening history |
connector.slack |
worker-slack |
Slack messages and channels |
pipeline.file-watcher |
worker-file-watcher |
Detect new/changed user files → DB |
pipeline.embedding |
worker-embedding |
Chunk text → generate embeddings |
default |
(shared) | Misc tasks |
The Celery Beat scheduler dispatches auto-sync tasks on a configured interval across all connector queues.
Failed jobs follow a Redis-backed dead-letter pattern — inspect with celery inspect reserved or your monitoring tool of choice.
personalapi/
├── backend/
│ ├── api/
│ │ ├── core/ # Settings, DB wiring, auth, OAuth helpers
│ │ ├── models/ # SQLAlchemy ORM models
│ │ ├── routers/ # auth, connectors, search, chat, developer, ws
│ │ ├── schemas/ # Pydantic request / response contracts
│ │ └── main.py # FastAPI entrypoint and router mounting
│ ├── mcp/ # MCP-compatible FastAPI sub-application
│ ├── migrations/ # SQL bootstrap scripts
│ ├── normalizer/ # Source-specific normalization logic
│ ├── rag/ # Chunking, retrieval, context, generation
│ ├── scripts/ # Operational utilities
│ ├── storage/ # User-scoped file storage
│ ├── tests/ # Unit, integration, live backend tests
│ └── workers/ # Celery app, queue tasks, beat, embeddings
├── frontend/
│ ├── app/ # Next.js App Router pages
│ ├── components/ # UI components
│ ├── hooks/ # State and API integration hooks
│ └── lib/ # API client and shared utilities
└── docs/
├── 01-system-architecture.md
├── 02-implementation-guide.md
├── 03-deployment-and-scaling.md
├── backend-implementation-log.md
├── FRONTEND_API_REFERENCE.md
└── frontend/
├── API_INTEGRATION.md
├── DASHBOARD_DESIGN.md
└── LANDING_PAGE.md
cd backend
py -3 -m pytest tests/ -qDefaults to https://api.personalapi.tech. Override with BASE_URL:
BASE_URL=http://localhost:8000 python -m pytest tests/test_live_backend.py -v -scd frontend
npm run lint
npm run build- Backend tests pass
- Frontend lint + production build succeed
-
GET /health,GET /health/llm,GET /mcp/healthreturn OK - Connector OAuth redirect URIs are correctly configured for the target environment
- Rotate
SECRET_KEYto a cryptographically random value - Set
DATABASE_SSL_MODE=requirefor managed PostgreSQL - Restrict
CORS_ORIGINSto approved frontend domains only - Store all secrets outside source control (use a secrets manager)
- Enable TLS termination in front of the API (nginx / load balancer)
- Protect provider OAuth callback URLs with production credentials
- Verify
pgvectorandpg_trgmextensions exist before running migrations - Run all SQL migrations before first traffic
- Run a dedicated worker process per Celery queue
- Ensure Redis is persistent (
appendonly yes) or acceptable to lose on restart
- Set up health check monitoring on
/health,/health/llm,/mcp/health - Monitor worker failures and dead-letter queue depth
- Alert on Redis unavailability and high database latency
- Configure daily PostgreSQL backups and snapshot user-storage volumes
- Verify API key rotation and revocation paths are functional
Database connection failed
Fix: Check DATABASE_URL, confirm PostgreSQL is reachable, verify migrations have run, confirm pgvector and pg_trgm extensions exist. Check DATABASE_SSL_MODE.
Fix: The relevant provider credentials (CLIENT_ID, CLIENT_SECRET, REDIRECT_URI) are missing from the environment. Populate them and restart the API.
Work through this checklist in order:
- Did the connector sync actually run? Check Celery worker logs.
- Were items normalized and inserted? Query
SELECT COUNT(*) FROM items WHERE user_id = ?. - Did the embedding worker process the chunks? Check
item_chunkstable. - Is
RAG_LLM_ENABLED=trueand is the LLM backend reachable (GET /health/llm)?
Fix: Confirm Redis is running, the WebSocket token is valid (not expired), and worker completion paths are publishing events correctly.
Fix: Verify the worker hostname and queue flag match. Confirm REDIS_URL is correct. Run celery -A workers.celery_app:celery_app inspect active to see live workers.
- Fork the repository
- Create a feature branch:
git checkout -b feat/your-feature - Make your changes with tests
- Run the pre-merge validation checklist
- Open a pull request against
main
Please keep PRs focused and include a clear description of what changed and why.
| Contributor | GitHub |
|---|---|
| Om Sakhare | @Arch-777 |
| Ansh Jadhav | @JadhavAnsh |
| Nishant Patil | @const-nishant |
| Pratik Dandge | @Insomniac-Coder0 |
Built with FastAPI · Next.js · PostgreSQL · Redis · pgvector