Eling provides three MCP servers, split by concern:
| Server | Command | Purpose | Tools |
|---|---|---|---|
eling |
python -m eling mcp / eling mcp |
Notion-only (online/remote memory) | 6 eling_* tools |
as_brain |
python -m eling.as_brain.mcp_server / eling as-brain |
Local layers (facts, KB, code, builtin, HRR) | 20 brain_* tools |
continuum |
python -m eling continuum mcp / eling-continuum |
Layer 6 orchestration hub (multi-agent) | 15 continuum_* tools |
# Notion-only MCP server
python -m eling mcp
# or
eling mcp
# Local-layers MCP server
python -m eling.as_brain.mcp_server
# or
eling as-brainStore content as a Notion page. Requires configured NOTION_API_KEY and
NOTION_PARENT_PAGE_ID. Use the local-layers as_brain MCP server
(brain_remember) for local memory storage (facts/KB).
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
content |
string | required | Content to store as a Notion page |
title |
string | `` | Page title (auto-derived from content if empty) |
category |
string | "general" |
Optional category hint for child-page routing |
Response:
{
"page_id": "abc123",
"url": "https://notion.so/abc123",
"title": "Stored content"
}Fetch a Notion page's full, un-truncated content as markdown, via the
/v1/pages/<id>/markdown endpoint. Unlike eling_get_page (which walks the
blocks API and truncates secrets to their last few chars), this returns complete
values — use it for credential pages where you need the full API token.
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
page_id |
string | required | Notion page ID |
Response:
{
"page_id": "3907b66e-...",
"markdown": "Token\npypi-FAKE...\n",
"truncated": false
}The as_brain MCP server serves the local memory layers — facts, KB, code, builtin, and HRR. All tool names use the brain_ prefix.
| Tool | Purpose |
|---|---|
brain_remember |
Store content — auto-routes to facts (short) or KB (long) |
brain_recall |
Cross-layer search with RRF fusion (BM25 + trigram + porter) |
brain_reason |
Compositional HRR query tying multiple entities together |
brain_probe |
Get all facts about an entity |
brain_think |
Synthesis + gap analysis across layers |
brain_stats |
Show per-layer statistics |
brain_export |
Full brain export as JSON or Markdown |
brain_evolve |
Trigger memory evolution (merge near-duplicates) |
brain_snapshot |
Snapshot the facts database before destructive operations |
brain_list_snapshots |
List all available snapshots |
brain_rollback |
Rollback facts database to a named snapshot |
brain_link_stats |
Zettelkasten link graph statistics |
brain_linked_facts |
Get facts linked to a given fact_id |
brain_search_temporal |
Search facts by time range — "last 3 days", "kemarin" |
brain_versioned_update |
Update a fact with append-only versioning |
brain_get_version_history |
Get all versions of a fact |
brain_undo_to_version |
Rollback a fact to a previous version |
brain_versioning_stats |
Versioning statistics across the fact store |
brain_verify |
Query/record verification status with optional spec-kit check |
brain_verify_spec |
Run spec-kit conformance verification against project specs |
Universal brain — agent auto-attribution. The
as_brainserver captures the host agent identity from the MCPinitializehandshake (clientInfo.name) and uses it as the defaultsourceforbrain_remember. Each connected agent's memories are auto-tagged with its own identity; pass an explicitsourceto override.
Universal mode — verify-on-stop for all agents. Set the
ELING_VERIFY_ALL_AGENTS=1environment variable when launching theas_brainserver to keep verify-on-stop active for every agent (including Hermes). By default Hermes skips eling's nudges and uses its own built-in verification.
These tools accept the same parameters as their eling_* predecessors.
See the migration table below.
For detailed parameter schemas, see the tool definitions in
eling.as_brain.mcp_server.TOOLS.
eling_* (v0.7.2-) |
brain_* (v0.7.3+, as_brain) |
Notes |
|---|---|---|
eling_remember (local) |
brain_remember |
|
eling_recall |
brain_recall |
|
eling_reason |
brain_reason |
|
eling_probe |
brain_probe |
|
eling_reflect |
— | Notion promote → use eling_remember in eling server |
eling_sync |
— | Layers auto-sync internally |
eling_stats |
brain_stats |
|
eling_think |
brain_think |
|
eling_export |
brain_export |
|
eling_verify |
brain_verify |
|
eling_verify_spec |
brain_verify_spec |
|
eling_link_stats |
brain_link_stats |
|
eling_linked_facts |
brain_linked_facts |
|
eling_evolve |
brain_evolve |
|
eling_snapshot |
brain_snapshot |
|
eling_list_snapshots |
brain_list_snapshots |
|
eling_rollback |
brain_rollback |
|
eling_search_temporal |
brain_search_temporal |
|
eling_versioned_update |
brain_versioned_update |
|
eling_get_version_history |
brain_get_version_history |
|
eling_undo_to_version |
brain_undo_to_version |
|
eling_versioning_stats |
brain_versioning_stats |
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
fact_id |
integer | required | Fact ID to promote |
Response:
{
"fact_id": 17,
"page_id": "abc123...",
"promoted": true
}Get all facts about a single entity (from facts layer).
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
entity |
string | required | Entity name to probe |
limit |
integer | 10 |
Max results |
Query verification-on-stop status or record a verification event. Active for agents without built-in verification (OpenCode, OpenClaw, Cursor, Windsurf); auto-skipped when the host has its own verify-on-stop (Hermes).
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
status |
string | "" |
"" = query mode. "passed", "failed", "skipped" to record |
command |
string | "" |
The command that was run (e.g. "pytest") |
output |
string | "" |
Command output (truncated to 500 chars) |
spec_check |
boolean | false |
Also run spec-kit conformance verification |
Response (query mode):
{
"active": true,
"changed_paths": ["src/main.py"],
"verified": false,
"needs_verification": true,
"nudge": "[System: You edited code...]",
"spec_kit": {
"detected": true,
"coverage": {"covered": 3, "uncovered": 2, "total": 5},
"requirements": [...]
}
}Run spec-kit conformance verification. Detects spec-kit artifacts
(specs/<feature>/spec.md, plan.md, tasks.md) and checks whether
code files cover each spec requirement.
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
changed_files |
string[] | [] |
Files changed in this session (for targeted coverage) |
Response:
{
"detected": true,
"summary": "3/5 requirements covered (2 uncovered)",
"coverage": {"covered": 3, "uncovered": 2, "total": 5},
"features": ["auth", "payments"],
"requirements": [
{"text": "Login must validate email", "covered": true},
{"text": "Passwords must be hashed with bcrypt", "covered": false}
],
"nudge": "[System: Spec-kit requirements pending verification..."
}Synchronize data between layers (facts→Notion, flush to disk after writes).
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
direction |
string | "all" |
"push" (facts→Notion), "pull" (Notion→KB), "flush" (disk), or "all" |
layer |
string | "auto" |
Layer scope |
Zettelkasten fact link graph statistics.
Parameters: none
Response:
{
"total_links": 42,
"linked_facts": 18,
"avg_links_per_fact": 2.33
}Get facts linked to a given fact_id (Zettelkasten-style), ordered by link weight.
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
fact_id |
integer | required | Fact ID to get linked facts for |
limit |
integer | 10 |
Max results |
Response:
[
{
"fact_id": 5,
"content": "HRR dim should match numpy float32 stride",
"category": "general",
"trust_score": 0.85,
"weight": 0.42
}
]Trigger a memory evolution pass: scan all facts for near-duplicate pairs and merge them.
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
threshold |
float | 0.65 |
Jaccard similarity threshold for merge |
Response:
{
"merged": 3,
"candidates_checked": 120
}Create a named snapshot of the facts database. Use before destructive operations (evolution, decay, bulk edits) for safe rollback.
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
reason |
string | "" |
Why the snapshot is taken (e.g. "pre_evolution") |
Response:
{
"snapshot_id": "20260704-013052-853",
"path": "/root/.eling/snapshots/20260704-013052-853.db",
"created_at": "2026-07-04T01:30:52",
"reason": "pre_evolution",
"size_bytes": 4096,
"fact_count": 42
}List all available snapshots, newest first.
Parameters: none
Response:
{
"snapshots": [
{
"snapshot_id": "20260704-013052-853",
"fact_count": 42,
"reason": "pre_evolution"
}
]
}Rollback the facts database to a named snapshot. The current database is auto-snapshotted before the rollback so it can be undone.
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
snapshot_id |
string | required | Snapshot ID to restore (from eling_list_snapshots) |
Response:
{
"snapshot_id": "20260704-013052-853",
"restored_from": "/root/.eling/snapshots/20260704-013052-853.db",
"restored_to": "/root/.eling/facts.db",
"fact_count": 42,
"current_backup": "20260704-013215-456"
}Get statistics about all memory layers.
Parameters: none
Response:
{
"home": "/root/.hermes/eling",
"facts": {
"total_facts": 42,
"total_entities": 28,
"with_hrr": 42,
"avg_trust": 0.72
},
"kb": {
"total_chunks": 156,
"total_sources": 12,
"total_errors": 0
},
"code_available": true,
"notion_available": true,
"privacy": {
"total_redacted": 3,
"total_dedup_hits": 7
},
"hooks": {
"total_handlers": 15,
"hooks_with_handlers": 15
}
}Search facts by time range using natural language (English or Indonesian).
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
query |
string | "" |
Time range expression like "last 3 days", "this week", "kemarin", "hari ini" |
category |
string | "" |
Optional category filter |
since_days |
integer | 0 |
Override: search back N days (e.g., 7 = last 7 days) |
source |
string | "" |
Filter by agent source |
limit |
integer | 20 |
Max results |
Supported patterns:
| Language | Examples |
|---|---|
| English | today, yesterday, this week, last month, last 3 days, last 7 days, last 30 days |
| Indonesian | hari ini, kemarin, minggu ini, bulan lalu, 3 hari terakhir, 7 hari terakhir, 30 hari terakhir |
Response:
[
{
"fact_id": 42,
"content": "Eling v0.6.0 released",
"category": "release",
"trust_score": 0.85,
"created_at": "2026-07-04T10:30:00"
}
]Update a fact's content while preserving the previous version.
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
fact_id |
integer | required | Fact ID to update |
content |
string | required | New content |
reason |
string | "" |
Why the update was made (e.g., "corrected typo") |
Response:
{
"fact_id": 42,
"version_id": 3,
"previous": "Original content...",
"new": "Updated content..."
}Get all versions of a fact, from newest to oldest.
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
fact_id |
integer | required | Fact ID to get history for |
Response:
[
{
"version_id": 2,
"content": "Latest content...",
"changed_at": "2026-07-04T12:00:00",
"reason": "corrected typo",
"embedding_dim": 1024
},
{
"version_id": 1,
"content": "Original content...",
"changed_at": "2026-07-04T10:00:00",
"reason": "initial"
}
]Rollback a fact to a previous version (also creates a new version entry).
Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
fact_id |
integer | required | Fact ID to rollback |
version_id |
integer | required | Version ID to restore |
Response:
{
"fact_id": 42,
"version_id": 5,
"restored_from": 2
}Get statistics about the versioning system across the fact store.
Parameters: none
Response:
{
"versioned_facts": 42,
"total_versions": 156,
"version_operations": 114
}eling <command> [options]
| Command | Description | Example |
|---|---|---|
remember |
Store content | eling remember "Use pytest -x to stop on first failure" --tags testing --source opencode |
recall |
Search layers | eling recall "testing patterns" --limit 5 --source hermes |
reason |
Connect entities | eling reason pytest HRR facts |
probe |
Facts about entity | eling probe pytest |
reflect |
Promote to Notion | eling reflect 17 |
verify |
Query verification status | eling verify |
verify-spec |
Run spec-kit conformance check | eling verify-spec --changed-files src/main.py |
snapshot |
Snapshot facts DB | eling snapshot --reason "pre_evolution" |
list-snapshots |
List all snapshots | eling list-snapshots |
rollback |
Restore facts DB from snapshot | eling rollback <snapshot_id> |
link-stats |
Zettelkasten link graph stats | eling link-stats |
linked-facts |
Get linked facts for fact_id | eling linked-facts 1 |
evolve |
Merge near-duplicate facts | eling evolve --threshold 0.7 |
sync |
Sync layers | eling sync --direction push |
stats |
Show brain stats | eling stats |
mcp |
Run MCP server | eling mcp |
config |
Manage config | eling config get hrr_dim |
install-opencode |
Install OpenCode lifecycle plugin | eling install-opencode |
install-zero |
Install Zero hooks + skill + MCP | eling install-zero |
init-rules |
Write steering rules for AI agents | eling init-rules |
search-temporal |
Search facts by time range | eling search-temporal "last 3 days" --category testing |
versioned-update |
Update fact with versioning | eling versioned-update 1 "new text" --reason "correction" |
version-history |
Show version history of a fact | eling version-history 1 |
undo-to-version |
Rollback fact to a version | eling undo-to-version 1 --version-id 0 |
versioning-stats |
Versioning system statistics | eling versioning-stats |
usage: eling remember [-h] [--layer {auto,facts,kb,notion}]
[--category CATEGORY] [--tags TAGS]
[--source SOURCE] [--title TITLE]
content
usage: eling recall [-h] [--limit LIMIT] [--layers LAYERS] [--source SOURCE] query
optional arguments:
--layers LAYERS comma-separated: "facts,kb,code"
--source SOURCE filter by agent origin: "hermes", "opencode", etc.
usage: eling reason [-h] [--limit LIMIT] entities [entities ...]
usage: eling sync [-h] [--direction {push,pull,flush,all}]
[--layer {auto,facts,notion,kb}]
[--daemon] [--interval INTERVAL]
[--once] [--state-file STATE_FILE]
usage: eling snapshot [-h] [--reason REASON]
usage: eling rollback [-h] snapshot_id
usage: eling install-opencode [-h] [--dry-run]
usage: eling install-zero [-h] [--dry-run] [--zero-config-dir ZERO_CONFIG_DIR]
usage: eling init-rules [-h] [--project-dir PROJECT_DIR]
[--agent {cursor,claude_code,opencode,generic}]
[--dry-run]
usage: eling config <subcommand> [options]
Subcommands:
get [key] Get config value(s)
set <key> <value> Set a config value
unset <key> Remove a config value
ls List all config keys with sources
init Write default config.json
schema Show full config schema
Eling resolves configuration in this priority order:
- Hermes plugin config →
~/.hermes/config.yaml→plugins.eling.* - Environment →
ELING_*prefixed vars - JSON config →
~/.eling/config.json - Defaults → hardcoded in
config.py
| Key | Env | Default | Type | Description |
|---|---|---|---|---|
home |
ELING_HOME |
$HERMES_HOME/eling |
path | Eling data directory |
hrr_dim |
ELING_HRR_DIM |
512 |
int | HRR vector dimension (must match numpy float32) |
default_trust |
ELING_DEFAULT_TRUST |
0.5 |
float | Initial trust score for new facts |
min_trust |
ELING_MIN_TRUST |
0.0 |
float | Minimum trust for recall results |
notion_enabled |
ELING_NOTION_ENABLED |
true |
bool | Enable Notion layer |
codegraph_enabled |
ELING_CODEGRAPH_ENABLED |
true |
bool | Enable Code layer |
dedup_cache_size |
ELING_DEDUP_CACHE_SIZE |
1000 |
int | SHA-256 dedup LRU cache size |
auto_sync_turns |
ELING_AUTO_SYNC_TURNS |
true |
bool | Auto-sync every N turns |
embedding_model |
ELING_EMBEDDING_MODEL |
"" |
string | Model name for embeddings. For sentence-transformers: all-MiniLM-L6-v2. For Mistral API: uses mistral-embed (1024 dims) when provider is mistral |
embedding_provider |
ELING_EMBEDDING_PROVIDER |
"" |
string | Embedding provider: "" (auto-detect), sentence-transformers, or mistral |
from eling.brain import Brain
brain = Brain(
home="/path/to/data", # default: ~/.eling
notion_api_key="ntkn_...", # optional
notion_parent_id="page_...", # optional
project_path="/path/to/code",# optional, for code layer
hrr_dim=1024, # default: 512
embedding_model="all-MiniLM-L6-v2", # optional, requires sentence-transformers
)
# Store (with agent source for multi-agent setups)
brain.remember("Content", layer="auto", source="hermes")
# Search (filter by agent source or leave empty for cross-agent)
results = brain.recall("query", limit=10, source="opencode")
# Connect
facts = brain.reason(["pytest", "HRR"])
# Probe a single entity
facts = brain.probe("pytest")
# Sync layers (push facts→Notion + flush to disk)
result = brain.sync(direction="all")
# Snapshot & rollback (v0.5.1)
snap = brain.snapshot(reason="pre_evolution")
brain.rollback(snap["snapshot_id"])
snapshots = brain.list_snapshots()
# Temporal search (v0.6.0) - natural language time range
results = brain.search_temporal("last 3 days", category="testing")
results = brain.search_temporal("kemarin") # Indonesian support
# Per-fact versioning (v0.6.0) - append-only updates
versioned = brain.versioned_update(1, "New content", reason="corrected typo")
history = brain.get_version_history(1)
undo = brain.undo_to_version(1, version_id=0)
vstats = brain.versioning_stats()
# Stats
stats = brain.stats()
# Promote
brain.reflect(fact_id=17)
# Stats
brain.stats()
# Sync
brain.sync(direction="all")
# Cleanup
brain.close()Standalone facts-layer provider — no Brain dependency, Hermes-compatible.
from eling.fact_memory_provider import FactMemoryProvider
mem = FactMemoryProvider(db_path="~/.myagent/facts.db")
# Store a fact (runs PII redaction + SHA-256 dedup)
r = mem.remember("Alice loves chocolate", category="preference")
# → {"stored": True, "fact_id": 1, "redacted": {"keys": 0}, "duplicate": False}
# Hybrid search: BM25 + Jaccard + HRR
results = mem.recall("chocolate", limit=10)
# Get all facts about an entity
facts = mem.probe("Alice")
# Delete a fact
mem.forget(1)
# Merge near-duplicates
stats = mem.evolve(threshold=0.65)
# Entity co-occurrence neighbors
neighbors = mem.entity_neighbors("Alice")
# Memory health
health = mem.stats()
# Apply exponential forgetting decay
decayed = mem.apply_decay(decay_rate=0.01)
# Cleanup
mem.close()from eling.config import (
DEFAULTS,
describe_config,
get_config,
resolve_config,
set_config_key,
remove_config_key,
)
# Resolve with full fallback chain
cfg = resolve_config()
print(cfg["hrr_dim"]) # 512 (or from env/config)
# Read/write config file
set_config_key("hrr_dim", 1024, home="/home/user/.eling")
# Get schema
schema = describe_config()from eling.hooks import HookRegistry, HOOK_DECISION_MADE
registry = HookRegistry()
# Register custom handler
def my_handler(name: str, ctx: dict) -> dict:
print(f"Hook {name} fired with: {ctx}")
return {"ok": True}
registry.register(HOOK_DECISION_MADE, my_handler)
results = registry.fire(HOOK_DECISION_MADE, {"content": "test"})continuum is a third MCP server that turns eling into a shared hub for many
coding agents. All agents point at one continuum.db (via a shared ELING_HOME);
every memory entry and agent registration is auto-attributed by the agent's MCP
handshake clientInfo.name.
# Start the hub
python3 -m eling continuum mcp
# or
eling-continuumIt exposes 15 continuum_* tools:
| Tool | Purpose |
|---|---|
continuum_project_create |
Register a canonical project root (shared memory + orchestration scope) |
continuum_project_get |
Get a registered project by path |
continuum_project_list |
List all registered projects |
continuum_knowledge_create |
Store a lesson: kind='fundamental' (binding rule, loaded every dispatch) or kind='situational' (semantic search). agent_slug auto-attributed from handshake |
continuum_knowledge_get |
Fetch a knowledge entry body by (project, slug) |
continuum_knowledge_list |
List knowledge metadata (pass kind='fundamental' for binding rules) |
continuum_knowledge_search |
BM25/semantic ranked search over knowledge (metadata-only) |
continuum_agent_register |
Register a dispatch agent (state=draft); reserve reserved_paths (globs) with collision checks |
continuum_agent_update |
Transition status draft→active→merged|abandoned; set branch/worktree/prompt/merged_commit |
continuum_agent_get |
Get one agent's full registry record |
continuum_registry_list |
Paginate dispatch metadata across agents (the "what did the other agent do?" view) |
continuum_plot_get |
Get the canonical PLOT.md protocol for a project |
continuum_plot_update |
Mutate PLOT.md via unified diff (no full-text writes) |
continuum_dispatch |
ONE-CALL DISPATCH: register agent + create isolated git worktree + return a ready-to-paste prompt for a fresh agent |
continuum_reservations |
Show reserved_path collisions across ACTIVE agents on a project |
chmod +x continuum/install.sh
continuum/install.sh --eling-home /shared/eling # wire Hermes/OpenCode/MiMo-Code/Zero/Claude Code/Codex
continuum/healthcheck.sh --eling-home /shared/eling # verify
continuum/uninstall.sh # unwire (restores backups)Per-agent configs: continuum/configs/. Full guide: continuum/README.md.