Skip to main content
Glama

keephaven-mcp

Your agent's memory, on a box in your house. An MCP server that gives an AI agent a long-term memory stored on a Keephaven, not on a vendor's server.

Works with MCP clients that run local servers, like Claude Desktop, Claude Code and Cursor.

What the agent gets

Tool

What it does

memory_write

Save a file, like people/dafarus.md or projects/keephaven.md. Optional etag check so two sessions don't overwrite each other.

memory_read

Read a file back, with its etag.

memory_list

List files, optionally under a folder.

memory_search

Case-insensitive search across files and journal.

memory_delete

Delete a file.

journal_append

Add an entry to an append-only journal. The agent can add to it, never edit or delete it.

journal_read

Read recent journal entries, oldest first.

memory_status

Name, read-only or not, quota used.

Related MCP server: fimemory

What the owner keeps

  • Each agent gets its own folder and can't see any other agent's.

  • You add an agent in Keephaven's Settings > Agents and get a token, shown once. The box stores only a fingerprint of it.

  • Revoke cuts the agent off at once. Its files stay until you delete them.

  • Set a size limit per agent, or make one read-only.

  • If your Keephaven backs up to a second box, the agent's folder is part of that backup, and the backup box refuses every delete. That part isn't tested between two real boxes yet.

Set it up

  1. On the Keephaven: Settings > Agents > Add an agent. Copy the two values it shows.

  2. Add the server to your MCP client. For Claude Desktop, in claude_desktop_config.json:

{
  "mcpServers": {
    "keephaven": {
      "command": "npx",
      "args": ["-y", "github:dafarusd/keephaven-mcp"],
      "env": {
        "KEEPHAVEN_URL": "http://keephaven-xxxx.local:8790",
        "KEEPHAVEN_TOKEN": "khm_..."
      }
    }
  }
}

For Claude Code:

claude mcp add keephaven -e KEEPHAVEN_URL=http://keephaven-xxxx.local:8790 -e KEEPHAVEN_TOKEN=khm_... -- npx -y github:dafarusd/keephaven-mcp

It installs straight from GitHub, so the first start takes a minute while it builds. Needs Node 20 or newer.

The machine running the agent has to reach the box: same home network, the Keephaven's own Wi-Fi, or your Tailscale tailnet when Remote access is on.

Try it with no box

The box runs one Python file with no dependencies. Run that same file anywhere with Python 3:

python3 agent-memory.py serve --data ./mem --bind 127.0.0.1 --dev-token khm_try-it-locally

Then point the MCP server at http://127.0.0.1:8790 with that token. The file is modules/agent-memory.py in the Keephaven repo.

Status, honestly

  • The memory service is built and tested: 22 API tests, and a two-VM NixOS test where the service runs as its own locked-down user and a second machine uses it over the network.

  • This MCP server has 7 end-to-end tests: the official MCP client, this server over stdio, and the real memory service.

  • It ships in Keephaven Agent Memory, released 2026-10-25 for a Pi 5 and for a USB SSD on a Windows PC: https://keephaven.co/agent-memory. The Pi edition passed its release checks on one Pi 5, the SSD edition on a real drive on a Windows PC. Backup ran from a real Pi 5 (pre-release build) to a PC build in a VM over Tailscale — not yet between two real boxes. Home and Photos boxes don't have it.

  • Tokens travel in plain HTTP on your home network, like the rest of the box's local pages. Over Tailscale they're encrypted.

Agent skill

skill/keephaven/ is an agent skill (a SKILL.md plus a read-only check.py): how to use a Keephaven as memory, and how to boot one in a VM and report what works. check.py was run against the Photos SSD image booted in QEMU: setup page, then ready, Photos up, Immich 3.0.3.

Built by @Dafarusd. MIT License.

Available Tools

8 tools
journal_appendAdd to your journalA

Append one entry to your append-only journal: what you did, decided, or learned. Nothing in the journal can be edited or deleted afterwards, so it's the record your future sessions can trust.

NameRequiredDescriptionDefault
dataNoany structured detail: ids, numbers, results
tagsNo
textYeswhat happened, in a sentence or two

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare idempotentHint=false, so the description carries most of the behavioral burden — and it does: 'Nothing in the journal can be edited or deleted afterwards' clearly discloses irreversibility, which is the critical trait for a write tool. It omits size/length constraints and any indication of how entries are later retrieved.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero waste, with the core action and the content guidance front-loaded and the irreversibility caveat immediately after. Nothing to trim.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-parameter write tool with no output schema, the description covers purpose and the irreversible-append semantic well. It would be stronger if it acknowledged the structured 'data'/'tags' dimensions and pointed at journal_read for retrieving past entries.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67% (text and data are described, tags is not), so the schema does most of the work. The description adds no parameter-level information at all — it never mentions the structured 'data' payload or the 'tags' array, so an agent must read the schema to learn that structured detail or categorization is even possible.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Append one entry to your append-only journal') plus the content scope ('what you did, decided, or learned'). It does not explicitly distinguish itself from the nearby memory_write sibling, which is the main ambiguity an agent would face.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'what you did, decided, or learned' implies when the tool is appropriate, and the append-only framing suggests durable records. However, there is no explicit when-not guidance and no named alternative (e.g., memory_write for mutable notes, journal_read for retrieval), leaving the choice to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

