Skip to main content
Glama
thecodacus

OKF Knowledge Agent MCP Server

by thecodacus

understory 🌱

Memoria que crece.

La capa bajo tus agentes: una memoria de markdown plano que se auto-conecta. Cada hecho que tus agentes aprenden se archiva como un concepto markdown, se enlaza cruzadamente en un grafo de conocimiento vivo, y el propio agente lo mantiene sano: buscable, con capacidad de diff y totalmente tuya. Funciona muy bien con modelos locales.

Los bundles siguen la especificación Open Knowledge Format (OKF) v0.1: archivos markdown plano con frontmatter YAML, legibles por humanos, con diff en git y portables entre herramientas.

Tres vías de entrada, un solo agente:

  • Servidor MCP — herramientas memory_query / memory_add / memory_update / memory_status / memory_maintain sobre stdio o HTTP transmisible. Cada llamada impulsa un agente LLM interno con la especificación OKF en su prompt del sistema.

  • Interfaz web — explora el bundle (árbol, visor de conceptos, registro de actualizaciones, insignia de conformidad), ve la memoria como un grafo dirigido por fuerzas estilo Obsidian (arrastrar/desplazar/zoom, coloreado por tipo, tamaño según conexiones, huérfanos con anillo rojo, clic para abrir) y chatea con el mismo agente para probarlo. Las llamadas a herramientas se renderizan en línea para que puedas ver cómo funciona.

  • Reproducción de rutas de consulta — cada ejecución del agente (consulta/mutación/chat) registra su recorrido (búsquedas → lecturas → escrituras) como una notación compacta, persistida en <bundle>/.traces/. La vista de grafo lista las ejecuciones recientes; al seleccionar una, se reproduce la ruta como saltos dirigidos numerados sobre el grafo: los conceptos visitados con anillo, los resultados de búsqueda punteados, todo lo demás atenuado.

  • CLI — entradas de prueba pnpm agent:query "..." / pnpm agent:mutate "...".

Regla de diseño: la conformidad se aplica en el código, no en los prompts. La capa determinista de bundles valida el frontmatter (type obligatorio), regenera los archivos index.md, añade entradas a log.md (de más reciente a más antigua, especificación §7) y limita todas las rutas a la raíz del bundle. El LLM decide qué cambiar; el código garantiza que el resultado sea un bundle conforme.

Inicio rápido (Docker)

No necesitas clonar nada: la imagen es pública. Guarda esto como docker-compose.yml:

services:
  understory:
    image: ghcr.io/thecodacus/understory:latest
    ports:
      - "3800:3800"
    # Lets the container reach a llama.cpp server running on the host via
    # http://host.docker.internal:8080/v1 (see "Local llama.cpp" below).
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      # Your memory lives here as plain markdown — a named volume, or point
      # a bind mount (e.g. ./my-memory:/bundle) at any OKF bundle.
      - understory-memory:/bundle
    environment:
      BUNDLE_ROOT: /bundle
      LLM_API_BASE_URL: ${LLM_API_BASE_URL}
      LLM_API_KEY: ${LLM_API_KEY}
      LLM_API_FORMAT: openai
      LLM_MODEL: ${LLM_MODEL:-}
      # Optional fallback
      LLM_FALLBACK_API_BASE_URL: ${LLM_FALLBACK_API_BASE_URL:-}
      LLM_FALLBACK_API_KEY: ${LLM_FALLBACK_API_KEY:-}
      LLM_FALLBACK_API_FORMAT: ${LLM_FALLBACK_API_FORMAT:-openai}
      LLM_FALLBACK_MODEL: ${LLM_FALLBACK_MODEL:-}
    restart: unless-stopped

volumes:
  understory-memory:
docker compose up -d

Elegir un proveedor

El sistema genérico de proveedores admite cualquier API compatible con OpenAI o Anthropic. Configura LLM_API_BASE_URL + LLM_API_KEY + LLM_MODEL y deja LLM_PROVIDER sin establecer.

DeepSeek:

LLM_API_BASE_URL=https://api.deepseek.com/v1 LLM_API_KEY=sk-... LLM_MODEL=deepseek-chat

OpenAI:

LLM_API_BASE_URL=https://api.openai.com/v1 LLM_API_KEY=sk-... LLM_MODEL=gpt-4o

Anthropic (Claude):

LLM_API_BASE_URL=https://api.anthropic.com/v1 LLM_API_KEY=sk-ant-... LLM_API_FORMAT=anthropic LLM_MODEL=claude-sonnet-5

