Memory Hive

io.github.330899935由 GitHub 帳號 330899935 發布v0.1.9更新於 Oct 29, 2026

Local-first memory over MCP. Built-in SQLite store; runs standalone. Agents propose; you confirm.

發布方自己的服務:Memory.fit

已驗證STDIO僅桌面知識與記憶溝通與協作

概覽

AI 產生的概覽

為 AI 助理設計的本地優先個人記憶伺服器:助理可搜尋已確認的記憶、提出待確認項目,並透過共享留言板協作。

可以做什麼
  • 以自然語言查詢搜尋已確認的記憶,並取得近期記憶摘要以開啟對話
  • 提出記憶供人工確認,項目進入待審佇列,確認前不會更動任何已確認記憶
  • 檢視或變更單筆記憶的生命週期:列出待審、依 id 讀取、軟刪除、還原、永久捨棄待審項目
  • 在共享留言板張貼交接訊息,並依游標輪詢新訊息
適用情境
適合希望助理跨工作階段記住決策與脈絡、又不想依賴託管服務的情況,且你願意親自確認哪些內容被保留。也適合多個代理透過同一份本機儲存交接工作。
執行需求
需要 Python 3.8+ 並安裝 pip 套件,由 MCP 用戶端以 stdio 指令啟動;本機儲存不需帳號或網路。選用的 App 模式使用 HIVE_MCP_URL(預設本機端點)以及 HIVE_AGENT_ID 與 HIVE_AGENT_TOKEN;HIVE_DB 指定資料庫路徑,HIVE_MODE 選擇 auto、local 或 remote。
安裝前請注意
本機 SQLite 資料庫未加密,能讀取你個人目錄的人即可讀取它。助理可寫入:propose 會排入佇列、say 會張貼訊息,forget 與 discard_pending 會變更或刪除資料(forget 可還原,discard 不可)。HIVE_AGENT_TOKEN 是需從環境變數讀取的機密。App 模式下發生錯誤會直接回傳而不回退,HTTP 通道的流量經 Cloudflare 轉送。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Memory Hive,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

Apiary Memory MCP

[Listed on mcpservers.org]

At a glance

What it isLocal-first personal memory for AI agents, over MCP. Agents can search what you have confirmed and propose what to keep — only you can confirm it. Everything lives in one SQLite file on your own disk.
What it is notNot a hosted service. No account, no cloud, no telemetry, no daemon. The server runs on your machine (127.0.0.1), not ours.
PlatformsDesktop app: macOS 10.15+. Companion app: iOS 17.0+. Pip package: any OS with Python 3.8+. There is no Windows desktop app.
Installpip install apiary-memory · or double-click apiary-memory-0.2.1.mcpb
Version0.2.1 on PyPI · desktop app 1.4.8

Two entry points — and they are not the same

CommandWhat it isWhat happens when you run it
apiary-memoryThe MCP server (stdio)Meant to be spawned by your MCP client. Run it in a terminal and it just waits on stdin — that is correct behaviour, not a hang.
apiary-memory-cliThe human CLIlist pending candidates · approve <id> commit one · search <query> · stats show where the DB lives

python -m hive_mcp does not work — this package has no __main__.py.

The pip package has no GUI and never pops a dialog. When an agent calls propose, the entry goes into a local candidate queue and stays there. Nothing enters the hive until a human runs apiary-memory-cli list and then approve <id>. If you want a window, use the macOS or iOS app.

Not to be confused with

NameStatus
hive-memoryDoes not exist on PyPI (404). Any document citing it is wrong — including AI answers about us.
memory-hive-mcpOur own former name. Still installs, but caps at 0.1.9. Use pip install apiary-memory for the current release.
hive-mcpSomeone else's Claude Code plugin.
hive.comTeam collaboration software.
theapiary.sh"the apiary" — shared memory for AI coding agents; its memory component is called honeycomb.
apiarybee.com"Apiary" — a self-organizing agent framework.
记忆蜂巢 (Chengdu Zhixin Hualao)An unrelated iOS group-chat app. Same four characters, nothing else in common.

