330899935

Apiary Memory MCP

Community 330899935
Updated

Apiary Memory — local-first memory your AI agents share over MCP. Agents propose; only you confirm. Plain files on your own disk. (formerly 记忆蜂巢 / Memory Hive)

Apiary Memory MCP

Also known as: Apiary Memory · 记忆蜂巢 · Memory Hive · 蜂巢 ·apiary-memory on PyPI and io.github.330899935/apiary-memory on the MCP Registry (from v0.2.0) ·old names memory-hive-mcp / hive-memory (v0.1.9 and earlier) still install and still work.Not affiliated with hive.com (team collaboration) or the hive-mcp Claude Code plugin.

Local-first personal memory for AI agents, over MCP. Your agents can search what you haveconfirmed and propose what they think you should keep; only you can confirm it. Everythinglives in one file on your own disk, and nothing is sent anywhere.

It runs on its own. A working SQLite memory store ships inside this package — no account, nocloud, no daemon, no dependencies.

pip install apiary-memory

Desktop app, no terminal: download apiary-memory-0.2.0.mcpb and double-click it.

Measured on 2026-10-27, on one MacBook with the Hive running locally — script and raw output in bench/:

Measure Result
Search latency p95 111 ms, p50 76 ms (warm, includes HTTP)
Retrieval correct entry in top-5 for 97.5% of 40 trials
Corpus 1,303 entries · 2.39 M chars · 45 days, plaintext only

Retrieval used each entry's own title as the query — an easy set. It shows the index is complete and ranks correctly on exact terms, not how well it answers a question asked in your own words. Run bench/bench_search.py on your own Hive.

What you get without the app

A complete, if modest, memory server. On a machine with nothing else installed:

Call What happens
initialize answered locally, protocol 2024-11-05
tools/list answered locally, six tools
propose writes to a real database on your disk
recall searches that database and returns ranked entries
get_context a digest of what you confirmed most recently
manage read one entry, list what is pending, forget, restore
say / board a shared message board for coordinating several agents

Storage is SQLite at ~/.memory-hive/hive.db by default. Search is lexical — character bigramsfor Chinese, words for Latin script — so it ranks well when the words overlap and finds nothingwhen they do not. There are no embeddings and no vector index. Every response says"mode": "local" so you can always tell which engine answered.

Without the app, the database is plain SQLite: it is not encrypted. That is stated hererather than discovered later — see Honest limits.

What the app adds

Apiary Memory for macOS is the same design with theexpensive parts built: eight vaults with four of them locked behind a PIN (Argon2id-wrapped key,AES-256 at rest), a daily evolution log, multi-agent identity management, and a UI for readingand confirming. It also answers MCP itself, with richer ranking.

If the app is running, this package uses it and leaves the local file alone. If it is not, thelocal store answers. You do not have to choose up front:

HIVE_MODE Behaviour
auto (default) Ask the app. Use the local store only if the app is unreachable.
local Never touch the network. Always use the local store.
remote Only the app. A connection failure is an error, not a reroute.

One rule holds in every mode: if the app is running and answers with an error, that error isreturned unchanged. Falling back on a refusal would write your memory into a second databasewhile your client believed it had reached the app. Silent data forking is worse than an errormessage, so a reply from the app is final. The fallback fires on a connection failure, and onnothing else.

Install

pip install apiary-memory        # the server: apiary-memory (was memory-hive-mcp)
                                 # the human's CLI: apiary-memory-cli (was memory-hive-mcp-cli)

Python 3.8 or newer. There is nothing else to install — the package uses only the standardlibrary, and sqlite3 is part of it.

From a checkout:

git clone https://github.com/330899935/apiary-memory
cd apiary-memory
PYTHONPATH=src python -m hive_mcp.stdio

Connect a client

Any MCP host that can run a stdio command will work. The minimum is the command; everything elseis optional.

Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "apiary-memory": {
      "command": "apiary-memory",
      "env": { "HIVE_MODE": "local" }
    }
  }
}

Cursor — ~/.cursor/mcp.json, same mcpServers shape.

Any host that only speaks HTTP — start the app and point it at http://127.0.0.1:8768/mcpwith the headers X-Hive-Agent and X-Hive-Token. This package is the stdio path; the HTTPendpoint belongs to the app.

Prerequisite

None, for the local store — install the package and it works. A running app is a prerequisiteonly for the app's own features: encrypted vaults, the evolution log, and multi-agent identity.If you want those, install the Hive app (macOS,version 1.4.5 or newer) and leave HIVE_MODE at auto.

