MCP server · agent memoryMCP 伺服器 · agent 記憶

Remember the decision, not just the text.

記住的是決策,不只是文字。

A Python MCP server that files what an agent learns as decisions, resolved issues, open questions, or knowledge, in one SQLite file per workspace. Records that get used rank higher; a decay job lowers the ones nobody touches.

一個 Python 寫的 MCP 伺服器,把 agent 學到的東西分成決策、已解決的問題、待解問題與知識,每個工作區存成一個 SQLite 檔。常被用到的紀錄排得比較前面,沒人碰的由衰減排程慢慢調低。

Python 3.11+FastMCP · stdio / HTTPNot actively maintained目前沒有持續維護
Tool calls · workspace my-project工具呼叫 · 工作區 my-project18 tools18 個工具
› memory_store("Decided to use SQLite | zero setup")Decision recorded [my-project]: Decided to use SQLite (id: e63c4402)› memory_reinforce("e63c4402")Reinforced 'e63c4402' in decisions [my-project]: salience 1.00 → 1.20› memory_search("fastmcp")Local search 'fastmcp' (1 results, sorted by salience):  [my-project] 77a435c3 | FastMCP serves /mcp over HTTP | sal=1.05 | ["mcp", "http"]› memory_compact()[my-project] session.md status: OK  Lines: 2 | Chars: 45 | Estimated tokens: 31
18MCP tools registered已註冊的 MCP 工具
4Record types, one table each紀錄類型,各有一張表
1.5Estimated tokens per CJK character每個 CJK 字元的估計 token 數
v0.1.0The only version, March 2026唯一的版本,2026 年 3 月
What it does它做什麼

Structured recall, not a note dump.

有結構的回想,不是一堆筆記。

Writes always go to the current workspace's SQLite file. Oracle and OpenAI are optional and only come into play when reading.

寫入一律進目前工作區的 SQLite 檔。Oracle 與 OpenAI 都是選配,只在讀取時派上用場。

01

Four record types

四種紀錄類型

Decisions keep what, why, and how. Resolved issues keep what and how. Open questions carry a priority from 1 to 3. Everything else is a knowledge item with a title, content, and tags.

決策記下做什麼、為什麼、怎麼做;已解決的問題記下問題與解法;待解問題有 1 到 3 的優先度;其餘都是有標題、內容與標籤的知識項目。

memory_record_*
02

One call to store

一個呼叫就能存

memory_store picks the type from English keywords such as decided, fixed, or a question mark, and splits a decision's what | why | how on the pipes.

memory_store 依英文關鍵字判斷類型,例如 decided、fixed 或半形的 ?,再用 | 把決策拆成做什麼、為什麼、怎麼做。

memory_store
03

Salience instead of deletion

用重要度取代刪除

A read or a local search hit multiplies salience by 1.05, memory_reinforce by 1.2, capped at 2.0. The decay job multiplies anything untouched for 30 days by 0.95 and never deletes a row.

每次讀取或本地搜尋命中,重要度乘以 1.05;memory_reinforce 乘以 1.2,上限 2.0。衰減排程把 30 天沒被碰過的紀錄乘以 0.95,但從不刪除資料。

python -m mcp_memory --decay
04

Search with fallbacks

逐層退回的搜尋

With Oracle and an OpenAI key, memory_search runs cosine vector search. With Oracle alone, a text match ranked by salience. With neither, a text match across every mapped workspace.

有 Oracle 加 OpenAI 金鑰時,memory_search 做 cosine 向量搜尋;只有 Oracle 時,改用依重要度排序的文字比對;兩者都沒有,就比對所有已對應的工作區。

memory_search
05

CJK-aware session check

CJK 感知的 session 檢查

memory_compact weighs session.md at 1.5 tokens per CJK, kana, or Hangul character, 2.0 per emoji, 0.25 otherwise, and flags it past 3,000 tokens or 100 lines. The agent does the trimming.

memory_compact 估算 session.md 時,CJK、日文假名與韓文每字算 1.5 token,emoji 算 2.0,其他算 0.25,超過 3,000 token 或 100 行就提醒壓縮,實際整理交給 agent。

memory_compact
06

Audit and report queries

稽核與報告查詢

Four read-only tools search an Oracle AUDIT_LOG by keyword, date, sender, or H/M/L importance, count it, and read DAILY_REPORTS and ACTIVITY_LOG. Something else has to fill those tables.

四個唯讀工具可以依關鍵字、日期、寄件者或 H/M/L 重要性搜尋 Oracle 的 AUDIT_LOG、做統計,也能讀 DAILY_REPORTS 與 ACTIVITY_LOG。這些表要由別的程式寫入。