Also known as: Apiary Memory · 记忆蜂巢 · Memory Hive · 蜂巢 · apiary-memory on PyPI · io.github.330899935/apiary-memory on the MCP Registry (from v0.2.0).

Your agents can search what you have confirmed and propose what they think you should keep; only you can confirm it. Everything lives 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, no cloud, no daemon, no dependencies.

bash
pip install apiary-memory

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

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

MeasureResult
Search latencyp95 111 ms, p50 76 ms (warm, includes HTTP)
Retrievalcorrect entry in top-5 for 97.5% of 40 trials
Corpus1,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:

CallWhat happens
initializeanswered locally, protocol 2024-11-05
tools/listanswered locally, six tools
proposewrites to a real database on your disk
recallsearches that database and returns ranked entries
get_contexta digest of what you confirmed most recently
manageread one entry, list what is pending, forget, restore
say / boarda shared message board for coordinating several agents

Storage is SQLite at ~/.memory-hive/hive.db by default. Search is lexical — character bigrams for Chinese, words for Latin script — so it ranks well when the words overlap and finds nothing when 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 here rather than discovered later — see Honest limits.

What the app adds

Apiary Memory for macOS is the same design with the expensive 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 reading and 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, the local store answers. You do not have to choose up front:

HIVE_MODEBehaviour
auto (default)Ask the app. Use the local store only if the app is unreachable.
localNever touch the network. Always use the local store.
remoteOnly 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 is returned unchanged. Falling back on a refusal would write your memory into a second database while your client believed it had reached the app. Silent data forking is worse than an error message, so a reply from the app is final. The fallback fires on a connection failure, and on nothing else.

Measured on the app

The numbers below come from the macOS app's local HTTP service on one MacBook — not from this package's SQLite store, which is a different engine over a different dataset. Mixing the two would be the usual benchmark trick, so they are kept apart.

Store size (four plaintext vaults)1,356 entries, 2.52M chars, 47 distinct days
Retrieval hit rateTop-5 92.5%, Top-20 95.0% (n=40)
Latency (local HTTP, incl. round trip)p50 90 ms, p95 127 ms

Measured 2026-10-29 against the live service. The hit-rate queries were each entry's own title — the easy case. It shows the index is complete; it does not show that free-form questions land. A separate pilot using plainly-phrased questions found the right entry in the top 5 only twice out of roughly a dozen, which is the biggest known weakness of this version.

The four encrypted vaults are excluded from the count because they are unreadable by design. A load test at 1,000,000 synthetic entries gave 0.6 s warm search, 5.3 GB RSS and a 1.0 GB index — see bench/ for the script and raw output.

Install

bash
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 standard library, and sqlite3 is part of it.

From a checkout:

bash
git clone https://github.com/330899935/apiary-memorycd apiary-memoryPYTHONPATH=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 else is optional.

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

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/mcp with the headers X-Hive-Agent and X-Hive-Token. This package is the stdio path; the HTTP endpoint belongs to the app.

Two ways to connect

There are two doors onto the same memory. Which one you use depends on where your AI runs, not on what it can do.

Local (MCP)Web (HTTP)
Built forAIs installed on your MacAIs running on someone else's servers
How you connecta stdio command in a config filepaste one address
Networknone — never leaves the machinepublic, relayed by Cloudflare
Available sincethis package, 0.1.0Desktop app 1.4.8

Behind both doors is the same home: what a local AI stores today, a web AI can read tomorrow — and the other way round. Swap in a hundred AIs; there is still one memory, and it is on your disk.

The web (HTTP) door

An AI running on the web cannot reach your Mac. So the Desktop app opens a channel outwards. In the app, open AI Connect · Web (HTTP), pick one of three levels, and copy the address:

LevelPublic?Address stable?Use when
Local webno—the AI runs on the same machine
Quick tunnelyesnoyou want a web AI in without owning a domain
Fixed addressyesyeslong-term use; needs your own Cloudflare account