The six tools

The six tools are the whole surface. They are the same six whether the app or the local storeanswers; only the ranking behind them differs — and, for two inputs, whether they exist at all.The app accepts precomputed embeddings (recall.query_vector, propose.vector); the localstore has no embedder, so tools/list omits those two wherever the local store can answer,including under auto where the app might stop answering mid-session. A field that would beaccepted and silently ignored is not advertised at all.

The same rule covers wording. recall.query is described as the lexical ranker it is whereverthe local store can answer — words and character bigrams, no embeddings — and as the app'sindex-based ranking with query_vector for meaning wherever only the app can answer. Adescription is a claim about what will happen to the input, so it is narrowed with the inputs.

Defaults are not narrowed, they are shared. Omit limit and you get 10 from recall and 8 fromget_context; omit compact and bodies come back trimmed; omit ttl on say and the cardlives 24 hours. Both engines answer those numbers identically, because a default is a number inthe schema rather than a capability one engine lacks. store.py holds each one as a namedconstant, and the tests compare the answer against the advertised number instead of a secondhand-written copy of it.

Tool Kind What it is for
recall read Search confirmed memory by topic. {"query": "..."} plus optional limit, vaults, compact.
propose write Submit a memory for the human to approve. Lands in a queue; changes no confirmed memory.
manage read/write Address one entry: list_pending, get_by_id, forget, restore, discard_pending.
get_context read A short digest of recent confirmed memory, to seed a conversation.
say write Post to the shared board so other agents see what was done or handed over.
board read Read the board, optionally only what arrived since your last cursor.

Two properties are worth stating plainly, because they are the product:

  • propose succeeding means "queued", not "stored". recall will not return it until ahuman confirms it.
  • manage has no approve action. There is no path from an agent to a confirmed memory.That is not an omission; it is the design.

Response shapes

tools/list is one surface for both engines, and an answer should be too: a model that hasto branch on which engine replied will eventually branch wrong. board therefore answersthe app's shape, field for field — items, unread, count, cursor, reader — andcursor is the id of the newest card, the same kind of value the app returns.

The cursor is what a poll carries across an engine switch, which is why it gets the space.Under auto one call can be answered by the app and the next by the local store. Before 0.1.9the local engine answered a float epoch timestamp and read the app's card id with float(),so a cursor fetched from the app came back as a full re-read of the board and nothing saidso; a float sent the other way matched no card id, and the app answered with its newestlimit, equally quietly.

A cursor can still fail to resolve: its card expired (cards live 24 hours by default), or itwas issued by the other engine, whose ids are CB… in the app and msg_… here. Neitherengine can resume from that, so both return the newest window — but this one also setssince_unknown and a note saying which of those happened. unread counts every live cardafter the cursor and count counts what the answer carries, so unread > count means thepage did not cover everything waiting, and the note says so in words.

Three shapes are not unified, because the engines really do hold different data:

  • a recall entry names its vault vault from the local store and wh from the app;
  • get_context returns one flat digest locally and one bucket per warehouse (context,keyed by warehouse name) from the app;
  • roster entries share agent_id; locally they also carry messages and last_seen,while the app adds its registry card — display name, seat, leases, current task — which aSQLite file has no way to know.

Confirming what agents propose

Agents propose. You confirm. The confirmation lives in a terminal, in a command you have totype — deliberately not a tool an agent can call.

apiary-memory-cli list                 # what is waiting
apiary-memory-cli show <id>            # read one in full
apiary-memory-cli approve <id>         # confirm it, or --all
apiary-memory-cli reject <id>          # drop it for good
apiary-memory-cli search "deploy key"  # search confirmed memory
apiary-memory-cli forget <id>          # soft delete, reversible
apiary-memory-cli restore <id>         # undo forget
apiary-memory-cli stats                # counts and the database path
apiary-memory-cli export --out dump.json
apiary-memory-cli path

--db <path> on any command points at a different database. HIVE_DB does the same from theenvironment.

Where your memory lives

~/.memory-hive/hive.db, unless HIVE_DB says otherwise. One SQLite file; copy it to back itup, delete it to start over.

The board keeps its messages in the same file, so there is only ever one thing to back up. Cardsexpire: 24 hours unless ttl says otherwise, clamped to between 60 seconds and 30 days, whichis what the app does too — a board that grows forever stops being a board.

How search works, and what it does not do