memory_audit_search

One note, four tables

一則紀錄,四張表

You pass one string. English keywords in it choose the table, and SQLite gets a single row.

你傳一串文字。裡面的英文關鍵字決定表,SQLite 只會多一列。

  1. Pick a type

    Words like decided or fixed pick the table, and a halfwidth question mark files a question.

  2. Decision

    Use | to split that row into what, why, and how.

  3. Resolved

    One pipe is enough here: problem on the left, fix on the right.

  4. Question

    Leave it out and the priority stays at 2, the middle.

  5. Knowledge

    The title keeps the first 100 characters, and the whole string is the body.

  • keywords read
  • table picked
  • one row written
Only those English keywords count. A fullwidth question mark is not a question, and everything else becomes knowledge.
  1. 判斷類型

    decided 或 fixed 這類字決定表,半形問號則當成問題。

  2. 決策

    用 | 隔開,拆成做什麼、為什麼和怎麼做。

  3. 已解決

    這裡一個 | 就夠,左邊是問題,右邊是解法。

  4. 待解問題

    沒填的話,優先度就是 2,中間那一檔。

  5. 知識

    標題只留前 100 個字,整段字串當內容。

  • 看過關鍵字
  • 表選好了
  • 寫進一列
只認這些英文關鍵字。全形問號不算問題,對不上的字就進知識表。

session.md runs long

session.md 太長時

It reads the file and returns a status. Shortening the file is left to the agent.

它讀完檔,回你一個狀態。檔案要由 agent 自己縮短。

  1. Line count

    Cross 100 lines and this check flags the file by itself.

  2. Token estimate

    The rough weights are 1.5 for CJK, kana, and Hangul, 2 for emoji, and 0.25 for the rest.

  3. Verdict

    Either limit sets the status to COMPACT RECOMMENDED, and the file stays as it is.

  • lines counted
  • tokens estimated
  • file left as is
Crossing 3000 tokens flags the file.
  1. 行數

    過了 100 行,光這一項就會標記。

  2. token 估算

    粗算時,漢字、假名和韓文字算 1.5,emoji 算 2,其他字元算 0.25。

  3. 判定

    任一項超過,狀態就是 COMPACT RECOMMENDED,檔案原樣留著。

  • 行數算完
  • token 也估了
  • 檔案維持原樣
超過 3000 token 會標記這個檔。
Architecture系統架構

Where the data lives.

資料放在哪裡。

Local tools resolve a workspace, then read or write that workspace's SQLite file. Oracle, when configured, is only ever queried, never written to.

本地工具會先判斷工作區,再讀寫該工作區的 SQLite 檔。有設定 Oracle 時只會查詢它,從不寫入。

Tool call → workspace → store工具呼叫 → 工作區 → 儲存
MCP clientMCP 用戶端Claude Code · stdioAny client over HTTP任何走 HTTP 的用戶端127.0.0.1:8787/mcp
mcp_memory18 FastMCP tools18 個 FastMCP 工具Workspace from MEMORY_WORKSPACE or cwd工作區取自 MEMORY_WORKSPACE 或 cwdUpdates salience on read讀取時更新重要度
Stores儲存SQLite per workspace: read and write每個工作區的 SQLite:可讀寫Oracle, optional: read onlyOracle(選配):唯讀OpenAI embeds the query onlyOpenAI 只負責查詢向量
~/.mcp-memory/config.json · workspace-map.json · .claude-memory/memory.db

Writes stay in SQLite

寫入只進 SQLite

Oracle and OpenAI can stay disconnected. When they are connected, this server only reads them.

Oracle 和 OpenAI 可以不接。接上了,這個伺服器也只讀。

  1. MCP tool

    The usual way in is stdio, and HTTP listens only on this computer, port 8787.

  2. memory.db

    Anything that reads or writes the local tables opens this file.

  3. Oracle query

    Whatever this server asks Oracle, the statement is a SELECT.

  4. Embed query

    An OpenAI key embeds the search string alone, and stored rows stay as they are.

  • SQLite write done
  • Oracle stays read only
  • query string embedded
  • Workspace
  • Read only
  • Optional
Audit rows, daily reports, and the activity log have to be filled by something else.
  1. 工具呼叫

    平常走 stdio,HTTP 只聽這台電腦的 8787。

  2. 記憶庫

    讀寫本地表都會打開這個檔。

  3. 雲端查詢

    這個伺服器問 Oracle 的時候,下的都是 SELECT。

  4. 查詢向量

    OpenAI 金鑰只用來把查詢字轉成向量,存好的列不會改。

  • SQLite 寫完了
  • Oracle 只讀
  • 查詢字轉成向量
  • 工作區
  • 只讀
  • 選配
