Skip to main content
Glama
kenningai

temporal-knowledge

by kenningai

Kenning Continuity

Enterprise knowledge that accumulates instead of degrading.

An MCP server that lets LLM agents accumulate organizational knowledge across sessions, scoped by domain, backed by Neo4j. Every structural invariant is enforced by a tool rather than asked for in an instruction, and no raw Cypher write is exposed — so the graph cannot corrupt itself no matter what the model decides to do.

It is in production at an enterprise scale: 37 domains, 376 sessions, and 3,000+ knowledge entities accumulated over four months of daily use.

Why this does not degrade as it fills

Most accumulating memory systems fail in one of two ways. They confabulate from the first day, because nothing distinguishes a thing that was observed from a thing that was inferred by a model trying to be helpful. Or they survive the demo and then degrade under mass, because every write is an unconstrained append and the store slowly fills with near-duplicates, silent overwrites, and claims nobody can trace to an author.

Four commitments, all enforced structurally:

Nothing is overwritten. There is no update_knowledge and no retype_knowledge. Changing what is known about an entity creates a new node linked to its predecessor by EVOLVED_FROM. The prior understanding is still there, still readable, still attributable. Being wrong earlier is a fact about the record, not something to be erased from it.

Every claim reaches its author in two hops. A knowledge entity is discovered by a Session; a Session is directed by a Person. Both edges are written by tools that refuse to run without a real director. So "who said this, and when, and toward what purpose" is always answerable — not by convention, but because there is no code path that creates knowledge without it.

Identity is never inferred from a string. Seventeen nodes named "Alice Example" across eleven domains are seventeen acts of reference, correctly distinct. Asserting that two of them are one person is a claim someone makes, in a session, recorded as a REFERENT_CLAIM that can carry the value distinct — because a system with nowhere to record the answer no will re-ask the same question forever. String-matching identity is where most knowledge graphs quietly begin lying.

Structure carries facts; properties do not duplicate them. A knowledge entity holds no domain property. It is placed in a domain by the session that discovered it and reached from there by a walk. The property that preceded this had drifted, which is what denormalizations do: 21 entities carried a domain string naming a real domain that had no path to them at all. A fact held as text beside a structure, rather than by it, is a fact that will disagree with the structure eventually.

There is no confidence field, deliberately. Someone's confidence on an occasion is a fact about their experience and does not transmit; a later reader derives their own from the description against what they know. What confidence scores reach for is carried instead by edges any reader can adjudicate: VALIDATION, INVALIDATING, and a Challenge with no paired Solution.

If you have run an accumulating memory system at scale and hit these walls yourself, we want to hear from you.

Related MCP server: Neo4j Agent Memory MCP Server

Architecture

Process layer (immutable) — Person → Session, within Domain → Session. NEXT_SESSION always points forward in time, enforced by the tool. Membership in this layer is the capacity to hold possible futures and measure them toward actualization; nothing here is a referent.

Knowledge layer (append-only) — 11 ontological types and 7 sub-labels, connected by 13 connection types, every node marked :Knowledge. Description changes create a new chain node linked by EVOLVED_FROM.

See HOWTO.xml for the operator-facing teaching to give an LLM as invariant scaffolding, and docs/design/ for the reasoning behind each commitment. HOWTO.xml is installed alongside the package, so a pip install reaches it at kenning_continuity/HOWTO.xml inside site-packages.

Prerequisites

  • Python 3.10+

  • Neo4j 5.x instance (local or remote)

  • uv (for development; not needed to install)

Quick start

pip install kenning-continuity

kenning-continuity --db-url bolt://localhost:7687

Or from source:

uv sync
uv run kenning-continuity --db-url bolt://localhost:7687

Configuration

CLI flags take precedence over environment variables, which take precedence over defaults.

CLI flag

Env var

Default

Description

--db-url

NEO4J_URI or NEO4J_URL

bolt://localhost:7687

Neo4j connection URL

--username

NEO4J_USERNAME

neo4j

Neo4j username

--password

NEO4J_PASSWORD

password

Neo4j password

--database