Chinese text is indexed as single characters plus overlapping character bigrams; Latin text aswords. A query is scored by how much of it the entry covers, then nudged by recency — a 10%multiplier, enough to break ties and not enough to overturn relevance.

This is a ranker, not an understander.

  • Scores are relative. 0.8 means "closer than 0.4 for this query", not "80% confident".They are not comparable across queries.
  • No semantic recall. Ask about "money" and an entry that only says "invoice" will not befound. Related-word coverage needs an embedder; this package has no dependencies and does notpretend otherwise.
  • The ranking is the one the description states. tools/list says "words and characterbigrams ... no embeddings" here, and that sentence is true of this engine. It is narrowed perengine like the embedding inputs are, because the app's answer to the same question differs.
  • A miss is reported as a miss. When nothing matches, recall says so and mentions how manyentries are awaiting confirmation, rather than returning a plausible neighbour.

Configuration

Variable Default Purpose
HIVE_MODE auto auto, local, or remote — see the table above
HIVE_DB ~/.memory-hive/hive.db Where the local database lives
HIVE_MCP_URL http://127.0.0.1:8768/mcp The app's endpoint
HIVE_AGENT_ID — Agent id from the app; only for calls the app serves
HIVE_AGENT_TOKEN — Access token from the app; only for calls the app serves

HIVE_AGENT_ID and HIVE_AGENT_TOKEN are not required to use the local store. They areread straight from the environment and never written to disk by this package.

Honest limits

Written down because a memory tool that oversells itself is worse than one that does less.

  1. The local store is not encrypted. Plain SQLite. Anyone who can read your home directorycan read it. The app's vaults are the encrypted option, and stats reports"encrypted": false instead of leaving you to find out.
  2. No semantic search, as above.
  3. One writer at a time. WAL mode lets the CLI confirm while a server is connected, but thisis a personal memory file, not a multi-host service. Do not point two machines at onedatabase over a network share.
  4. The board is coordination, not memory. Messages are for hand-offs between agents; theyare not searchable with recall.
  5. The app is macOS only. The local store is not — it is pure Python.

Troubleshooting

"no confirmed memory matched this query" with entries pending. Correct behaviour. Confirmthem: apiary-memory-cli list, then approve.

A call fails with a message about HIVE_AGENT_ID. The app answered and refused thecredential. The call did not fall back to the local store, on purpose. Register an agent inthe app and set both variables, or set HIVE_MODE=local if you meant to use the local file.

"Hive app not reachable ... and HIVE_MODE=remote forbids the local fallback". You asked forthe app only and it is not running. Start it, or drop HIVE_MODE=remote.

Where did my memory go? apiary-memory-cli stats prints the database path. If HIVE_MODEis auto and the app is running, the app has been answering — the local file is untouched bydesign.

Development

PYTHONPATH=src python -m unittest discover -s tests -v

The suite needs no running app and no network: it stands up its own fake backend where a realresponse is required, and points HIVE_DB at a temporary file so a test never touches a realmemory database.

Layout:

src/hive_mcp/store.py   the memory engine (SQLite, stdlib only)
src/hive_mcp/stdio.py   the MCP server: routing, envelopes, the app bridge
src/hive_mcp/cli.py     the human's half: review and confirm
src/hive_mcp/tools.json the tool surface snapshot for the offline path

License

MIT. Your memory file is yours; nothing here phones home.

MCP Server · Populars

MCP Server · New

    mybolide

    Coding Tools MCP

    Give any AI agent the ability to code

    Community mybolide
    trypostit

    The open-source social media scheduler built for AI agents

    Open-source social media scheduler built for AI agents and the teams behind them. Create, schedule and publish posts to every network through MCP or the REST API, or write them yourself in a composer your team will love.

    Community trypostit
    Agoragentic

    Agoragentic

    Public adapters and discovery catalog for Triptych OS (Agent OS): agent frameworks, MCP/A2A/x402 protocols, workflows, wallets, SDKs, and examples for execute-first routing, governed handoffs, and receipt-aware agent commerce.

    Community Agoragentic
    eduard256

    Ozon MCP Server

    MCP Server for Ozon marketplace - search products, get details, prices and delivery info

    Community eduard256
    TalkToHumans

    LinkedIn MCP Server

    Safe LinkedIn MCP server for Claude, ChatGPT, Cursor & Codex. Your Agents read LinkedIn DMs, search your network, enrich profiles and draft messages you send.

    Community TalkToHumans