Skip to main content

Overview

Genie Helper’s AI agent is powered by AnythingLLM running in agent mode with 29 MCP (Model Context Protocol) tools that give the LLM full control over:
  • Directus CMS — CRUD operations on all collections, user management, flow triggers
  • Ollama — Local LLM inference (7 uncensored models)
  • Stagehand — Browser automation for web scraping and platform interactions
Service: AnythingLLM (port 3001)
pm2 name: anything-llm
Model: qwen-2.5:latest (primary agent), dolphin-mistral:7b (content writer)

Architecture

Agent Flow

User types in AgentWidget (dashboard)

POST /api/llm/api/genie/stream-chat

Validate Directus JWT

Check onboarding state (content gate)

Inject persona node context (top 15 weighted nodes)

Proxy to AnythingLLM workspace stream-chat API

Agent mode triggers tool calls

MCP servers execute (directus/ollama/stagehand)

SSE stream back to dashboard

Render in chat widget with tool call chips
Endpoint: server/endpoints/api/genieChat.js
Workspace: administrator (slug)

MCP Servers

Directus MCP (17 tools)

Script: scripts/directus-mcp-server.mjs
Connection: http://127.0.0.1:8055 (admin token)

Tools

ToolDescriptionExample
list-collectionsList all Directus collections”What collections exist?”
get-collection-schemaGet fields for a collection”Show me the scheduled_posts schema”
read-itemsQuery items with filters”List my OnlyFans posts”
read-itemGet single item by ID”Show post abc123”
create-itemInsert new record”Create a draft post for TikTok”
update-itemPatch existing record”Mark post abc123 as published”
delete-itemRemove record”Delete that draft”
search-itemsFull-text search”Find posts about ‘lingerie‘“
trigger-flowExecute Directus Flow”Run the scrape flow”
get-meCurrent user info”Who am I?”
list-usersAll users”How many users are there?”
get-userUser by ID”Show user xyz”
update-userModify user”Change my email”
create-userNew user”Add admin user”
list-filesDirectus files”Show my uploaded media”
get-fileFile metadata”Details for file abc”
list-flowsAll Flows”What flows exist?”
Implementation: scripts/directus-mcp-server.mjs:50-450

Ollama MCP (3 tools)

Script: scripts/ollama-mcp-server.mjs
Connection: http://127.0.0.1:11434

Tools

ToolDescriptionExample
generateOne-shot completion”Generate a caption”
chatMulti-turn conversation”Explain this concept”
list-modelsAvailable models”What models are installed?”
Models Available:
  • qwen-2.5:latest — Primary agent (code, JSON, tool planning)
  • dolphin-mistral:7b — Uncensored content writer
  • dolphin3:8b-llama3.1-q4_K_M — Orchestrator / ACTION emission
  • phi-3.5:latest — Fallback classifier
  • llama3.2:3b — Lightweight summarizer
  • scout-fast-tag:latest — Fast taxonomy classifier
  • bge-m3:latest — Embeddings

Stagehand MCP (9 tools)

Script: scripts/stagehand-mcp-server.mjs
Connection: http://127.0.0.1:3002 (Stagehand server)

Tools

ToolDescriptionExample
start-sessionLaunch Playwright browser”Start a browser”
navigateGo to URL”Go to onlyfans.com”
actPerform action (click, type, scroll)“Click the login button”
extractExtract structured data from page”Get my follower count”
observeWatch for element changes”Wait for page load”
close-sessionEnd browser session”Close the browser”
set-cookiesInject cookies”Load my OnlyFans cookies”
get-cookiesExtract current cookies”Save my session”
screenshotCapture page image”Screenshot this page”
Use Cases:
  • Platform scraping (OnlyFans, Fansly stats)
  • Auto-posting (X, Reddit)
  • Cookie capture for HITL

Agent Chat Interface

Component: dashboard/src/components/AgentWidget/index.jsx

