my-memory
Integrates with Forgejo as remote Git hosting, providing OAuth 2.1 authentication for public clients, webhook handling for pushes, and support for pushes from Forgejo's web editor via rebase.
Uses Git as the source of truth for notes, committing every write with client attribution and trailers, maintaining history, and handling concurrent writes via optimistic concurrency and rebase.
Stores binary attachments in Git LFS, with companion notes containing extracted text (e.g., PDFs via pdftotext) so they remain searchable.
Click on "Deploy 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., "@my-memorywho works at Acme according to my notes?"
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.
my-memory
A self-hosted memory for AI agents. Your notes are a folder of Markdown files in git; my-memory serves them over MCP so any agent (Claude Code, Codex, claude.ai, your own bots) can search, read and write them. Every write is a git commit attributed to the client that made it.
Git is the source of truth. Search runs on a SQLite index (catalog, FTS5 full text by section, wikilinks) that can be rebuilt from git at any time.
One commit per write, authored by the client:
Claude Code (laptop),Alex (Claude)…. The commit message is the reason the agent gave, plusClient:/Tool:/Session:trailers.Safe for several agents at once. One writer queue, optimistic concurrency (
hashfromread), and pushes from elsewhere (your PC, Forgejo's web editor) integrated by rebase.Your conventions, not ours. The notes repo declares its folders, required frontmatter and filename rules in
memory.toml; itsAGENTS.mdis sent to every client as MCP instructions, with a short index.Two front doors. A private listener for static per-client tokens, file uploads and the git webhook. A public listener that only accepts OAuth 2.1 tokens (dynamic client registration and PKCE, sign-in delegated to Forgejo) for remote clients like claude.ai.
Attachments. Binaries go to git LFS with a companion note holding their text (PDFs via
pdftotext), so they are searchable too.Typed links.
works_at:: [[acme]]says what a link means, andlinkscan filter by it.
How it works inside (index, write flow, concurrency, auth): docs/design.md.
Tools
Tool | What it does |
| Short index, or every note in a folder with description, aliases and last change |
| Full-text search by section (accents ignored, prefixes match) with snippets |
| A note or one section, with its |
| Outgoing |
| Commits that touched a note: who, when, why |
| New note; unique names across folders; refuses look-alike duplicates unless |
| Exact text replacements, all or nothing |
| Rewrite a whole note; needs the |
| Rename or move; rewrites every |
| Remove a note (it stays in history); refused while other notes link to it |
| Store a file in LFS with a searchable companion note |
Clients with a read-only token only see the first five.
Related MCP server: Cortex
Notes format
---
name: Universidad
description: Carrera, asignaturas de este curso y cómo las lleva
aliases: [uni, carrera]
---
# Universidad
Text, with links like [[otra-nota]], [[otra-nota#Sección|texto]] or ![[documento.pdf]].File names (without .md) must be unique across the repo, so [[name]] always resolves; this is what Obsidian does with "shortest path" links.
A link can also say what it means, with Dataview-style inline fields: works_at:: [[acme]] on its own line, [lives_with:: [[sam]]] inside a sentence, or works_at: "[[acme]]" in the frontmatter. links returns the relation and can filter by it, so "who works at Acme" is one call.
memory.toml at the root of the notes repo (every key is optional):
[folders]
allowed = ["me", "people", "topics", "projects", "archive"]
archive = "archive" # excluded from list/search unless asked
index_full = ["me"] # listed note by note in the short index
root_files = ["AGENTS.md", "README.md"]
[notes]
required_fields = ["name", "description"]
filename_pattern = "^[a-z0-9]+(-[a-z0-9]+)*\\.md$"
superseded_field = "superseded_by"
max_description = 200
[instructions]
file = "AGENTS.md"
[attachments]
page_heading = "Page {n}"
[relations]
allowed = ["works_at", "lives_with"] # warn on other keys; without it, keys in use are suggestedRunning it
Requirements: Node.js 24, git, git-lfs, and poppler's pdftotext (optional).
npm ci && npm run build
my-memory token add laptop --name "Claude Code (laptop)" --scope write --file tokens.toml
my-memory serve --config config.tomlconfig.toml:
data_dir = "/var/lib/my-memory"
public_url = "https://memory.example.com" # only with the public listener
tokens_file = "tokens.toml"
webhook_secret_file = "webhook-secret" # paths, or credential:NAME for systemd credentials
[remote] # omit to keep the notes repo local
url = "http://127.0.0.1:3000/me/notes.git"
username = "my-memory"
token_file = "forgejo-token"
[listen.private]
address = "127.0.0.1"
port = 8782
[listen.public] # behind your TLS reverse proxy
address = "127.0.0.1"
port = 8781
[oauth] # required by the public listener
forgejo_url = "https://git.example.com" # as your browser reaches it
forgejo_internal_url = "http://127.0.0.1:3000" # as the server reaches it
client_id_file = "oauth-client-id" # an OAuth2 app registered in Forgejo,
client_secret_file = "oauth-client-secret" # redirect URI <public_url>/oauth/callback
allowed_users = ["me"]Uploads for attach: curl -T file.pdf -H "Authorization: Bearer $TOKEN" http://host:8782/uploads/file.pdf returns an upload_id. There is no size limit.
NixOS
{
inputs.my-memory.url = "github:<owner>/my-memory";
# in your configuration:
imports = [ inputs.my-memory.nixosModules.default ];
services.my-memory = {
enable = true;
remote = { url = "http://127.0.0.1:3000/me/notes.git"; tokenFile = "/run/secrets/forgejo-token"; };
listen.private = { address = "127.0.0.1"; port = 8782; };
tokensFile = "/var/lib/secrets/my-memory/tokens.toml"; # root:my-memory 0640
};
}After my-memory token add … --file <tokensFile>, run systemctl reload my-memory.
Connecting clients
# Claude Code
claude mcp add --transport http memory http://host:8782/mcp --header "Authorization: Bearer $MY_MEMORY_TOKEN"# Codex (~/.codex/config.toml)
[mcp_servers.memory]
url = "http://host:8782/mcp"
bearer_token_env_var = "MY_MEMORY_TOKEN"claude.ai: Settings → Connectors → Add custom connector → https://memory.example.com/mcp.
Moving an existing repo to wikilinks
my-memory migrate <clone> shows what would change: relative Markdown links become [[wikilinks]], name collisions are renamed, and frontmatter that is not valid YAML gets quoted. Add --apply to commit it. Only those spans change.
Development
npm ci
npm test # vitest: unit, integration (real git repos) and HTTP/OAuth end to end
npm run typecheck
nix flake check # builds the package and runs the NixOS VM testLicense
Apache-2.0.
This server cannot be deployed
Maintenance
Related MCP Connectors
Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.
Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.
Google Keep-style notes app with an MCP server for AI agents to read/write notes.
OAuth-protected, read-only-by-default MCP server for provenance-labeled QuillCaddie project memory.
Related MCP Servers
- FlicenseCqualityDmaintenanceGit-backed MCP server for creating and maintaining an Obsidian-style markdown knowledge base with full CRUD, search, and git sync.7-
- AlicenseNot gradedqualityBmaintenanceA dynamic, governed memory layer for Markdown notes that serves knowledge to AI clients and humans through a secure MCP server, with scoped access, git-audited changes, and optional LLM-powered semantic search.Apache 2.0
- AlicenseAqualityAmaintenanceMCP server for managing a local, domain-agnostic knowledge base using Markdown notes with frontmatter. Enables AI agents to capture, read, search, link, and maintain notes with atomic writes and privacy controls.13MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server that gives AI agents read and write access to a folder of Markdown notes, supporting full-text search, reading, listing, and writing notes. It is deliberately small, with no dependencies beyond the MCP SDK, and includes proper path traversal protection.MIT