Every time I start a new conversation with Claude, I re-explain my project context. What we decided, what the architecture looks like, what we tried and rejected. The AI has no memory.
I built edgenote-ai to fix this — a lightweight shared knowledge base on Cloudflare Workers that both humans and LLMs can read and write through MCP (Model Context Protocol).
The Problem
LLMs are stateless. They process your input, generate a response, and forget everything. Memory features like ChatGPT's are limited and proprietary — you can't control what gets remembered, search it, or share it across tools.
What I wanted:
- A place to store project notes, decisions, and context
- Accessible to any LLM via standard protocols (MCP)
- Searchable
- Also usable by humans through a web UI
- Self-hosted, open source, under my control
The Architecture
edgenote-ai provides three interfaces to the same data:
Human (browser) → Web UI →
Cloudflare Workers + D1
LLM (Claude) → MCP tools →
(+ Rust/WASM planned for search)
Scripts → REST API →
MCP Tools (9 total)
The MCP endpoint uses Streamable HTTP transport via the official @modelcontextprotocol/sdk. When connected to Claude Desktop (via mcp-remote), the LLM gets these tools:
| Tool | Description |
|---|---|
note_create |
Create a note |
note_read |
Read by ID or title |
note_update |
Update or append content |
note_search |
Search notes (currently D1 LIKE-based) |
note_list |
List all notes |
note_delete |
Delete a note |
note_export |
Bulk export for loading full context |
context_briefing |
Comprehensive overview of your knowledge base |
note_summarize |
Summarize one or more notes |
The context_briefing tool is what makes this useful in practice — at the start of a conversation, the LLM calls it and immediately understands what's in your knowledge base.
Dynamic Server Instructions
When a new MCP session starts, the server returns dynamic instructions in the initialize response:
"instructions": "This is edgenote-ai, a shared knowledge base with 9 notes.
Last updated: 2026-05-25. Recent notes: Architecture Overview, Sprint 3 Retro...
Use context_briefing for a full overview before starting work."
This tells the LLM what exists before it even calls a tool.
Zero-Friction Setup
- Sign in with Google at edgenote.0xkaz.com
- Copy the MCP config from your dashboard
- Add to Claude Desktop config (uses
mcp-remotefor the remote connection) - Done — Claude can read and write your notes
{
"mcpServers": {
"edgenote": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://edgenote.0xkaz.com/mcp",
"--header",
"Authorization: Bearer YOUR_API_KEY"
]
}
}
}
Technical Decisions
Why Cloudflare Workers?
A remote MCP server needs global accessibility with low latency. Workers gives:
- Edge deployment in 300+ locations
- D1 for SQL storage (SQLite-compatible)
- R2 for object storage
- $5/mo paid tier covers everything
Search: Honest About the Current State
Currently, search is D1 LIKE '%query%' — basic but functional. I have a Rust/WASM core built with pulldown-cmark (Markdown parsing) and an in-memory search index, but it's not yet integrated into the Workers runtime.
The plan is to add tantivy (a Rust full-text search library) compiled to WASM for ranked results, fuzzy matching, and CJK tokenization. This is on the roadmap, not shipped.
I'm being upfront about this because I've seen too many projects claim features they haven't built yet.
Auth Design
Dual auth from day one:
-
API key (
enai_*prefix) — for MCP clients and REST API -
Google OAuth — for the web UI, with CSRF
stateparameter
Both resolve to the same user ID. Sign up via Google → get an API key automatically → copy ready-made MCP config from dashboard.
Security
- Markdown rendering uses DOMPurify + script context XSS prevention (
<escaping) - OAuth includes
stateparameter for CSRF protection - R2 image serving has path traversal protection
- All note queries are scoped by
user_id
What I Learned
MCP is powerful but remote servers are rare
The protocol is well-designed. Claude Desktop connects via mcp-remote (an npm proxy that translates Streamable HTTP to stdio). Most MCP servers are local — remote ones are still uncommon.
LLMs are surprisingly good at using structured tools
When you give Claude note_search and context_briefing, it knows when to use them without explicit prompting. "Check my notes about the deployment plan" just works.
The "context briefing" pattern is essential
Individual note reads are useful, but the real value comes from the LLM understanding your entire knowledge base at a glance. The context_briefing tool gives a structured overview — note count, titles, summaries — so the LLM can make informed decisions about which notes to read.
Dynamic instructions make remote MCP servers feel intelligent
The MCP spec's instructions field in the initialize response is underutilized. Making it dynamic (querying D1 for the user's actual note state) makes the server feel like it knows you.
What's Next
- [ ] tantivy WASM search (replacing D1 LIKE queries)
- [ ] CRDT-based real-time sync (Automerge)
- [ ] Shared spaces for team collaboration
- [ ] Semantic search (Vectorize + Workers AI)
- [ ] MCP-native OAuth (eliminate copy-paste API keys)
Try It
This is an early-stage side project — feedback and contributions welcome.
- Demo: edgenote.0xkaz.com
- GitHub: github.com/0xkaz/edgenote-ai
- License: MIT
I'd love feedback on the MCP tool design. What tools would be most useful for your AI workflow? What would you want your AI assistant to remember?





