NEO4J_DATABASE

neo4j

Neo4j database name

--transport

NEO4J_TRANSPORT

stdio

stdio, sse, or streamable-http

--namespace

NEO4J_NAMESPACE

(none)

Tool name prefix (e.g. myappmyapp-begin_session)

--read-timeout

NEO4J_READ_TIMEOUT

30

Read query timeout, seconds

--server-host

NEO4J_MCP_SERVER_HOST

127.0.0.1

HTTP host (non-stdio transports)

--server-port

NEO4J_MCP_SERVER_PORT

8000

HTTP port (non-stdio transports)

--server-path

NEO4J_MCP_SERVER_PATH

/mcp/

HTTP path (non-stdio transports)

--allow-origins

NEO4J_MCP_SERVER_ALLOW_ORIGINS

(none)

Comma-separated CORS origins

--allowed-hosts

NEO4J_MCP_SERVER_ALLOWED_HOSTS

(none)

Comma-separated hosts, DNS-rebinding protection

MCP client configuration

Claude Desktop / Claude Code

{
  "mcpServers": {
    "temporal-knowledge": {
      "command": "kenning-continuity",
      "args": ["--db-url", "bolt://localhost:7687"]
    }
  }
}

HTTP transport

kenning-continuity \
  --db-url bolt://localhost:7687 \
  --transport streamable-http \
  --server-host 0.0.0.0 \
  --server-port 8000 \
  --allow-origins "http://localhost:3000" \
  --allowed-hosts "localhost,127.0.0.1"

Tool surface (23 tools)

A session runs: create_domain (once) → begin_session → create / evolve / confirm / connect knowledge → end_session.

The server is stateless. begin_session returns a session_id that the client passes to every subsequent knowledge tool. A session never closed stays active — by design.

Process (4)

Tool

Description

list_domains

All domains with session counts and last activity

create_domain

Create a knowledge domain (idempotent)

begin_session

Start a session; returns session_id. domain, purpose, director and director_key are all required — the director's Person node is created here and nowhere else

end_session

Close a session with a summary of what was learned

begin_session returns a count by type, not the domain state. Returning the state inline was 600,820 characters on one production domain — roughly 150k tokens spent before the session had asked a question. Call get_domain_state with types and limit for the part you actually need.

Knowledge mutation (6)

Tool

Description

create_knowledge

Create entities. Refuses on collision, refuses process types, and refuses unknown fields rather than dropping them

evolve_knowledge

The only way to change a description. Creates a new chain node preserving the prior one via EVOLVED_FROM; keeps the ontological type, replaces the sub-label set

confirm_knowledge

Record that entities were reviewed and found unchanged

merge_knowledge

Compact an EVOLVED_FROM chain into one canonical node. Destructive — cannot be undone

create_connections

Link entities. Takes a session_id and records it on every edge — an edge is an assertion and reaches its author

claim_referent

Claim two referents are the same thing, with a required resolution: proposed, confirmed, or distinct

Query (5)

Tool

Description

search_knowledge

Fulltext across names and descriptions, head-of-chain only

get_domain_state

Current entities for a domain; optional types, limit, descriptions

get_session_history

Who worked on what, when, and toward what purpose

get_chain_history

Walk EVOLVED_FROM backward — what was previously understood

read_cypher

Read-only Cypher escape hatch; writes are rejected

Taxonomy (2)

Tool

Description

list_knowledge_types

11 ontological types and 7 sub-labels, with the lattice

list_connection_types

13 knowledge and 5 process edge types

Graph analytics (6)

Tool

Description

gds_create_projection

Create a GDS graph projection

gds_drop_projection

Drop a projection

gds_pagerank

PageRank centrality

gds_betweenness

Betweenness centrality — bridge nodes

gds_louvain

Louvain community detection

gds_wcc

Weakly connected components

Type system

Every knowledge node carries :Knowledge, exactly one ontological label, an ont_type property naming that label deterministically, and zero or more sub-labels via Neo4j multi-labeling.

Ontological type

What it is

Actor

That which acts; has agency

Structure