If local works, do not open a tunnel. That is what the app tells you, and it is our advice here too: if local is enough, do not open the door onto the street.

Three things to know before you connect:

  1. Once connected, the AI can read your memory. It gets what it asks for, within what it is allowed to see.
  2. Over the public internet your data is relayed by Cloudflare — it is not end-to-end encrypted to the app. What is stored and what is computed stay on your Mac, but the traffic passes through Cloudflare.
  3. The four privacy vaults and the cognition layer are never opened to outside AIs — that is a wall, not a switch. No matter which level you open, they are not part of it.

Which AIs? Any client that supports remote MCP works — read-only, public vaults only. One caveat: ChatGPT uses Custom GPT Actions (OpenAPI), a different mechanism from MCP. An address alone will not work there, and that step is not built yet.

Why transport still says stdio

The package and the MCP Registry entry both declare "transport": {"type": "stdio"}. That is accurate and stays that way: this package is the stdio bridge. The web (HTTP) door is a capability of the Desktop app, not of this package. Declaring http here would make clients dial an endpoint the package does not serve, and the connection would simply fail — so the door is documented above rather than declared as a package transport.

Prerequisite

None, for the local store — install the package and it works. A running app is a prerequisite only 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 store answers; 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 local store 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 be accepted and silently ignored is not advertised at all.

The same rule covers wording. recall.query is described as the lexical ranker it is wherever the local store can answer — words and character bigrams, no embeddings — and as the app's index-based ranking with query_vector for meaning wherever only the app can answer. A description 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 from get_context; omit compact and bodies come back trimmed; omit ttl on say and the card lives 24 hours. Both engines answer those numbers identically, because a default is a number in the schema rather than a capability one engine lacks. store.py holds each one as a named constant, and the tests compare the answer against the advertised number instead of a second hand-written copy of it.

ToolKindWhat it is for
recallreadSearch confirmed memory by topic. {"query": "..."} plus optional limit, vaults, compact.
proposewriteSubmit a memory for the human to approve. Lands in a queue; changes no confirmed memory.
manageread/writeAddress one entry: list_pending, get_by_id, forget, restore, discard_pending.
get_contextreadA short digest of recent confirmed memory, to seed a conversation.
saywritePost to the shared board so other agents see what was done or handed over.
boardreadRead 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 a human 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 has to branch on which engine replied will eventually branch wrong. board therefore answers the app's shape, field for field — items, unread, count, cursor, reader — and cursor 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.9 the 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 said so; a float sent the other way matched no card id, and the app answered with its newest limit, equally quietly.

A cursor can still fail to resolve: its card expired (cards live 24 hours by default), or it was issued by the other engine, whose ids are CB… in the app and msg_… here. Neither engine can resume from that, so both return the newest window — but this one also sets since_unknown and a note saying which of those happened. unread counts every live card after the cursor and count counts what the answer carries, so unread > count means the page 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 a SQLite 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 to type — deliberately not a tool an agent can call.

bash
apiary-memory-cli list                 # what is waitingapiary-memory-cli show <id>            # read one in fullapiary-memory-cli approve <id>         # confirm it, or --allapiary-memory-cli reject <id>          # drop it for goodapiary-memory-cli search "deploy key"  # search confirmed memoryapiary-memory-cli forget <id>          # soft delete, reversibleapiary-memory-cli restore <id>         # undo forgetapiary-memory-cli stats                # counts and the database pathapiary-memory-cli export --out dump.jsonapiary-memory-cli path

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

Where your memory lives

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

The board keeps its messages in the same file, so there is only ever one thing to back up. Cards expire: 24 hours unless ttl says otherwise, clamped to between 60 seconds and 30 days, which is 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 as words. 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 be found. Related-word coverage needs an embedder; this package has no dependencies and does not pretend otherwise.
  • The ranking is the one the description states. tools/list says "words and character bigrams ... no embeddings" here, and that sentence is true of this engine. It is narrowed per engine 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 many entries are awaiting confirmation, rather than returning a plausible neighbour.