稽核列、每日報告和活動紀錄,要靠別的程式寫進去。
Design decisions設計取捨

Why it is shaped this way.

為什麼這樣設計。

01

Typed tables over one memory blob

分表存放,而不是一整包記憶

Decisions, fixes, questions, and knowledge have different fields and lifetimes. Separate tables let an agent list open questions by priority or pull a decision together with its reasoning.

決策、修正、問題與知識,欄位不同,保存的時間也不同。分表存放,agent 才能依優先度列出待解問題,或把決策連同理由一起找出來。

02

Fade instead of delete

淡出,而不是刪除

Salience only changes ranking. Decay lowers a score and never removes a row, so an old record can still be listed or fetched by id; it just ranks lower in search.

重要度只影響排序。衰減只降分數、不刪資料,舊紀錄仍然可以列出來或用 ID 取回,只是在搜尋結果裡排得比較後面。

03

A character-class estimate, not a tokenizer

依字元類別估算,不用 tokenizer

The session check needs a threshold, not an exact count. Weighting characters by class adds no dependency and keeps CJK-heavy files from looking up to six times smaller than a flat 0.25-per-character rule would make them.

session 檢查需要的是門檻,不是精確的數字。依字元類別加權不必多裝套件,也避免以中文為主的檔案,被一律每字 0.25 的估算方式低估到只剩六分之一。

Scores follow use

分數跟著使用走

A higher score only changes rank. Decay lowers a number and leaves the row in place.

分數高只影響排序。衰減把數字調低,那一列還在。

  1. Read or hit

    Opening a saved record and a SQLite hit both go through the same bump.

  2. Raise score

    1.05 is the bump for a touch, 1.2 is reinforce, and 2.0 is as high as either goes.

  3. Decay job

    Rows nobody touched for 30 days are multiplied by 0.95 once each run, and the score can keep falling.

  • score bumped
  • cap stays at 2
  • old rows fade
Put --decay on a schedule when you want the pass to repeat.
  1. 讀取或命中

    打開一筆紀錄,和 SQLite 搜尋命中,走的是同一段加分。

  2. 提高分數

    碰一下是乘 1.05,reinforce 乘 1.2,兩邊到 2.0 就停。

  3. 衰減排程

    30 天沒人碰的列,每次跑乘上 0.95,分數可以一直往下。

  • 分數往上
  • 上限停在 2
  • 舊列只變淡
想讓這一步重複跑,就把 --decay 放進排程。
Start here從這裡開始

Set up in four steps.

四個步驟完成設定。

You need Python 3.11+ and bash or zsh. The server does not create its own databases, so you map a workspace and create memory.db once. These commands were run as written on 2026-09-30.

需要 Python 3.11 以上,以及 bash 或 zsh。伺服器不會自己建資料庫,所以要先對應一個工作區,並建立一次 memory.db。這些指令已在 2026-09-30 照原樣實際跑過。

Install

安裝

setup_config.py is optional; it writes paths, an Oracle wallet connection, and an OpenAI key to ~/.mcp-memory/config.json.

setup_config.py 可以不跑;它會把路徑、Oracle wallet 連線與 OpenAI 金鑰寫進 ~/.mcp-memory/config.json。

git clone https://github.com/teddashh/mcp-memory-server.git
cd mcp-memory-server
pip install -e .

Map a workspace

對應工作區

The workspace map turns an id into a folder under ~/Documents/Workspace.

工作區對應檔把一個 ID 對應到 ~/Documents/Workspace 底下的資料夾。

mkdir -p ~/Documents/claude-setup
mkdir -p ~/Documents/Workspace/my-project/.claude-memory
echo '{"my-project": "my-project"}' \
  > ~/Documents/claude-setup/workspace-map.json

Create its database

建立資料庫

Save the SQL from the README as schema.sql, then run this in the same folder.

把 README 裡的 SQL 存成 schema.sql,再到同一個資料夾執行。

python - <<'PY'
import sqlite3
from pathlib import Path
ws = Path.home() / "Documents/Workspace/my-project"
db = sqlite3.connect(ws / ".claude-memory" / "memory.db")
db.executescript(Path("schema.sql").read_text())
PY

Register and check

註冊並確認

Run it inside your project, with the Python you installed into. Then ask the agent to call memory_status: it should show my-project, zero counts, and Oracle not connected.

