memory-wiki
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@memory-wikiRemember that I prefer dark mode for coding."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Personal Memory Wiki
A persistent personal memory system for Claude. It accumulates, organizes, and surfaces a single user's knowledge over time, built as a Python MCP server plus nightly consolidation and weekly digest daemons. All data is plain Markdown in a local git repo. No database, no embeddings, no RAG.
This project currently lives inside the FloLey-public-website repo, in this
self-contained memory-wiki/ folder, so it can be lifted into its own repo
later with a folder copy. The code is path-agnostic via the WIKI_ROOT
environment variable.
Status: Nightly dream (automatic schedule)
The dream can run on its own, once a night, via an in-process scheduler thread
started with the server. The mode is set from the console (/ui/dream) and stored
in the wiki (dream_schedule.json): off (default), dry-run (propose nightly,
review in the morning), or execute (apply nightly). It fires once a day after a
chosen local hour; "once a day" is enforced by the presence of the day's report,
so restarts never double-run and a missed night is caught up. Nothing happens
until you switch it on.
Related MCP server: Chronos MCP
Status: Slice 9 (staged dream pipeline + editable prompts)
The dream now runs as a three-stage pipeline instead of one big call:
triage (input: policy + all short-term + the long-term index) clusters and routes each unit;
decide (per unit, reads only the touched pages) chooses the action;
write (per integrate/promote) produces the page's final content + a one-line index description.
So no call ever needs the whole long-term memory; cost scales with the number of
captures, not the wiki size. The dry-run stops after stage 2 (reports the
decisions); execute runs stage 3 and applies in one commit, with the index
regenerated by code (descriptions from stage 3). The three stage prompts are
editable files (prompts/triage.md, decide.md, write.md, seeded) viewable
at /ui/prompts; the JSON schema is injected by code so editing guidance cannot
break the contract. Each stage's model is WIKI_DREAM_MODEL by default, overridable
per stage via WIKI_DREAM_MODEL_TRIAGE / _DECIDE / _WRITE.
Status: Slice 8 (temporal items + dream execution)
Adds two things:
Temporal items (
temporal/): dated, transient things (todo, reminder, event) that live until a date, then are archived. Every item has a due date; a durable fact with no expiry belongs on a long-term page, not here.remembertakes optionaldueandtype; the daemon files dated captures here rather than into long-term knowledge;prime()surfaces the active ones.Dream execution: the dream can now apply a plan (not just propose). The model returns a structured JSON plan (full page contents, temporal items, the new index, which short-term entries were consumed); the applier writes pages, creates temporal items, updates the index, drops consumed short-term entries, expires past-due temporal items, all in one revertible commit. It never deletes long-term content. The dry-run stays;
/ui/dreamhas both a dry-run and an "Execute" button.
Status: Slice 7 (consolidation daemon, dry-run)
Slice 7 adds the dream: a consolidation pass that reads short-term memory and
the policy (DREAM.md) and proposes how to distil captures into long-term pages.
It runs as a dry-run for now: it writes a report to dream_reports/ and
changes nothing. Trigger it from the console at /ui/dream (a "Run a dream"
button) and read the report there. The policy DREAM.md ships with a default and
is seeded into the wiki on first run (never overwriting an edited one); tune it in
/ui. The model is configurable via WIKI_DREAM_MODEL (defaults to Opus) and
needs ANTHROPIC_API_KEY. Execution (actually applying the plan) is a later
slice, deliberately after iterating on the policy via dry-runs.
Status: Slice 6 (lean tool surface)
Slice 1 proved the chain end to end. Slice 2 added GitHub OAuth. Slice 3 added
short-term memory. Slice 4 added the web console at /ui. Slice 5 added rich
reading. Slice 6 consolidates the MCP surface to four tools: a small surface
is easier for the model to use correctly (fewer ways to pick the wrong tool).
MCP tools (for Claude):
prime()- call FIRST: loads the grounding context (theself/pages then the long-term and short-term indexes) in one call.read(path)- read any file: a page, an index, or a short-term entry. Tolerant of paths (a bareself/identity.mdworks) and suggests alternatives on a miss rather than asserting a file does not exist.search(query_text, max_results?)- full-text search, returningpath:line: textmatches.remember(content, summary?, tags?)- capture into short-term memory: writesshort_term/entries/{id}.md, appends to the index, commits withstm:.GET /health- liveness probe for the Docker healthcheck (public, not a tool).
Writing to long-term memory is intentionally not an MCP tool: it happens through
the web console (manual:) or the future nightly daemon, not a live
conversation. All tools honour the owner allow-list and the path guard, so
long_term/private/ is never read or searched.
Short-term memory is the open, fast-to-write layer. It accumulates as you talk;
a later consolidation phase will distil it into curated long-term pages. Over
MCP, remember is intentionally the only write path: structural long-term edits
belong to the web console or the (future) nightly daemon, not to a live
conversation.
Web console (slice 4)
A private, browser-facing console served by the same process at /ui:
/ui- overview: lists every markdown file under the wiki (the structure)./ui/page/{path}- view a page rendered from markdown./ui/edit?path=...- edit a page (or create a new one when path is empty).POST /ui/save,POST /ui/delete- write or soft-delete, committed with amanual:prefix. Soft-delete removes the file from the working tree but keeps it in git history./ui/login,/ui/auth/callback,/ui/logout- GitHub login flow.
Auth: a browser GitHub login (the same OAuth app as the MCP endpoint),
restricted to the owner (WIKI_ALLOWED_GITHUB_LOGIN), with a signed,
HttpOnly/Secure session cookie. Forms carry a signed CSRF token. Markdown is
rendered with raw HTML disabled, so stored content cannot inject markup. In
local dev (WIKI_AUTH_DISABLED=1) the login is bypassed.
One-time GitHub change required: the console callback is
https://wiki.florent-lejoly.be/ui/auth/callback, which is not a subpath of the MCP callback. Set the GitHub OAuth app's Authorization callback URL to the roothttps://wiki.florent-lejoly.be/; GitHub accepts any subpath of it, so both/auth/callback(Claude) and/ui/auth/callback(console) work.
Authentication (slice 2)
The server is protected by GitHub OAuth via FastMCP's GitHubProvider (an
OAuth proxy that runs the standard OAuth 2.1 + PKCE discovery flow Claude.ai
expects). On top of "any valid GitHub login", an allow-list middleware
(AllowedUserMiddleware) restricts access to a single GitHub account
(WIKI_ALLOWED_GITHUB_LOGIN), so the wiki stays private to its owner.
Controlled by environment:
WIKI_AUTH_DISABLED=1runs the server open. The dev compose sets this, so local development needs no secrets.Otherwise
GH_OAUTH_CLIENT_IDandGH_OAUTH_CLIENT_SECRETare required; the server refuses to start without them (production can never come up silently open).WIKI_JWT_SIGNING_KEYshould be set to a stable random value so issued tokens survive restarts and the user is not forced to re-authorize on every deploy.
In production these come from repository Actions secrets, injected by the deploy
workflow into a gitignored .env on the VPS. The /health route stays public
regardless, for the container healthcheck.
GitHub OAuth app setup (one time)
Create a GitHub OAuth App (Settings -> Developer settings -> OAuth Apps) with:
Homepage URL:
https://wiki.florent-lejoly.beAuthorization callback URL:
https://wiki.florent-lejoly.be/auth/callback
Then set the repository Actions secrets GH_OAUTH_CLIENT_ID,
GH_OAUTH_CLIENT_SECRET, WIKI_JWT_SIGNING_KEY (names must not start with
GITHUB_, which GitHub reserves).
Architecture
Transport: Streamable HTTP, MCP mounted at
/mcp, listening on:8765.Data: a Docker named volume
wiki_datamounted at/srv/wiki. The entrypoint seeds it fromseed/only if empty, thengit inits it, so redeploys never clobber data.Public URL:
https://wiki.florent-lejoly.be/mcp, fronted by Caddy (auto-HTTPS) in the maindocker-compose.yml.
Tests
The logic (storage, temporal items, the dream pipeline, path guard, prime) is
covered by a fast pytest suite that runs against a throwaway wiki, with git
commits stubbed. From memory-wiki/:
pip install pytest # or: pip install -e ".[dev]"
pytest -qThe suite also runs in CI on every push. The tests need no API key or network: the model-calling steps are stubbed.
Run locally
From the repo root:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build mcp-serverThen:
# Liveness
curl -s localhost:8765/health # -> {"ok": true}
# Inspect tools and call them interactively (Streamable HTTP transport)
npx @modelcontextprotocol/inspector
# connect to: http://localhost:8765/mcp
# call ping, then read_long_term_indexConnect Claude.ai (after deploy + DNS)
Make sure
wiki.florent-lejoly.beresolves to the same public IP asflorent-lejoly.be(one DNS record, see the deploy note below).In Claude.ai: Settings -> Connectors -> Add custom connector.
URL:
https://wiki.florent-lejoly.be/mcp.Claude redirects you to GitHub to log in and consent. Only the allow-listed GitHub account can use the tools.
Ask Claude to call
ping, thenread_long_term_index().
Deploy note (one manual prerequisite)
The build and deploy are automated by the repo's GitHub Actions workflow (a
floley-public-website-mcp image is built and pushed, then the VPS pulls it).
The only manual step is the DNS record for wiki.florent-lejoly.be. Caddy
issues HTTPS automatically on the first request once DNS resolves.
Layout
memory-wiki/
Dockerfile
docker-entrypoint.sh # seed-if-empty + git init, then run the server
pyproject.toml
src/wiki_server/
server.py # FastMCP app: tools + /health
paths.py # path validation under WIKI_ROOT, refuses private/
seed/ # initial wiki content, copied into the volume onceRoadmap (next)
Built so far: OAuth, remember() + the lean read/search tools, the web console,
the staged dream (dry-run, execute, editable prompts, per-stage model + cost),
temporal items, the people/places/organizations taxonomy, and the automatic
nightly schedule. The codebase is split into focused modules with a pytest suite
run in CI.
Still open from the original vision: the weekly digest (a periodic summary of what changed and what is coming up). Optional later: notifications, and a "reorg" dream to fold residual duplicate pages.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
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/FloLey/memory-wiki'
If you have feedback or need assistance with the MCP directory API, please join our Discord server