journal_readRead your journalA
Read-only

Read your most recent journal entries, oldest first. Use at the start of a session to pick up where you left off.

NameRequiredDescriptionDefault
limitNo
sinceNoYYYY-MM-DD, only entries from this day on

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

readOnlyHint=true already tells the agent this is a safe read, so the description's job is lighter. It adds real value with the ordering guarantee ("oldest first") and the session-start framing, but leaves unclear what "most recent" defaults to and says nothing about pagination or entry contents.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, no waste, with scope and ordering front-loaded before the usage hint. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple and read-only with no output schema, so the description is nearly sufficient. However, with no output schema the agent gets no hint of what a journal entry looks like, and the undocumented `limit` parameter leaves the return volume ambiguous.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50%: `since` documents its YYYY-MM-DD format, but `limit` has no description or default anywhere. The description could have explained how many entries are returned by default and how limit interacts with the oldest-first ordering, but it does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Read your ... journal entries") plus scope and ordering ("most recent", "oldest first"), which no sibling claims. It doesn't explicitly separate itself from memory_read or memory_search, so an agent must infer the journal-vs-memory distinction from the name alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete trigger: "Use at the start of a session to pick up where you left off." That is a clear when-to-use signal, but there is no when-not guidance and no pointer to journal_append or memory_search as alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_deleteDelete a memory fileA
Destructive

Delete one file from your memory on the box. Journal files can't be deleted. A paired backup box keeps what it already received.

NameRequiredDescriptionDefault
pathYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

destructiveHint=true already flags the safety profile, but the description adds genuinely non-obvious behavior: journal files are immune to deletion, and a paired backup box retains what it already received, so deletion is not fully propagated. It does not state error conditions (missing path, journal rejection) but covers the key side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, each with a distinct job: the action, the exception, and the persistence caveat. Front-loaded and zero waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter destructive tool with annotations and no output schema, the description covers scope, exclusions, and the important 'backup keeps a copy' caveat. Only path format and failure behavior are left unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for the single 'path' parameter, and the description never explains its expected format (relative vs absolute, extension, whether it names a directory or file). 'One file' only weakly implies the path targets a file, so the description does not compensate for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Delete') on a specific resource ('one file from your memory on the box'), and explicitly excludes journal files, which is the main overlap with the journal_* siblings. An agent can tell exactly what this removes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the action (remove a stored memory file) and there is a hard exclusion ('Journal files can't be deleted'), but no guidance on when this is preferable to alternatives or on prerequisites such as knowing the path via memory_list/memory_read.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_listList memory filesA
Read-only

List the files in your memory, optionally under a folder prefix like 'people' or 'projects/keephaven'.

NameRequiredDescriptionDefault
prefixNofolder to list, e.g. 'people'

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds the useful scoping detail that listing is confined to "your memory" and may be narrowed by folder prefix, but it says nothing about what is returned (names vs. paths), ordering, or whether listing is recursive under a prefix.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the optional-prefix caveat is attached inline rather than padded into extra sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-required-param read tool with annotations covering safety, the description is nearly sufficient. The one remaining gap, given no output schema, is that it never says what the listing contains or whether results are recursive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents prefix with an example. The description adds only a second example with a nested path ('projects/keephaven'), which hints at hierarchical prefix matching but doesn't confirm whether matching is recursive or one level deep.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("List the files in your memory") with the optional scoping dimension. It does not name how it differs from siblings like memory_search or memory_read, so an agent must infer that this enumerates rather than retrieves content.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the word "List" and the folder-prefix note, but there is no explicit when-to-use guidance and no mention of memory_search as the alternative when the agent wants content rather than filenames.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_readRead a memory fileA
Read-only

Read one file from your memory. Returns its text and an etag; pass the etag to memory_write to avoid overwriting a newer copy.