Arrangement without agency; persistent shape

Artifact

Produced thing that persists and can be referenced

Place

A site, campus, region or extent — always a referent, never a referrer

Event

Temporally-located happening

Insight

A realization, discovery, breakthrough

Pattern

Recurring structure recognized across instances

Challenge

Present-tense obstacle

Solution

Resolution that worked; pairs with Challenge

Lesson

Rule derived from experience

Rationale

The reason behind something

Sub-labels are a lattice, not a flat map

PersonReferent → Actor          System        → Structure
Organization   → Actor          Process       → Structure
Team           → Organization → Actor         Configuration → Structure
                                              Service       → Structure

create_knowledge accepts either an ontological type (Actor) or a sub-label (Team), and applies the whole chain: :Knowledge:Actor:Organization:Team. A query for organizations therefore finds teams. A flat map would emit :Actor:Team, silently dropping the middle level, and nothing would report it.

Connection types (13)

EVOLVED_FROM, ENABLING, REQUIRING, INFORMING, CAUSING, COMPOSING, EXTENDING, RECOGNITION, VALIDATION, INVALIDATING, ASSOCIATED_WITH, SITUATED_AT, REFERENT_CLAIM.

Process edges — HAS_SESSION, NEXT_SESSION, DIRECTED, DISCOVERED, CONFIRMED — are written only by process tools and cannot be created through create_connections.

What a description should say

A description says what the entity is, not what happened to or around it. Temporal observations belong on Event nodes reached by edges.

  • Correct, for an Actor:PersonReferent: "Founder of Example Corp. Largest individual shareholder (8.4%). Filed under Schedule 13D — not passive."

  • Wrong: "SCHEDULE 13D/A Amendment No. 10 filed Oct 8, 2025. FOUNDER GOES PUBLIC…"

The filing is an Event. Alice Example is the founder. The filing revealing something about them is an INFORMING edge. Their description should survive any number of future filings unchanged, unless their identity itself changes.

Development

uv sync --group dev

./.venv/bin/pytest tests/unit          # mocked substrate, no database
./.venv/bin/pytest tests/integration   # real Neo4j via testcontainers; needs Docker
./.venv/bin/pyright

A defect that lives in a Cypher query is invisible to the unit tests — they mock the substrate, and an edge-fabrication bug once passed every one of them identically before and after the fix. Anything touching a query belongs in tests/integration/.

License and attribution

Licensed under the Apache License, Version 2.0. Use it, modify it, run it in production, commercially or otherwise.

The work here is the ontology — the type lattice, the resolution-by-walk, the placement of epistemic standing in edges, the principle that every invariant lives in a tool. That is given away freely, and Apache-2.0 asks only that attribution travel with it: keep LICENSE and NOTICE, and mark what you changed.

The Kenning AI name is not part of that grant (Apache-2.0 §6). See TRADEMARKS.md for what you may do without asking — which is nearly everything, including saying what your software is built on.

Contact

contact@kenningai.com — no form, no funnel, it reaches us directly.

We are especially interested in hearing from anyone who has run an accumulating memory system at scale and formed a view on why they fail. That failure mode is the reason for nearly every decision in this repository, and disagreement from someone who has hit it themselves is worth more to us than agreement from anyone who hasn't.


Kenning AI · kenningai.com

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityNo data
ResponsivenessNo issues

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
    D
    maintenance
    Enables storage and retrieval of knowledge in a graph database format, allowing users to create, update, search, and delete entities and relationships in a Neo4j-powered knowledge graph through natural language.
    5
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Audit-grade memory backbone for agent teams. Bi-temporal facts (event time + transaction time, with recall(as_of=...) replay), 6-step deterministic retrieval (no LLM in the critical path), conversation ingest with speaker-locked dual-pass extraction, per-tenant Postgres row-level security, and Ed25519-signed provenance. Postgres + pgvector + Neo4j defaults.
    14
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides persistent knowledge graph memory for AI agents, enabling them to store, recall, and query facts about people, projects, and relationships across sessions.
    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/kenningai/kenning-continuity'

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