Configuration

VariableDefaultPurpose
HIVE_MODEautoauto, local, or remote — see the table above
HIVE_DB~/.memory-hive/hive.dbWhere the local database lives
HIVE_MCP_URLhttp://127.0.0.1:8768/mcpThe 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 are read 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 directory can 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 this is a personal memory file, not a multi-host service. Do not point two machines at one database over a network share.
  4. The board is coordination, not memory. Messages are for hand-offs between agents; they are 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. Confirm them: apiary-memory-cli list, then approve.

A call fails with a message about HIVE_AGENT_ID. The app answered and refused the credential. The call did not fall back to the local store, on purpose. Register an agent in the 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 for the 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_MODE is auto and the app is running, the app has been answering — the local file is untouched by design.

Development

bash
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 real response is required, and points HIVE_DB at a temporary file so a test never touches a real memory 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 bridgesrc/hive_mcp/cli.py     the human's half: review and confirmsrc/hive_mcp/tools.json the tool surface snapshot for the offline path

License

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

來源:README.md,提交 7164f7e

工具

6

recall

Recall memory

Search the human's confirmed memory by natural-language query and return the closest stored entries. Use this to find what was previously decided, recorded, or agreed. Do not use it at session start when you have no query yet - use get_context instead. Do not use it to review entries still awaiting approval - use manage with action list_pending. Annotations already declare this read-only, so this text covers what they cannot: results come from the confirmed store only, private vaults are omitted for agents not permitted to read them, and an empty list means no match rather than no memory.

輸入參數limitquery必填vaultscompact

propose

Propose a memory

Submit a memory for the human to approve. It lands in a pending queue and changes no confirmed memory. Use it when the human says to remember something, or when a decision is reached that will still matter later. Do not use it as a scratchpad for transient reasoning or for data you merely fetched. This tool cannot confirm its own writes: the entry stays pending until the human accepts it inside their own Hive, so a success response means queued, not stored. Supply client_id to make retries idempotent.

輸入參數tagstitlevaultcontent必填client_id

manage

Manage stored memories

Inspect or change the lifecycle of a specific stored memory, addressed by id or by queue state. Use list_pending to review what is awaiting the human's approval, and get_by_id to read one entry in full. forget soft-deletes and is reversible with restore; discard_pending permanently drops an entry that was never confirmed. To search confirmed memory by topic instead of by address, use recall. Except for discard_pending, every action here is reversible, which is why this is not marked destructive.

輸入參數idaction必填

get_context

Get session context

Pull a short digest of recent memory from the human's active threads and open tasks, to seed a conversation before they ask anything. Call this once at session start. For answering a specific question, use recall instead, since that searches all confirmed memory rather than only what is recent. For entries still awaiting approval, use manage with action list_pending. Annotations already declare this read-only; what they cannot say is that the digest reflects the most recent activity, so two calls minutes apart may differ.

輸入參數limit

say

Post to the shared board

Post a message to the shared board so the human and other agents see what was done or what is being handed over. Use it when finishing a unit of work, or to hand work to another agent. Do not use it to report routine steps the human did not ask about - the human reads this board. To read what others have posted, use board. Identity comes from your credential, so a caller cannot post as another agent.

輸入參數tottlkindrefsstagesummary必填task_id

board

Read the shared board

Read the shared board, optionally only what arrived since your last read. Use it to poll for messages or hand-offs addressed to you. To post, use say. Pass the previous cursor as since so a poll returns only new messages instead of the whole board. Annotations declare this read-only; note that messages expire, so an empty result can mean nothing was posted or that earlier messages have aged out.

輸入參數limitsinceroster

版本歷史

4
  1. v0.1.9最新Oct 26, 2026
  2. v0.1.8Oct 24, 2026
  3. v0.1.6Oct 22, 2026
  4. v0.1.1Oct 21, 2026

評分

已滿足適用檢查項的 90%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分
  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

其他 Memory 整合