Groq:

LLM_API_BASE_URL=https://api.groq.com/openai/v1 LLM_API_KEY=gsk_... LLM_MODEL=llama-3.3-70b-versatile

llama.cpp local:

LLM_API_BASE_URL=http://host.docker.internal:8080/v1 LLM_MODEL=

Cuando understory se ejecuta en Docker, localhost es el propio contenedor, no el host — así que un llama-server en el host se alcanza en host.docker.internal (los archivos compose anteriores ya lo mapean mediante extra_hosts). Si se ejecuta desde el código fuente en la misma máquina que llama-server, usa http://localhost:8080/v1.

llama.cpp local con respaldo de DeepSeek:

LLM_API_BASE_URL=http://host.docker.internal:8080/v1 LLM_MODEL= \
LLM_FALLBACK_API_BASE_URL=https://api.deepseek.com/v1 LLM_FALLBACK_API_KEY=sk-... LLM_FALLBACK_MODEL=deepseek-chat

Las antiguas variables de entorno LLM_PROVIDER + clave por proveedor siguen funcionando (compatibles hacia atrás), pero están obsoletas.

A continuación:

  • Interfaz webhttp://localhost:3800 — explora la memoria, observa el grafo, chatea con el agente

  • Endpoint MCPhttp://localhost:3800/mcp (HTTP transmisible) — regístralo en cualquier cliente MCP:

    claude mcp add --transport http ustory http://localhost:3800/mcp
  • Tu agente ahora tiene memory_query / memory_add / memory_update / memory_status / memory_maintain, y recibe un resumen inicial de la memoria al comienzo de cada sesión.

Enséñale algo (memory_add: «Desplegamos los viernes, nunca los lunes»), luego abre el grafo y observa cómo el concepto se integra solo. ¿Despliegas con Portainer? Usa docker-compose.portainer.yml como stack de repositorio.

Related MCP server: Kremis

Pila tecnológica

Monorepo pnpm:

Paquete

Descripción

packages/core

Capa de bundles OKF (sin LLM) + agente (bucle de herramientas de Vercel AI SDK: search/read/list/write/patch/delete) + registro de proveedores

packages/server

