Memoflare is an MCP server that gives AI agents durable, path-addressed memory — a filesystem-shaped store agents can read, write, search, and manage. It is built for agent-first workflows and can run locally, in Docker, or on Cloudflare Workers.
- Five MCP tools:
remember,read,update,forget,search(hybrid full-text + vector search) - MCP resources:
core://,tree://,memo://{path}for passive discovery - Bootstrap flow: agents are instructed to read
core://first to load skills and core memos - Two runtimes: Node.js (local) and Cloudflare Worker (edge) sharing the same service layer
- Node.js ≥ 20.12
- pnpm (recommended)
pnpm install
cp .env.example .env # optional; defaults work for loopback dev
pnpm run local- HTTP MCP:
http://localhost:3001/mcp - Health check:
http://localhost:3001/
pnpm run local -- --stdiopnpm run local -- --root ./dataDefault root without overrides: ~/memoflare (memo files plus .memoflare/memory.db).
Memoflare can run entirely on your own hardware without Cloudflare. You get local SQLite + filesystem storage, sqlite-vec for vectors, and FastEmbed for embeddings (model pre-downloaded in the Docker image).
1. Configure environment
cp .env.example .envSet MEMORY_ROOT=./data (or an absolute path) so memo files and the DB persist on the host. Compose bind-mounts that path to /app/memoflare inside the container.
2. Start the stack
pnpm run docker:upBy default the service listens on 127.0.0.1:3001 only. MCP endpoint: http://127.0.0.1:3001/mcp.
3. Expose beyond localhost (optional)
If you put Memoflare behind a reverse proxy or need LAN access:
- Set a strong
MEMORY_BEARERin.env - Change the Compose port mapping to bind the host interface you intend (or keep loopback and terminate TLS at the proxy)
- Point clients at
http(s)://<your-host>/mcpwithAuthorization: Bearer <token>
Do not publish port 3001 to the public internet without MEMORY_BEARER (or MEMORY_ALLOW_INSECURE=1, which is only appropriate for trusted local setups).
4. Operations
pnpm run docker:logs # follow logs
pnpm run docker:restart
pnpm run docker:downHost layout after use:
{MEMORY_ROOT}/
<your-top-level>/... # memo markdown/json files
.memoflare/memory.db # SQLite index + vectors
.trash/... # soft-deleted memos
pnpm install
pnpm run local:build
node dist/local.js --host 0.0.0.0 --port 3001 --root /var/lib/memoflare --bearer "$MEMORY_BEARER"Binding to non-loopback addresses requires --bearer (or --allow-insecure for controlled environments). Use a process manager (systemd, pm2) and a reverse proxy with TLS in production.
For MCP clients that spawn the server as a subprocess:
pnpm run local -- --stdio --root ~/memoflareNo HTTP port; auth is handled by OS process isolation.
Example for Cursor / Claude Desktop (HTTP transport):
{
"mcpServers": {
"memoflare": {
"url": "http://127.0.0.1:3001/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}Omit headers when using loopback without a bearer token.
Production edge deployment uses a Cloudflare Worker with D1 (metadata + FTS), R2 (memo bytes), Vectorize (semantic search), and Workers AI (embeddings). OAuth via KV is optional.
- Cloudflare account with Workers paid features as needed (D1, R2, Vectorize, Workers AI)
- Wrangler CLI logged in:
pnpm exec wrangler login
From the repo root:
# D1 database
pnpm exec wrangler d1 create memoflare-db
# Copy the database_id from the output into wrangler.jsonc under d1_databases[0]
# R2 bucket (dashboard or CLI)
pnpm exec wrangler r2 bucket create memoflare-files
# Vectorize index (768-dim cosine — matches BGE base EN v1.5)
pnpm exec wrangler vectorize create memoflare-vectors --dimensions=768 --metric=cosineEdit wrangler.jsonc and add the database_id returned by d1 create. Bucket and index names must match the file (memoflare-files, memoflare-vectors).
With OAuth disabled (default MEMOFLARE_OAUTH_ENABLED: "0"), the worker expects a static API bearer for /mcp and /sync:
pnpm exec wrangler secret put MEMORY_BEARER
# Enter a long random token; clients send Authorization: Bearer <token>Optional CORS origin for browser clients:
pnpm exec wrangler secret put ALLOWED_ORIGINwrangler deploy does not apply D1 migrations. After schema changes (or on first deploy):
pnpm exec wrangler d1 migrations apply memoflare-db --remotepnpm install
pnpm run typecheck
pnpm test
pnpm run deployNote the Worker URL from the output (e.g. https://memoflare.<subdomain>.workers.dev).
curl -s "https://memoflare.<subdomain>.workers.dev/"Expected:
{ "name": "Memoflare", "status": "ok", "mode": "cloud" }MCP (with bearer token):
curl -s -H "Authorization: Bearer YOUR_TOKEN" \
"https://memoflare.<subdomain>.workers.dev/mcp"-
Create KV:
pnpm exec wrangler kv namespace create OAUTH_KV -
Add to
wrangler.jsonc: -
Set consent password:
pnpm exec wrangler secret put MEMOFLARE_OAUTH_PASSWORD -
Redeploy. Unauthenticated MCP returns
401until a user completes/authorize.
Scopes: memos:read, memos:write, config:write, admin. The static MEMORY_BEARER still resolves as admin via resolveExternalToken.
| Binding | Resource |
|---|---|
MEMOFLARE_DB |
D1 memoflare-db |
MEMOFLARE_FILES |
R2 memoflare-files |
MEMOFLARE_VECTORS |
Vectorize memoflare-vectors |
AI |
Workers AI (embeddings) |
OAUTH_KV |
KV (OAuth only) |
Create .env.cloud (not committed):
MEMORY_CLOUD_URL=https://memoflare.<subdomain>.workers.dev
MEMORY_BEARER=your-cloud-bearer-tokenpnpm run sync:push # local → cloud
pnpm run sync:pull # cloud → localUse the same MEMORY_BEARER you configured as a Wrangler secret.
After wrangler.jsonc is filled in:
pnpm run devpnpm run typecheck
pnpm testOn first install, if native modules fail to build:
pnpm approve-builds
pnpm install| Tool | Purpose |
|---|---|
remember |
Create or replace a memo at a path |
read |
Read memos, directory trees, or workspace bootstrap (core://) |
update |
Append, patch, rename, or edit metadata |
forget |
Trash, restore, or purge memos |
search |
Keyword search or vector similarity |
| Mode | Behavior |
|---|---|
| Local loopback HTTP | No token by default |
| Local public bind | Requires MEMORY_BEARER or --allow-insecure |
| Cloud (OAuth off) | Requires MEMORY_BEARER on /mcp and /sync |
| Cloud (OAuth on) | OAuth tokens with scopes; static bearer still works as admin |
| Stdio | No token (process isolation) |
src/
local.ts # Node.js entry (HTTP + stdio)
worker.ts # Cloudflare Worker entry
mcp/ # MCP tools and resources
services/ # Memo pipeline, search, config, directory
providers/ # Local vs cloud storage/embeddings/vectors
migrations/ # D1 / SQLite schema
tests/ # Vitest suite
config/ # Drizzle config
wrangler.jsonc # Cloudflare Worker config
docker-compose.yml # Self-hosted Docker
MIT — see LICENSE.