genie-mcp-server.mjs. It replaced three separate MCP processes (Directus, Ollama, Stagehand) in Sprint 1+2 and has grown to 83 tools across 6 plugins as of Sprint 5.
Architecture
The server uses stdio transport and is spawned once by AnythingLLM on startup. There is no per-tool process overhead, no redundant auth setup, and no risk of tool name collisions across servers (duplicate tool names causeprocess.exit(1) at boot — enforced by design).
Why a single server?
- No per-tool process overhead. All tools share one Node.js process and one set of HTTP clients (Directus, Ollama, Stagehand).
- No auth duplication.
MCP_SERVICE_TOKENis loaded once bylib/services.mjsand passed to every plugin handler. - Simpler config. AnythingLLM registers a single
genieentry inanythingllm_mcp_servers.jsonrather than one entry per service. - Startup safety. The plugin loader enforces no duplicate tool names across plugins — any collision terminates the process at boot rather than silently shadowing a tool.
Boot config
The server is registered instorage/plugins/anythingllm_mcp_servers.json:
server/utils/boot/index.js calls bootMCPServers() during AnythingLLM startup, which reads this file and spawns the server.
Environment variables
| Variable | Default | Used by |
|---|---|---|
MCP_SERVICE_TOKEN | — (required) | All Directus API calls |
DIRECTUS_URL | http://127.0.0.1:8055 | cms.directus, media.process |
OLLAMA_URL | http://127.0.0.1:11434 | ai.ollama |
OLLAMA_MODEL | qwen-2.5:latest | ai.ollama default model |
STAGEHAND_URL | http://127.0.0.1:3002 | web.stagehand |
STAGEHAND_MODEL | ollama/qwen-2.5 | web.stagehand model |
PLUGINS_DIR | storage/plugins | pluginLoader.mjs |
Critical constraint: MCP-only Directus writes
All Directus writes from server-side code must go throughcms.directus MCP tools. Direct Directus SDK calls or raw fetch() to Directus from server code are prohibited.
Exceptions (pre-auth only, require DIRECTUS_ADMIN_TOKEN):
register.js— new user registration flowrbacSync.js— Directus → AnythingLLM RBAC provisioning
This constraint exists because
MCP_SERVICE_TOKEN carries the correct scoped permissions and audit trail for the service account. Bypassing it creates permission inconsistencies and breaks the audit log in list-activity.Plugin bundles
cms.directus
55 tools — Full Directus 11 API: items CRUD, users, files, flows, fields, relations, roles, policies, permissions, settings, schema, activity, and revisions. The primary data layer for all agent writes.
web.stagehand
9 tools — Browser automation via Playwright/Stagehand. Stateful sessions for scraping platform stats, HITL login flows, and fan data extraction.
ai.ollama
3 tools — Local LLM inference via Ollama. Single-turn completions and multi-turn chat. No API keys, no cloud, no content moderation.
media.process
5 tools — Media pipeline integration. ffprobe validation, async watermarking, teaser clipping, thumbnail generation, and job status polling via BullMQ.
taxonomy.core
7 tools — 3,205-node taxonomy graph: content search, LLM-assisted tagging, term mapping, graph ingestion, rebuild, pruning, and Hebbian edge reinforcement.
memory.recall
4 tools — Skill retrieval via RRF + synaptic propagation. Surfaces relevant procedural skills from 191 skills across a 12,880+ edge DuckDB graph.
Plugin convention
Every plugin is a directory understorage/plugins/ containing two files:
lib/pluginLoader.mjs) scans PLUGINS_DIR at startup. Directories with only a handler.js (CommonJS) are skipped — those are AnythingLLM agent skills, not MCP plugins.
ToolDef shape:
services object with pre-configured fetch clients:
services.directus— authenticated Directus client (MCP_SERVICE_TOKENBearer)services.ollama— Ollama base URLservices.stagehand— Stagehand base URL
Sprint history
| Sprint | Change | Tools |
|---|---|---|
| Sprint 1+2 (2026-03-08) | cms-directus, ai-ollama, web-stagehand migrated to unified server | 29 |
| Sprint 3 (2026-03-08) | media-process (5) + taxonomy-core initial (2) | 36 |
| Sprint 4 (2026-03-08) | taxonomy-core expanded to 7 tools; Hebbian cron added | 41 |
| Sprint 5 (2026-03-09) | cms-directus expanded 17→55 (fields, relations, roles, policies, permissions, schema, activity, revisions) | 79 |
| Sprint 6 (2026-03-14) | memory-recall plugin added (4 tools) | 83 |