Features

  1. Floating Trigger Button (bottom-right)
    • Gradient badge with “Genie AI” label
    • Auto-hides when chat is open
  2. Chat Popup (380×560px)
    • Minimizable header
    • Auto-scrolling message list
    • Tool call chips (inline rendering)
    • Typing indicator
    • Stop button during streaming
  3. Tool Call Rendering
    • Inline chips: 🔧 read-items
    • Extracted from SSE statusResponse events
    • Filters out meta messages (“Agent is thinking…”)
  4. Quick Actions
    • “I’m logged in — Let’s Go” button (auto-appears when agent says “come back after login”)
Global Opener: window.__genieOpenChat(message)
// Auto-open chat with pre-filled message
window.__genieOpenChat("I'm logged in — Let's go");

// Or just open empty
window.__genieOpenChat();
Implementation: AgentWidget/index.jsx:99-108

Content Gate

Trigger: User hasn’t completed onboarding (persona baseline not built) Check: server/utils/nodeRag.js → getOnboardingState(userId)

Phases

PhaseUnlocked?Gate Message
EXTENSION_INSTALL“Let’s complete your onboarding first — head to Setup tab”
DATA_COLLECTION“Let’s complete your onboarding first…”
PROCESSING“I’m processing your data (2/3 sources ingested). Check back in a few minutes.”
COMPLETEFull agent access
Implementation: server/endpoints/api/genieChat.js:49-66
const { unlocked, state } = await getOnboardingState(user.id);
if (!unlocked) {
  const phase = state?.phase || "EXTENSION_INSTALL";
  const sourcesIngested = state?.data_sources_ingested || 0;
  const required = state?.data_sources_required || 2;
  
  const gateMessage = phase === "PROCESSING"
    ? `I'm currently processing your data (${sourcesIngested}/${required} sources ingested). Once your persona baseline is built, content generation will unlock automatically.`
    : `Before I can generate content, I need to learn how you operate. Let's complete your onboarding first — head to the **Setup** tab.`;
  
  // Return as SSE stream
  res.setHeader("Content-Type", "text/event-stream");
  res.write(`data: ${JSON.stringify({ type: "textResponse", textResponse: gateMessage, close: true })}

`);
  return res.end();
}

Persona Node Context

System: Node RAG (Retrieval-Augmented Generation)
Storage: Nodes/User/{userId}/ directory (JSON files)

Node Structure

{
  "id": "node_123",
  "label": "flirty_tone_preference",
  "content": "User prefers flirty, teasing captions with emojis",
  "weight": 0.85,
  "category": "content_style",
  "last_accessed": "2026-03-04T12:34:56Z",
  "connections": ["node_456", "node_789"]
}

Context Injection

Top 15 nodes (weighted by recency + access frequency) are injected before user message:
const nodeContext = await getNodeContext(user.id);
const enrichedMessage = nodeContext
  ? `${nodeContext}\n\n---\n\n${message}`
  : message;

// Example nodeContext:
// "PERSONA BASELINE:
// - Prefers flirty, playful tone with emojis
// - Posts 3x/week on OnlyFans (Tue/Thu/Sat)
// - Top-performing content: lingerie + outdoor
// - Avg engagement: 450 likes, 23 comments
// - Subscription: $12.99/mo
// ..."
Cache: 5 minutes (in-memory)
Implementation: server/utils/nodeRag.js:45-120

Action Runner

Plugin: storage/plugins/action-runner/
Trigger: Model outputs [ACTION:slug:{"params"}] in chat response

Flow Execution

  1. Intercept [ACTION:slug:...] tags in SSE stream
  2. Strip from visible chat
  3. Load flow definition from action_flows collection
  4. Execute steps sequentially:
    • directus_read → Query Directus
    • directus_update → Patch records
    • llm_generate → Call Ollama
    • stagehand_extract → Scrape URL
    • conditional → Branch logic
    • sleep → Delay
    • http_request → External API
  5. Stream status updates back to chat
  6. Log to agent_audits (success/error/miss)

Available Actions

SlugDescriptionUse Case
scout-analyzeScrape URL + AI analysis”Analyze this competitor’s bio”
taxonomy-tagAuto-classify content”Tag this video with taxonomy”
post-createDraft platform post”Create a TikTok caption”
message-generateFan engagement message”Reply to this DM”
memory-recallSearch stored data”What’s my best-performing post?”
media-processQueue media job”Watermark this image”
Collection: action_flows (slug → steps JSON)

