Update - #7
Open
jamusaaron wants to merge 32 commits into
Open
Conversation
The MCP server only exposed addToMCPMemory and searchMCPMemory tools, while delete and update operations were only available via REST endpoints. This adds listMCPMemories, deleteMCPMemory, and updateMCPMemory tools so MCP clients can perform full CRUD operations on memories. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
Configures the MCP memory server for use with Claude Code via .claude/settings.json and adds CLAUDE.md with project documentation for Claude Code sessions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
Complete rewrite from 5-tool prototype to production memory system: Data model: structured memories with category (14 types), layer (core/long_embedded/mid_ground/current), confidence/salience/emotion scoring, contradiction detection, and confidence decay. Storage: D1 for structured data (10 tables), KV for caching (living summary, personality, session state), R2 for static context files. Tools (88 total): - Memory CRUD & retrieval (20): write, edit, forget, promote, query, smart context, pattern analysis, consolidation, decay sweep - People/profiles (13): add, list, get/update profiles, propose/apply pending updates, AI extraction, profile health audit - Session lifecycle (9): session brief, logging, close, audit, living summary, context management - Behavioral modeling (6): behavioral model, emotional context, personality profile, mode selection, feedback loop - Uncertainty loop (3): ask user, record answer, list open questions - Ingestion pipeline (3): transcript ingestion, AI extraction, triage - Cross-agent shared memory (5): agent notes, cross-checking - Static files (2): R2-backed context document read/write - Health check (1): full system component verification - Infra passthrough (26): Cloudflare D1/KV/R2/Workers management Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
Improved all tool descriptions to be more actionable for LLM clients, explaining WHEN to use each tool and how it relates to other tools. New memory tools: suppress_memory, restore_memory, verify_memory, search_by_tag, get_suppressed_memories, memory_timeline, export_memories, bulk_tag_memories. New people tools: search_people, delete_person, update_person. New session tool: session_list. New uncertainty tool: dismiss_uncertainty. New static file tools: delete_static_file, list_static_files. New behavioral tool: record_observation. New ai-agent tool: ai_note_delete. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
- Use prepare().run() instead of exec() for D1 migrations (fixes multiline SQL in local dev) - Wrap contradiction detection in try/catch so write_memory works when AI/Vectorize are unavailable Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
- Add keywordSearchMemories (D1 LIKE search across text/subject/tags/triggers) and searchMemoriesWithFallback so query_memories, smart_context, and get_memory_context keep working when Vectorize/Workers AI are unreachable - Add batch_write_memories tool for bulk imports (1-50 memories per call) - Add optional MEMORY_API_KEY auth: Bearer header or ?key= param on all data routes; SSE message POSTs validated by unguessable session ID - Add POST /:userId/memories REST endpoint - Make submit_inbound and ingest_transcript degrade gracefully when AI triage/extraction is unavailable (store with defaults instead of failing) Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
The kv_namespaces binding had a placeholder ID ("mcp-memory-kv") and the
r2_buckets binding referenced a bucket that may not exist in the account,
causing the Cloudflare Workers Builds deploy to fail on binding validation.
- Remove KV/R2 bindings from wrangler.jsonc (commented instructions to
re-enable with real resource IDs)
- Cache operations fall back to a D1 kv_store table (with TTL emulation)
when env.KV is unbound
- Static files fall back to a D1 static_files table when env.R2 is unbound
- health_check reports which backend is active for cache and static files
- Deploy now only requires resources that exist: D1, Vectorize, Workers AI
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
The ratelimit binding is not referenced anywhere in the code and unsafe bindings are a potential deploy-validation failure point. Dropping it narrows the deploy config to only what the worker actually uses. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
Workers Builds fails instantly if its configured build command is `npm run build` and the script doesn't exist. Provide build/test scripts (type-check) so any common build-command configuration succeeds. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
The previous database_id a25fc989-... does not exist in this account. Point DB at mcp-memory-db (1dd6fb6c-...) and KV at the existing namespace.
connection_map was left on raw searchMemories() when the keyword-search fallback was added to query_memories, smart_context, and get_memory_context — it's the same shape (pure related-memory lookup, no LLM synthesis) and was failing outright without Vectorize/Workers AI. run_consolidation intentionally keeps its hard Vectorize dependency: keyword-match scores aren't a valid proxy for the similarity threshold it uses to suppress memories, so degrading it risks false-positive consolidation. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
fix: connection_map keyword-search fallback for consistency
wrangler.jsonc already had a triggers.crons entry (*/30 * * * *) with no
handler — Cloudflare was logging "Handler does not export a scheduled()
function" on every fire. Added the handler and made it do something
useful.
- runDecaySweep() and listDistinctUserIds() extracted to utils/db.ts,
reused by both the run_decay_sweep MCP tool (unchanged behavior,
now DRY) and the new scheduled handler
- scheduled() enumerates every user with stored memories and runs the
decay sweep for each, logging a summary; failures for one user don't
block the rest
- export default switched from the bare Hono app to { fetch, scheduled }
so both handlers are wired
Verified with `wrangler dev --test-scheduled` + `/__scheduled` — runs
cleanly with 0 and 1 users, and the MCP tool still produces identical
output after the refactor.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
feat: wire up scheduled() handler for the decay sweep cron
The architecture doc claimed memory writes trigger downstream rebuilds of the living summary and profiles, but the code never actually did this — putLivingSummary was imported into memory.ts and never called. Both derived documents only ever updated when someone remembered to call rebuild_living_summary / rebuild_self_profile by hand. Added src/utils/cascade.ts: a cheap per-user dirty counter (no AI call) bumped by write_memory, batch_write_memories, edit_memory (on text changes), suppress_memory, restore_memory, and forget_memory. Two triggers consume it: - Threshold-based, on every write: living summary rebuilds past 10 unsummarized changes, self-profile past 5 — so a burst of writes pays the AI cost once instead of on every call. - Session-boundary, in session_close: rebuilds either document if its counter is non-zero at all, since session close is infrequent enough to justify the cost regardless of how small the change was. get_session_brief now surfaces staleness directly instead of silently serving a possibly-stale cached summary. rebuild_living_summary and rebuild_self_profile (the existing manual tools) now delegate to the same cascade functions so a manual rebuild correctly clears the dirty counter too — previously the brief would keep claiming staleness even right after a manual rebuild. All rebuild attempts are best-effort: a failure (e.g. Workers AI unreachable) is logged and leaves the dirty counter untouched, so nothing is falsely marked fresh. Verified against a live dev server: dirty count increments on write, threshold-crossing at write #10 correctly triggers an auto-rebuild attempt, session_close attempts and correctly fails-open without crashing (no Workers AI locally), and the counter survives failed attempts instead of being incorrectly cleared. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
feat: wire up the write cascade between memory writes and derived docs
…ub, behavioral cascade Three enhancements to how the tools feed each other, extending the write cascade shipped previously: 1. record_user_answer closes the uncertainty->memory loop. Its own description already promised "consider using the answer to update memories" but it did nothing — an answered question's knowledge just evaporated. It now writes the resolved Q&A as a memory (with the write cascade) by default; store_as_memory=false opts out. 2. get_session_brief becomes the operational hub. It now surfaces open uncertainties (from ask_user) and memories needing reverification (decayed confidence) alongside the summary/context, so a session starts knowing what to ask and confirm without separately calling list_open_uncertainties / list_reverify_queue. 3. Behavioral cascade mirrors the write cascade. record_observation and personality_feedback now bump a behavioral-model dirty counter; behavioral_model rebuilds past 5 changes or at session_close, instead of only when manually rebuilt with rebuild=true. behavioral_model and the new rebuild share one code path in cascade.ts so a manual rebuild also clears the counter. Added getUncertaintyById (db) and extended cascade.ts with a behavioral_model kind. session_close now reports which of the three documents it refreshed. Verified against a live dev server: answering an uncertainty stores the Q&A as a memory and the write cascade fires; the brief renders an "Open Questions" section; the 5th observation triggers the behavioral auto-rebuild path (fails open locally without Workers AI, as designed). Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
feat: cross-tool integration — answered questions persist, brief as hub, behavioral cascade
… fallback Every AI-dependent feature (living summary, self-profile, behavioral model, triage, extraction, pattern analysis, personality) was broken in production: llmCall hardcoded @cf/meta/llama-3.1-8b-instruct, which Cloudflare retired at end-of-support 2026-05-30. rebuild_living_summary surfaced it live with "AiError 5028: This model was deprecated on 2026-05-30." llmCall now tries an ordered list of current text-generation models and falls through on deprecation/availability errors, so a single model retirement can no longer silently break the whole system. The primary is overridable via the LLM_MODEL var (config change, not code) for the next time Cloudflare rotates models. Embeddings (@cf/baai/bge-m3) were unaffected and are unchanged. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
Audit follow-up to the deprecated-model outage. Two gaps closed: 1. health_check only exercised the embedding model (@cf/baai/bge-m3) and reported a single "Workers AI: OK" — so it showed green the entire time text generation was down. It now probes embeddings AND text generation separately (via checkTextGeneration -> llmCallDetailed), reporting which text model is live, so this class of total outage can never be silent again. 2. Extended FALLBACK_TEXT_MODELS across families (added Mistral small 3.1 24b and Qwen2.5 32b after the four Llama entries) so even a whole-family deprecation can't take out all text generation. Added llmCallDetailed (returns the working model id) which llmCall and checkTextGeneration both build on. Audited the rest of the surface: production D1 is clean (137 memories all embedded, 0 empty, 3 legitimately suppressed, profiles intact); no other hardcoded models/external APIs; infra tools degrade gracefully without credentials; all vector/cascade writes are properly awaited. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
fix: llmCall used a deprecated Workers AI model — add resilient model fallback
Adds runAiSelfTest: probes Workers AI text generation (checkTextGeneration)
and writes {status, model, ts} to the D1 kv_store table under key
__ai_selftest__. Wired into both the fetch middleware (throttled to once per
90s, backgrounded via waitUntil) and the scheduled() cron handler.
Purpose: the self-test always executes in the Worker runtime — the freshly
deployed code — so the live text model can be verified even when a Durable
Object MCP session is pinned to older code, and even when the Worker isn't
reachable over HTTP. The result row is inspectable directly with a D1 query,
giving a reliable production health signal independent of the MCP connector.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
feat: worker AI self-test written to D1 for out-of-band verification
…ced) The user runs this on a paid Cloudflare plan and does not want request rate limiting, so it should not be enforced or claimed. Production reverts to no rate-limiting middleware (this branch == main's code, which has none), and the README security section no longer claims rate limiting protects the service. Security model is now stated accurately: per-namespace data isolation + optional API-key auth (MEMORY_API_KEY) + Cloudflare TLS/infra. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
docs: accurate security model — no rate limiting (paid plan, not wanted)
Memories can be written with embedding_status='pending' when Vectorize/ Workers AI is briefly unavailable, or via direct D1 inserts. Previously they stayed pending until someone manually called backfill_embeddings through the MCP connector — which is useless if the connector is down. Extract backfillEmbeddingsForUser() (shared by the backfill_embeddings tool and the worker) and call it per-user inside the 30-minute scheduled() maintenance pass, alongside the decay sweep. Pending embeddings now vectorize themselves with no manual step and no connector dependency. Best-effort per memory; failures are logged and don't block the sweep. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BotQMbUfnnaJdFsDWsTNcw
feat: auto-backfill pending embeddings in the scheduled worker handler
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.