System Architecture
Genie Helper is a multi-service platform that combines AnythingLLM, Directus CMS, Ollama, and Stagehand browser automation into a unified AI operations platform for content creators.Architecture Overview
Service Layout
AnythingLLM
Port: 3001
PM2 Name:
Role: Chat API, AI agent, embed widget
Files:
PM2 Name:
anything-llmRole: Chat API, AI agent, embed widget
Files:
server/, storage/Directus CMS
Port: 8055
PM2 Name:
Role: Collections, auth, REST API
Files:
PM2 Name:
agentx-cmsRole: Collections, auth, REST API
Files:
cms/Stagehand
Port: 3002
PM2 Name:
Role: Browser automation
Files:
PM2 Name:
stagehand-serverRole: Browser automation
Files:
scripts/stagehand-mcp-server.mjsDashboard
Port: 3100
PM2 Name:
Role: React SPA (serve dashboard/dist/)
Files:
PM2 Name:
genie-dashboardRole: React SPA (serve dashboard/dist/)
Files:
dashboard/Media Worker
Port: —
PM2 Name:
Role: BullMQ consumer (Redis)
Files:
PM2 Name:
media-workerRole: BullMQ consumer (Redis)
Files:
media-worker/Collector
Port: —
PM2 Name:
Role: Document ingestion
Files: AnythingLLM collector scripts
PM2 Name:
anything-collectorRole: Document ingestion
Files: AnythingLLM collector scripts
Ollama
Port: 11434
PM2 Name: (system)
Role: Local LLM inference
Files: System service
PM2 Name: (system)
Role: Local LLM inference
Files: System service
MCP Servers (29 Tools Total)
Genie Helper uses the Model Context Protocol to give the AI agent access to three core systems:Directus MCP (17 Tools)
Script:scripts/directus-mcp-server.mjs
View All Directus Tools
View All Directus Tools
list-collections— List all available collectionsget-collection-schema— Get schema for a specific collectionread-items— Read multiple items from a collectionread-item— Read a single item by IDcreate-item— Create a new item in a collectionupdate-item— Update an existing itemdelete-item— Delete an itemsearch-items— Search items with filterstrigger-flow— Trigger a Directus Flowget-me— Get current user infolist-users— List all usersget-user— Get a specific userupdate-user— Update user detailscreate-user— Create a new userlist-files— List uploaded filesget-file— Get file detailslist-flows— List all automation flows
Ollama MCP (3 Tools)
Script:scripts/ollama-mcp-server.mjs
generate— Generate text completionschat— Interactive chat with modellist-models— List available local models
Stagehand MCP (9 Tools)
Script:scripts/stagehand-mcp-server.mjs
View All Stagehand Tools
View All Stagehand Tools
start-session— Initialize browser sessionnavigate— Navigate to URLact— Perform browser action (click, type, etc.)extract— Extract data from pageobserve— Observe page stateclose-session— Close browser sessionset-cookies— Set browser cookiesget-cookies— Get browser cookiesscreenshot— Capture screenshot
MCP Configuration
Config File:storage/plugins/anythingllm_mcp_servers.jsonAuto-boot: Patched
server/utils/boot/index.js → bootMCPServers() on startup
Data Layer (Directus Collections)
Genie Helper uses Directus as its primary data store with 11+ key collections:| Collection | Purpose | Key Fields |
|---|---|---|
creator_profiles | Platform accounts, encrypted credentials, scrape status | platform, username, credentials (encrypted) |
scraped_media | Content with engagement metrics | url, views, likes, revenue |
scheduled_posts | Post queue (worker polls every 60s) | scheduled_at, platforms, status |
media_jobs | BullMQ job records | job_type, status, result |
hitl_sessions | Human-in-the-loop login requests | platform, status, completed_at |
platform_sessions | Encrypted browser cookies from extension | platform, cookies (encrypted) |
taxonomy_dimensions | 6 super-concept content classification | dimension_name, weight |
taxonomy_mapping | 3,208 classified tags across 6 concepts | tag, dimension, confidence |
fan_profiles | Fan engagement data | username, ltv, last_interaction |
action_flows | Action Runner flow definitions | slug, steps (JSON) |
agent_audits | Every ACTION execution logged | action_slug, success, error |
All platform credentials are encrypted with AES-256-GCM using
server/utils/credentialsCrypto.js before storage.Action Runner System
The Action Runner is a middleware layer that intercepts special tags from the AI model’s output:How It Works
Available Actions
| Action Slug | Purpose | MCP Tools Used |
|---|---|---|
scout-analyze | Scrape URL + AI analysis | stagehand:navigate, stagehand:extract, ollama:generate |
taxonomy-tag | Auto-classify content with taxonomy | directus:read-item, ollama:generate, directus:update-item |
post-create | Draft platform-specific post | directus:read-items, ollama:chat, directus:create-item |
message-generate | Fan engagement message | directus:read-item, ollama:generate |
memory-recall | Search stored data + summarize | directus:search-items, ollama:generate |
media-process | Queue media job | directus:create-item (media_jobs) |
Media Worker (BullMQ)
The Media Worker is a BullMQ consumer that processes asynchronous jobs: Queues:scrape-jobs— Profile scrapingmedia-jobs— Media processingonboarding-jobs— User onboarding workflows
scrape_profile
Uses Stagehand to log into OnlyFans, extract stats and content, store in
scraped_mediapublish_post
Cross-platform posting via Stagehand browser automation
apply_watermark
ImageMagick-based image watermarking (100ms per operation)
create_teaser
FFmpeg video preview generation (~30s CPU per clip)
post_scheduler
Polls
scheduled_posts every 60s and publishes ready postsmedia-worker/index.jsRedis Backend: Required for BullMQ job queue
Dashboard (React SPA)
Path:dashboard/Stack: React 18 + Vite + Tailwind CSS + React Router v6
Doc Root:
dashboard/dist/ served at geniehelper.com/
Routes
Public Routes:/— Home/pricing— Pricing plans/about— About page/register— Registration (invite-gated)/login— Login
/app/*):
/app/dashboard— Main dashboard/app/media— Media library/app/calendar— Post calendar/app/fans— Fan management/app/analytics— Performance analytics/app/platforms— Platform connections/app/settings— User settings
/admin— Directus + AnythingLLM iframes/view-as— User impersonation
AI Chat Widget
AnythingLLM embed widget injected bottom-right on all/app/* routes:
- Embed ID:
cf54a9c0-224c-469d-b97b-5dc8095eac82(Administrator workspace) - Greeting: Set via
data-greetingattribute on script tag - Component:
dashboard/src/components/AgentWidget/index.jsx - Trigger:
window.__genieOpenChat()
API Proxies
Nginx Configuration:/api/directus/→http://localhost:8055/api/llm/→http://localhost:3001
- Directus JWT (auto-refresh)
- sessionStorage for impersonation tabs
- Invite-gated — Alpha invite code validated against AnythingLLM invite API
Data Flow Examples
Profile Scraping Flow
User Clicks 'Scrape Profile'
Dashboard sends POST to
/api/queue/scrape-profile with creator_profile_idStagehand Session Started
If cookies exist:
If cookies missing: Create
set-cookies + navigate to platformIf cookies missing: Create
hitl_sessions record (yellow dashboard banner)Content Classification Flow
Security Architecture
Credential Encryption
File:server/utils/credentialsCrypto.js
- AES-256-GCM encryption
- No encryption keys in browser — all crypto is server-side only
- Handles both new object format and legacy raw strings
Authentication Flow
- User logs in via
/login(React form) - Credentials sent to
/api/directus/auth/login - Directus returns JWT access token + refresh token
- Dashboard stores tokens in localStorage
- All API requests include
Authorization: Bearer <token> - Auto-refresh when access token expires
RBAC Synchronization
User roles are synced between Directus and AnythingLLM: Endpoint:server/endpoints/api/rbacSync.jsWebhook: Directus fires webhook on user create/update
Secret:
RBAC_SYNC_WEBHOOK_SECRET validates webhook authenticity
Nginx Reverse Proxy
Current proxy layout (full config indocs/nginx/geniehelper.com.vhost_nginx.conf):
- Sub-path locations (
/app/,/api/llm/) and exact-match (= /path) are safe - SPA routing:
error_page 404 =200 /index.html; - WebSocket: use
"upgrade"literal forConnectionheader
Project Structure
Performance Considerations
Server Specs: $100/mo IONOS dedicated VPS, self-hostedResource Usage:
- LLM inference: CPU-bound Qwen2.5 7B ~2-5s/call, ~4.8GB RAM pinned
- Stagehand sessions: ~300MB RAM/active browser → ~33 concurrent sessions hard ceiling (10GB available)
- FFmpeg clip generation: ~30s CPU per clip (real bottleneck)
- Sharp/ImageMagick watermark: ~100ms (effectively zero cost → unlimited justified)
- Current Plesk VPS is CPU-only
dolphin3:8band any >7B model will stall on CPU- Production upgrade: GPU VPS or stick with
qwen-2.5:latest
Next Steps
Quick Start
Install and configure Genie Helper on your server
API Reference
Explore the Directus and AnythingLLM API endpoints
MCP Servers
Learn how to extend MCP servers with custom tools
Deployment
Production deployment best practices