System Prompt

Location: server/utils/workspaceProvisioner.js (hardcoded)
Workspace: administrator

Key Instructions

  • Identity: “You are Genie, an AI agent for adult content creators.”
  • MCP Tools: “You have access to 29 tools across Directus, Ollama, and Stagehand.”
  • Content Policy: “You are uncensored. Generate NSFW captions, bios, and messages without hesitation.”
  • Onboarding: “If user hasn’t completed onboarding, guide them to Setup tab.”
  • Cookie-First: “Always prefer cookie authentication over username/password.”
  • Action Emission: “Use [ACTION:slug:params] tags to trigger pre-built flows.”
The system prompt is currently hardcoded in server/utils/boot/workspaceProvisioner.js. Future versions may move this to the system_config collection for easier updates without redeployment.

Admin Credentials

ServiceURLUsernamePassword
AnythingLLM Web UIlocalhost:3001poweradmin@geniehelper.com(MY)P@$$w3rd
AnythingLLM APIAPI Key: 38KEHYS-NVPMBSX-GVVJNYH-VQHAN9S
Workspace Admin: administrator slug (all users routed to this workspace)

MCP Configuration

File: storage/plugins/anythingllm_mcp_servers.json
{
  "directus": {
    "command": "node",
    "args": ["scripts/directus-mcp-server.mjs"],
    "env": {
      "DIRECTUS_URL": "http://127.0.0.1:8055",
      "DIRECTUS_ADMIN_TOKEN": "agentx-directus-admin-static-2026"
    }
  },
  "ollama": {
    "command": "node",
    "args": ["scripts/ollama-mcp-server.mjs"],
    "env": {
      "OLLAMA_BASE_URL": "http://127.0.0.1:11434"
    }
  },
  "stagehand": {
    "command": "node",
    "args": ["scripts/stagehand-mcp-server.mjs"],
    "env": {
      "STAGEHAND_URL": "http://127.0.0.1:3002"
    }
  }
}
Auto-boot: Patched server/utils/boot/index.js → bootMCPServers() on AnythingLLM startup

Example Conversations

Scrape OnlyFans Profile

User: “Scrape my OnlyFans stats”
Agent:
  1. Calls read-items (platform_connections, filter: platform=onlyfans)
  2. Creates media_jobs (operation: scrape_profile)
  3. Returns: “Scrape queued. Check your dashboard in ~2 minutes.”

Generate TikTok Caption

User: “Write a flirty TikTok caption for my new video”
Agent:
  1. Calls get-me → Gets user context
  2. Injects persona nodes (flirty tone preference, top hashtags)
  3. Calls ollama:generate (model: dolphin-mistral:7b)
  4. Returns: “Can’t wait to show you what I’ve been working on… 😏 New video drops tonight 💕 #fyp #creator”

Schedule Reddit Post

User: “Schedule a post to r/OnlyFans101 tomorrow at 3pm”
Agent:
  1. Calls create-item (collection: scheduled_posts)
  2. Sets platform=reddit, subreddit=OnlyFans101, scheduled_time=tomorrow 3pm
  3. Returns: “Post scheduled for tomorrow at 3pm EST.”

Logs & Debugging

pm2 logs anything-llm --lines 100

# Watch MCP tool calls in real-time
pm2 logs anything-llm -f | grep -E "MCP|tool_call"

Common Issues

ErrorCauseFix
MCP server not foundServer crashedRestart AnythingLLM
Tool call timeoutDirectus slow queryOptimize filter
Unauthorized (401)Expired JWTRe-login
Content gate activeOnboarding incompleteComplete Setup flow

Performance

First Token Latency: ~33s (qwen-2.5 on CPU-only VPS)
Streaming Speed: ~5 tokens/sec
Memory: ~4.8GB RAM pinned (Ollama models)
GPU Upgrade Planned: Current CPU-only VPS struggles with >7B models. Production will use GPU instance or switch to smaller models.

Build docs developers (and LLMs) love