NameRequiredDescriptionDefault
pathYese.g. 'people/dafarus.md'

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and the description is fully consistent with a safe read. It adds value beyond the annotations by disclosing the return shape (text and etag) and explaining the etag's role in optimistic concurrency for memory_write — behavior an agent would otherwise not know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, both earning their place: the action first, then the return value and its downstream use. Zero filler and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description correctly covers return values and the etag contract, which is the key missing piece for a read tool. Minor gaps remain around non-existent paths and how path namespaces are structured, but the essentials for correct invocation are present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Single parameter with 100% schema coverage, so the schema's example ('people/dafarus.md') already carries the semantics. The description adds nothing about path resolution, namespaces, or whether paths are relative to a root, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource — 'Read one file from your memory' — which distinguishes it from list/status siblings by scoping the operation to a single file. It stops short of naming memory_list or memory_search as the alternative for multi-file retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is one concrete usage hint: pass the returned etag to memory_write to avoid overwriting a newer copy, which implies the read-before-write pattern. However, no guidance is given on when to use this versus memory_list or memory_search, and no error conditions (e.g. missing file) are described.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_statusMemory statusA
Read-only

Who you are on this Keephaven, whether you can write, and how much of your quota is used.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already establishes that this is a safe read operation. The description adds useful behavioral context beyond that by disclosing that the tool reports write capability and quota consumption, though it does not detail authentication requirements or exact response fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise sentence with no redundant text. It front-loads the main status dimensions the agent would care about.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only status tool with no output schema, the description covers the key information an agent needs: identity, write permission, and quota usage. It does not specify exact return fields or formatting, but no output schema exists to carry that detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is no parameter semantics burden. The schema is empty and needs no additional explanation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description identifies the status report's contents: current identity, write permission, and quota usage. It is more specific than the tool name, though it does not use an explicit verb like 'returns' or 'reports' and does not directly differentiate itself from sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the listed contents: an agent would use this when it needs to know its identity, whether writes are allowed, or remaining quota. However, the description gives no explicit when-to-use guidance, exclusions, or comparison to alternatives like memory_read or memory_list.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_writeWrite a memory fileA
DestructiveIdempotent

Create or replace one file in your memory (UTF-8 text, up to 10 MB). Paths are plain segments of letters, digits, _ . - separated by '/'. journal/ is not writable here: use journal_append.

NameRequiredDescriptionDefault
pathYese.g. 'projects/keephaven.md'
contentYesthe whole new content of the file
if_matchNoetag from memory_read; the write fails if the file changed since

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=true, so the safety profile is covered, and 'create or replace' is consistent with it. The description adds real constraints beyond annotations: UTF-8 text, 10 MB cap, and the journal/ write restriction. It does not say whether intermediate directories are created or what the call returns (e.g. an etag for later if_match).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the action and scope, then size/type limits, then the sibling exclusion. Every clause carries information the agent needs; nothing is redundant with the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description avoids needing to explain return values, and it covers the write scope, size limit, path syntax, and the journal carve-out. The remaining gap is that it never hints at what a successful write returns, which matters because if_match depends on an etag from memory_read.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3. The description still earns a bump by specifying path construction rules (allowed characters and '/' separation) that the schema only illustrates with an example. It adds nothing on if_match, which the schema already explains.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Create or replace one file in your memory') and immediately bounds it to a single file. It also names the sibling it is not (journal_append) and the condition that selects that sibling, so an agent can distinguish it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit exclusion with the correct alternative: 'journal/ is not writable here: use journal_append.' That is clear routing guidance, but it only covers the journal case; there is no guidance on when to use memory_write versus memory_delete or on when concurrency control (if_match) matters.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 8 tool updatesv0.1.0
    • First observedjournal_append
    • First observedjournal_read
    • First observedmemory_delete
    • First observedmemory_list
    • First observedmemory_read
    • First observedmemory_search
    • First observedmemory_status
    • First observedmemory_write

TDQS

A4.1/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct resource-action pair: memory file operations, append-only journal operations, search, and status. The boundary between memory_write and journal_append is explicitly clarified, preventing likely misselection.

Naming Consistency5/5

All tools follow a predictable resource_action pattern: memory_* for file memory and journal_* for journal operations. The convention is consistent and easy to infer.

Tool Count5/5

Eight tools are well-scoped for a memory/filesystem server with an append-only journal. Each tool has a clear role without excessive fragmentation.

Completeness5/5

The set covers memory file CRUD (read/write/list/delete), identity and quota status, search across memory and journal, and append/read journal lifecycle. The append-only journal intentionally omits edit/delete operations, so the surface is complete for the stated domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables AI assistants to read and write a local, encrypted-by-default memory store, so they can share persistent notes and context across sessions and models on your machine.
    38 npm
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to automatically capture durable knowledge and retrieve only relevant, token-bounded context from a secure local-first long-term memory, with support for progressive disclosure, snapshots, health diagnostics, and background tasks.
    Apache 2.0