在你的專案裡執行,並使用安裝套件時的那個 Python。接著請 agent 呼叫 memory_status:應該會顯示 my-project、全部為零的數量,以及 Oracle not connected。

claude mcp add memory -e MEMORY_WORKSPACE=my-project \
  -- python -X utf8 -m mcp_memory

Clone, then call it

裝好才能呼叫

The server will not create memory.db. You do that before the first call.

伺服器不會幫你建 memory.db。第一次呼叫前要自己準備好。

  1. Install

    Use Python 3.11 or newer, and install the package in editable mode.

  2. Map workspace

    An id in workspace-map.json names a folder under the workspace root.

  3. Create database

    Run the SQL in the README to create memory.db.

  4. Register

    When you register the server, set MEMORY_WORKSPACE to that workspace id.

  • package installed
  • map file written
  • database ready
Ask for a status check and you should see this workspace, counts at zero, and Oracle disconnected.
  1. 安裝套件

    Python 要 3.11 以上,套件用可編輯模式裝。

  2. 對應工作區

    workspace-map.json 的 id 會指向工作區根目錄下的一個資料夾。

  3. 建立資料庫

    先跑 README 裡的 SQL,把 memory.db 建出來。

  4. 註冊伺服器

    註冊伺服器時,把 MEMORY_WORKSPACE 設成那個工作區 id。

  • 套件裝好了
  • 對應檔寫好
  • 資料庫好了
問一次狀態,該看到這個工作區、筆數是 0,Oracle 還沒連上。
Honest status誠實的現況

Where it stands.

目前的樣子。

v0.1.0 was written and published on 2026-03-31, and its functionality has not changed since. It is not actively maintained. It still loads on current FastMCP, and the local tools work once the database exists.

v0.1.0 在 2026-03-31 寫完並發布,之後功能沒有再變更,目前沒有持續維護。它在目前的 FastMCP 上仍能載入,資料庫建好之後,本地工具都能正常使用。

Checked on 2026-09-30

2026-09-30 實測可用

  • All 18 tools register on fastmcp 4.0.10, the latest release at the time
  • 18 個工具都能在 fastmcp 4.0.10(當時的最新版)上註冊
  • The four setup steps on this page, run as written in an empty home directory; claude mcp list shows the server connected
  • 本頁的四個設定步驟,在全新的家目錄照原樣跑過;claude mcp list 顯示伺服器已連線
  • With a prepared memory.db: store, list, get, delete, reinforce, local search, and the session check
  • memory.db 準備好之後:儲存、列出、取回、刪除、強化、本地搜尋與 session 檢查都正常
  • Salience tracking on reads, and the --decay job
  • 讀取時的重要度追蹤,以及 --decay 衰減排程
  • stdio by default; --http serves streamable HTTP at 127.0.0.1:8787/mcp
  • 預設走 stdio;--http 會在 127.0.0.1:8787/mcp 提供 streamable HTTP
  • Interactive setup_config.py for paths, an Oracle wallet, and OpenAI embeddings
  • 互動式的 setup_config.py,可以設定路徑、Oracle wallet 與 OpenAI embedding

Limits and not yet

限制與尚未完成

  • No schema or migrations: you create memory.db, the workspace map, and any Oracle tables
  • 沒有 schema 也沒有 migration:memory.db、工作區對應檔與 Oracle 的表都要自己建
  • Oracle is the only cloud database in the code, and nothing here syncs SQLite to it, writes embeddings, or fills the audit tables
  • 程式裡唯一的雲端資料庫是 Oracle,而且沒有任何程式會把 SQLite 同步過去、寫入 embedding,或填入稽核相關的表
  • Search covers knowledge items only, and the vector path ignores salience
  • 搜尋只涵蓋知識項目,而且向量搜尋不看重要度
  • Auto-classification reads English keywords only; a full-width ? is not treated as a question
  • 自動分類只認英文關鍵字;全形的「?」不會被當成問題
  • Decay has no floor and applies once per run, so its pace depends on your scheduler
  • 衰減沒有下限,每執行一次就套用一次,速度取決於你的排程
  • Secrets are saved as plain JSON, and there are no tests or releases
  • 機密資訊以明文 JSON 儲存;沒有測試,也沒有 release
Version版本
0.1.0
License授權
MIT
Stack技術
Python · FastMCP · SQLite
Optional選配
Oracle · OpenAI embeddings
Last feature change最後功能更新
2026-03-31
Verified查核日期
2026-10-06

More from Ted Huang. Every public project has a page like this one, in English and Traditional Chinese.

Ted Huang 的其他作品。每個公開專案都有一頁像這樣的中英雙語介紹。

All projects →全部專案 →