Express: MCP streamable-HTTP en /mcp, binario stdio, API REST de exploración en /api/*, chat en streaming en /api/chat, sirve el build web

packages/web

Vite + React + TS + Tailwind: navegador de bundles + chat con agente (useChat)

Los proveedores se configuran mediante LLM_API_BASE_URL, LLM_API_KEY, LLM_API_FORMAT (openai o anthropic) y LLM_MODEL. Cualquier endpoint compatible con OpenAI (DeepSeek, OpenAI, Groq, OpenRouter, llama.cpp, etc.) funciona con LLM_API_FORMAT=openai; los endpoints compatibles con Anthropic usan LLM_API_FORMAT=anthropic. El respaldo opcional usa las variables LLM_FALLBACK_* correspondientes.

llama.cpp

# on the inference box — --jinja enables OpenAI-style tool calling
llama-server -m model.gguf --jinja --host 0.0.0.0 --port 8080

# here — no model id needed, it's discovered for llama-server-like local endpoints
LLM_API_BASE_URL=http://inference-box:8080/v1 LLM_API_FORMAT=openai LLM_MODEL= \
BUNDLE_ROOT=./sample-bundle node packages/server/dist/index.js

También funciona detrás de llama-swap: la detección prefiere el modelo actualmente cargado para que una consulta no provoque un cambio de modelo de varios minutos. Fija un modelo concreto con LLM_MODEL=.

Desde el código fuente

pnpm install
pnpm build
cp .env.example .env   # add your API key

BUNDLE_ROOT=./sample-bundle \
LLM_API_BASE_URL=https://api.deepseek.com/v1 \
LLM_API_KEY=sk-... \
LLM_API_FORMAT=openai \
LLM_MODEL=deepseek-chat \
node packages/server/dist/index.js
# → http://localhost:3800  (web UI + /api + /mcp)

O construye el contenedor tú mismo: docker compose up --build (el docker-compose.yml del repositorio compila desde el código fuente y monta ./sample-bundle).

Modo de desarrollo (servidor en :3800, Vite HMR en :5180 con proxy):

BUNDLE_ROOT=./sample-bundle pnpm --filter @understory/server dev
pnpm --filter @understory/web dev

Registro de MCP (Claude Code / Desktop)

claude mcp add ustory \
  -e BUNDLE_ROOT=/path/to/your/bundle \
  -e LLM_API_BASE_URL=https://api.deepseek.com/v1 \
  -e LLM_API_KEY=sk-... \
  -e LLM_API_FORMAT=openai \
  -e LLM_MODEL=deepseek-chat \
  -- node /path/to/understory/packages/server/dist/mcp/stdio.js

O apunta un cliente MCP HTTP a http://host:3800/mcp.

Autenticación

Por defecto el servidor está abierto: correcto en localhost o en una LAN de confianza. Antes de exponerlo en cualquier otro lugar, establece AUTH_TOKEN:

AUTH_TOKEN=$(openssl rand -hex 24)

Con esto establecido, /mcp y /api requieren Authorization: Bearer <token> (la interfaz web sigue siendo accesible y solicita el token). Registra clientes MCP autenticados con una cabecera:

claude mcp add --transport http ustory http://host:3800/mcp \
  --header "Authorization: Bearer <token>"

El transporte stdio no necesita token: es un proceso local lanzado por el cliente.

Memoria semilla

Un LLM cliente que solo ve cuatro nombres de herramientas a secas nunca tiene el instinto de consultar la memoria. Así que al inicio de la sesión el servidor inyecta un resumen compacto de lo que contiene la base de conocimiento (directorios, conceptos con tipos + descripciones, actividad reciente) a través de ambos canales que llegan al modelo:

  1. el campo instructions de la inicialización MCP (clientes como Claude lo ponen en el prompt del sistema), y

  2. la descripción de la herramienta memory_query — el respaldo universal que carga todo cliente que llama a herramientas.

La semilla se regenera desde cero para cada sesión. Después de memory_add / memory_update en una sesión de larga duración (stdio), la descripción de la herramienta se actualiza mediante tools/list_changed, de modo que la sesión ve sus propias escrituras. Las ediciones fuera de banda (ediciones manuales, otros clientes) se detectan en la siguiente sesión.

Salud y mantenimiento del grafo

La memoria es un grafo, no un montón de notas, y los grafos se deterioran: los conceptos quedan huérfanos (nada enlaza a ellos) y los enlaces se rompen. Dos mecanismos la mantienen sana:

  • Enlazado en el momento de escritura — el nuevo conocimiento o bien enriquece el concepto al que pertenece (un atributo de una entidad existente se incorpora mediante un parche, no se archiva por separado) o, cuando se trata de una entidad distinta, se crea y se enlaza de vuelta desde los conceptos relacionados. Las contradicciones se reemplazan in situ, nunca se dejan en pie junto al valor antiguo.

  • memory_maintain — un lint determinista (huérfanos + enlaces rotos, expuestos en memory_status bajo graph) impulsa a un agente interno a conectar los huérfanos con conceptos relacionados y arreglar los enlaces colgantes. Ejecútalo periódicamente para contrarrestar la deriva; no hace nada cuando el grafo ya está sano.

Este diseño refleja el patrón del LLM Wiki de Karpathy (index.md + log.md, crear-vs-enriquecer, lint de huérfanos). Se difiere de ese patrón hasta que la escala lo justifique: un esquema explícito de tipos de página y búsqueda híbrida FTS5+embeddings (el escaneo simple en search.ts funciona bien hasta unos pocos miles de conceptos).

Pruebas

pnpm test                                  # core: 18 tests (spec §5/§6/§7/§9, sandbox, search, concurrency)
pnpm --filter @understory/server exec tsx scripts/mcp-smoke.mts   # MCP stdio round-trip (needs SMOKE_BUNDLE + an API key)

Entorno

Consulta .env.example. BUNDLE_ROOT es obligatorio; GIT_AUTOCOMMIT=true hace commit de cada mutación.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    A Knowledge Graph MCP server optimized for LLM context efficiency through compact JSON and SQLite persistence. It enables full graph management including node/edge CRUD operations, full-text search, and subgraph traversal.
  • A
    license
    A
    quality
    A
    maintenance
    MCP server exposing a deterministic, local knowledge graph over stdio. Zero LLM calls in the bridge; answers are classified as Fact, Inference, or Unknown and persisted in redb (ACID, BLAKE3-hashed).
    10
    14
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    A local OKF-compatible knowledge engine for AI agents. Enables capturing agent conversations, hybrid semantic+keyword search, MCP serving to agents, interactive graph visualization, and OKF bundle export.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides LLM agents with a structured, queryable, local-first knowledge base with typed documents and full-text search via MCP.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/thecodacus/understory'

If you have feedback or need assistance with the MCP directory API, please join our Discord server