{"id":47702204,"url":"https://github.com/jmeyer1980/neurodivergent-memory","last_synced_at":"2026-04-26T15:01:07.693Z","repository":{"id":347449312,"uuid":"1194068145","full_name":"jmeyer1980/neurodivergent-memory","owner":"jmeyer1980","description":"A TypeScript-based MCP server implementing a memory system inspired by neurodivergent cognitive styles. It organizes thoughts into five districts (knowledge domains), ranks search results using BM25 semantic ranking, and stores memories as a persistent knowledge graph with bidirectional connections.","archived":false,"fork":false,"pushed_at":"2026-04-16T02:19:23.000Z","size":17720,"stargazers_count":6,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-16T03:25:38.820Z","etag":null,"topics":["adhd-tools","agent-memory","associative-memory","bm25","cognitive-architecture","contextual-ai","docker","executive-dysfunction","fractal-semantics","graph-traversal","knowledge-graph","knowledge-management","mcp-server","memory-graph","model-context-protocol","neuro-symbolic","neurodivergent","nodejs","semantic-search","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jmeyer1980.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":"Roadmap_0_1_8_push_to_1_0_0.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"jmeyer1980","patreon":null,"open_collective":null,"ko_fi":"bellok","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":"gh/jmeyer1980","custom":"paypal.me/TinyWalnutGames"}},"created_at":"2026-03-27T22:11:40.000Z","updated_at":"2026-04-15T12:42:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jmeyer1980/neurodivergent-memory","commit_stats":null,"previous_names":["jmeyer1980/neurodivergent-memory"],"tags_count":83,"template":false,"template_full_name":null,"purl":"pkg:github/jmeyer1980/neurodivergent-memory","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmeyer1980%2Fneurodivergent-memory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmeyer1980%2Fneurodivergent-memory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmeyer1980%2Fneurodivergent-memory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmeyer1980%2Fneurodivergent-memory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jmeyer1980","download_url":"https://codeload.github.com/jmeyer1980/neurodivergent-memory/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmeyer1980%2Fneurodivergent-memory/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32301330,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adhd-tools","agent-memory","associative-memory","bm25","cognitive-architecture","contextual-ai","docker","executive-dysfunction","fractal-semantics","graph-traversal","knowledge-graph","knowledge-management","mcp-server","memory-graph","model-context-protocol","neuro-symbolic","neurodivergent","nodejs","semantic-search","typescript"],"created_at":"2026-04-02T17:30:36.652Z","updated_at":"2026-04-26T15:01:07.673Z","avatar_url":"https://github.com/jmeyer1980.png","language":"JavaScript","funding_links":["https://github.com/sponsors/jmeyer1980","https://ko-fi.com/bellok","https://thanks.dev/gh/jmeyer1980","paypal.me/TinyWalnutGames"],"categories":[],"sub_categories":[],"readme":"# neurodivergent-memory MCP Server\n\n[![npm version](https://img.shields.io/npm/v/neurodivergent-memory?logo=npm)](https://www.npmjs.com/package/neurodivergent-memory)\n[![Docker Image Version](https://img.shields.io/docker/v/twgbellok/neurodivergent-memory?logo=docker\u0026label=docker)](https://hub.docker.com/r/twgbellok/neurodivergent-memory)\n[![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Node 24 LTS](https://img.shields.io/badge/node-24_LTS-5FA04E?logo=node.js\u0026logoColor=white)](https://nodejs.org/en/about/previous-releases)\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd width=\"360\" valign=\"top\"\u003e\n      \u003cdetails\u003e\n        \u003csummary\u003e📽️ Click to preview\u003c/summary\u003e\n        \u003cbr /\u003e\n        \u003ca href=\"https://raw.githubusercontent.com/jmeyer1980/neurodivergent-memory/main/neurodivergent-memory.gif\"\u003e\n          \u003cimg src=\"https://raw.githubusercontent.com/jmeyer1980/neurodivergent-memory/main/neurodivergent-memory.gif\" alt=\"neurodivergent-memory preview\" width=\"320\" /\u003e\n        \u003c/a\u003e\n      \u003c/details\u003e\n    \u003c/td\u003e\n    \u003ctd valign=\"top\"\u003e\n      \u003cp\u003e\u003cstrong\u003eProject Preview\u003c/strong\u003e\u003c/p\u003e\n      \u003cp\u003e\n        This is a Model Context Protocol server for knowledge graphs designed around neurodivergent thinking patterns.\n      \u003c/p\u003e\n      \u003cp\u003e\n        This TypeScript-based MCP server implements a memory system inspired by neurodivergent cognitive styles. It organizes thoughts into five \u003cstrong\u003edistricts\u003c/strong\u003e (knowledge domains), ranks search results using \u003cstrong\u003eBM25 semantic ranking\u003c/strong\u003e, and stores memories as a persistent knowledge graph with bidirectional connections.\n      \u003c/p\u003e\n      \u003cblockquote\u003e\n        \u003cp\u003e\n          \u003cstrong\u003eDesign note:\u003c/strong\u003e The district model is rooted in \u003ca href=\"https://gitlab.com/tiny-walnut-games/fractalstat\"\u003eFractalSemantics (FractalStat)\u003c/a\u003e addressing, where every entity inherits ancestry from a single anchor point called \u003cstrong\u003eLUCA\u003c/strong\u003e (Last Universal Common Ancestor). These concepts are also used in \u003ca href=\"https://gitlab.com/tiny-walnut-games/the-seed/-/tree/4884b3a22da8a487e7c7931cb7426e20def0d7ba/warbler-cda-package\"\u003eWarbler-CDA\u003c/a\u003e and \u003ca href=\"https://gitlab.com/tiny-walnut-games/the-seed\"\u003ethe seed\u003c/a\u003e. The five canonical districts are the five direct children of LUCA in the default schema. Custom districts in later milestones must declare a valid LUCA-derived address, making ancestry explicit and traceable rather than assumed.\n        \u003c/p\u003e\n      \u003c/blockquote\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Quick-start\n\n### Windows\n\n```powershell\n# Download and install Chocolatey:\npowershell -c \"irm https://community.chocolatey.org/install.ps1|iex\"\n\n# Download and install Node.js:\nchoco install nodejs --version=\"24.14.1\"\n\n# Verify the Node.js version:\nnode -v # Should print a Node.js 24.x version.\n\n# Verify npm version:\nnpm -v # Should print an npm 11.x version.\n\n# Run the packaged neurodivergent-memory CLI without a global install\nnpx neurodivergent-memory@latest init-agent-kit\n```\n\n### Linux/macOS\n\n```bash\n# Download and install nvm:\ncurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash\n\n# in lieu of restarting the shell\n. \"$HOME/.nvm/nvm.sh\"\n\n# Download and install Node.js:\nnvm install 24\n\n# Verify the Node.js version:\nnode -v # Should print a Node.js 24.x version.\n\n# Verify npm version:\nnpm -v # Should print an npm 11.x version.\n\n# Run the packaged neurodivergent-memory CLI without a global install\nnpx neurodivergent-memory@latest init-agent-kit\n```\n\n## Model Flow\n\n```mermaid\nflowchart LR\n  A[Client MCP Request] --\u003e B[MCP Server Stdio Transport]\n  B --\u003e C{Request Type}\n  C --\u003e|Tools| D[Tool Handler]\n  C --\u003e|Resources| E[Resource Handler]\n  C --\u003e|Prompts| F[Prompt Handler]\n\n  D --\u003e G[NeurodivergentMemory Core]\n  E --\u003e G\n  F --\u003e G\n\n  G --\u003e H[Memory Graph Store]\n  G --\u003e I[BM25 Index]\n  H --\u003e J[Persisted JSON Snapshot]\n\n  D --\u003e K[MCP JSON Response]\n  E --\u003e K\n  F --\u003e K\n  K --\u003e A\n```\n\nFlow notes:\n\n- Memory operations update both graph state and BM25 index.\n- Persistence writes to the local snapshot file for restart continuity.\n- All MCP responses return through stdio transport.\n\n## Features\n\n### Five Memory Districts\n\nMemories are organized by cognitive domain:\n\n- **logical_analysis** — Structured thinking, problem solving, and analytical processes\n- **emotional_processing** — Feelings, emotional responses, and affective states\n- **practical_execution** — Action-oriented thoughts, tasks, and implementation\n- **vigilant_monitoring** — Awareness, safety concerns, and protective thinking\n- **creative_synthesis** — Novel connections, creative insights, and innovative thinking\n\n### Resources\n\n- Explore memory districts and individual memories via `memory://` URIs\n- Each memory includes content, tags, emotional metadata, and connection information\n- Access memories as JSON resources with full metadata\n\n### Tools\n\n- **`store_memory`** — Create new memory nodes with optional emotional valence and intensity\n- **`retrieve_memory`** — Fetch a specific memory by ID\n- **`update_memory`** — Modify content, tags, district, emotional_valence, intensity, or project attribution\n- **`delete_memory`** — Remove a memory and all its connections\n- **`connect_memories`** — Create bidirectional edges between memory nodes\n- **`search_memories`** — BM25-ranked semantic search with optional goal context, recency bias, and filters (district, project_id, tags, epistemic status, emotional valence, intensity, min_score)\n- **`traverse_from`** — Graph traversal up to N hops from a starting memory\n- **`related_to`** — Find memories by graph proximity + BM25 semantic blend, with optional goal context and epistemic-status filters\n- **`list_memories`** — Paginated listing with optional district/archetype/project_id/epistemic-status filters\n- **`memory_stats`** — Aggregate statistics (totals, per-district/per-project counts, most-accessed, orphans) with optional project scope\n- **`server_handshake`** — Return runtime server identity/version details for explicit client-side version confirmation\n- **`storage_diagnostics`** — Show the resolved snapshot path, WAL path, and effective persistence source in one response\n- **`import_memories`** — Bulk-import from inline JSON entries or a snapshot `file_path`, with `dry_run`, dedupe policies, and explicit snapshot migration flags\n- **`prepare_memory_city_context`** — Tool mirror of `explore_memory_city` for clients that support tools but do not invoke MCP prompts\n- **`prepare_synthesis_context`** — Tool mirror of `synthesize_memories` for prompt-limited clients\n- **`prepare_packetized_synthesis_context`** — Tool mirror of `synthesize_memory_packets` for prompt-limited or attachment-constrained clients\n\n### Prompts\n\n- **`explore_memory_city`** — Guided exploration of districts and memory organization\n- **`synthesize_memories`** — Create new insights by connecting existing memories\n- **`synthesize_memory_packets`** — Packetized synthesis prompt for attachment-constrained clients; emits one coverage manifest plus bounded memory slices that summarize the broader graph\n\nUse `synthesize_memories` when the MCP client can comfortably consume many raw memory resources. Use `synthesize_memory_packets` when the caller path is attachment-constrained or when you need broader graph coverage in a small number of structured resources.\n\nFor maximum interoperability across MCP clients, the server exposes the same synthesis/exploration context in two forms:\n\n- **Prompts** via `prompts/list` + `prompts/get` for clients that implement MCP prompt invocation.\n- **Tools** via the `prepare_*_context` tools for clients that support MCP tools but ignore or under-support prompts.\n\nSome clients, such as Cline, expose MCP prompts as namespaced slash commands in the form `/mcp:\u003cserver-name\u003e:\u003cprompt-name\u003e` rather than `/\u003cprompt-name\u003e`.\n\n## Core Concepts\n\n### Memory Archetypes\n\nEach memory is assigned an archetype tied to its district:\n\n- **scholar** — logical_analysis\n- **merchant** — practical_execution\n- **mystic** — emotional_processing and creative_synthesis\n- **guard** — vigilant_monitoring\n\n### Semantic Ranking\n\nSearch uses **Okapi BM25** ranking (k1=1.5, b=0.75) without requiring embeddings or cloud calls. Results are normalized to 0–1 score range.\n\n### Emotional Metadata\n\nEach memory can optionally carry:\n\n- **emotional_valence** (-1 to 1) — Emotional charge or affective tone\n- **intensity** (0–1) — Mental energy or importance weight\n\n### Epistemic Status\n\nMemories can optionally carry `epistemic_status` to distinguish tentative planning from validated knowledge.\n\n- `draft` — provisional or planning-oriented\n- `validated` — confirmed and safe to treat as established\n- `outdated` — superseded but retained for history\n\nWhen `store_memory` or `import_memories` creates a new `practical_execution` memory without an explicit `epistemic_status`, the server defaults it to `draft` if the memory has a task tag. The canonical task tag is `kind:task`, and the server also accepts the compatibility synonyms `type:task` and bare `task`. This keeps planning notes from silently presenting as settled fact.\n\n### Project Attribution and Scoped Retrieval\n\nMemories can optionally include a first-class `project_id` for attribution and scoped retrieval across multi-project graphs.\n\n- `project_id` is optional on writes (`store_memory`, `update_memory`, `import_memories`).\n- `update_memory` accepts `project_id: null` to clear existing project attribution.\n- `search_memories`, `list_memories`, and `memory_stats` accept an optional `project_id` filter.\n- `search_memories`, `list_memories`, and `related_to` accept optional `epistemic_statuses` filters so callers can avoid stale planning memories when appropriate.\n- `search_memories` accepts optional `context` and `recency_weight` parameters. Context is blended into ranking as a lightweight BM25 boost; `recency_weight` must be between `0` and `1` and adds a recency boost without replacing semantic relevance.\n- `search_memories` accepts `min_intensity` / `max_intensity` as the preferred intensity filter names. The legacy `intensity_min` / `intensity_max` aliases remain supported for compatibility.\n- `related_to` accepts an optional `context` parameter to bias related-memory ranking toward the caller's current goal.\n- Stats now include a `perProject` breakdown.\n- Scoped `memory_stats` reports `totalConnections` only for edges where both endpoints are in scope.\n- `list_memories` includes a `project: ...` segment in each line (`unset` when no project attribution exists).\n- Validation contract: `project_id` must match `^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$` (max length 64).\n- Invalid values return stable error code `NM_E020` with recovery guidance.\n\n### Import Diagnostics and Migration Semantics\n\n`storage_diagnostics` reports the resolved snapshot path, the WAL path, and which configuration source won the persistence-path precedence check.\n\n`import_memories` supports two source modes:\n\n- Inline `entries` for ordinary bulk seeding.\n- `file_path` for server snapshot imports, avoiding large MCP payloads.\n\nImport validation flags:\n\n- `dry_run: true` validates the request without writing data and returns deterministic `would_import`, `would_skip`, and `would_fail` counts.\n- `dedupe` accepts `none`, `content_hash`, or `content_plus_tags`.\n- Deduplicated rows are reported with stable reason codes: `DEDUPE_CONTENT_HASH` or `DEDUPE_CONTENT_PLUS_TAGS`.\n- Snapshot `file_path` imports accept `.json` files under the resolved persistence directory by default. Set `NEURODIVERGENT_MEMORY_IMPORT_ALLOW_EXTERNAL_FILE=true` only when importing external snapshot files intentionally.\n\nSnapshot migration flags:\n\n- `preserve_ids` is only valid with `file_path`; any ID collision with the live store is rejected deterministically.\n- `merge_connections` is only valid with `file_path`; every referenced connection target must exist either in the imported snapshot or the live store, or the row fails validation with `INVALID_CONNECTION_TARGET`.\n- If validation failures are present, the non-dry-run import is rejected as a whole. Run `dry_run: true` first to inspect the failure list before retrying.\n\n### Knowledge Graph Persistence\n\nMemories are persisted with a write-ahead journal (WAL) plus snapshot model:\n\n- Every mutating operation appends to `memories.json.wal.jsonl` first.\n- The in-memory graph is then updated and periodically snapshotted to `memories.json`.\n- On startup, the server loads `memories.json`, replays WAL entries, compacts to a fresh snapshot, then truncates the WAL.\n\nThis improves crash recovery behavior compared to snapshot-only persistence.\n\nFor explicit control, set one of these environment variables:\n\n- `NEURODIVERGENT_MEMORY_DIR` to choose the directory that contains `memories.json`\n- `NEURODIVERGENT_MEMORY_FILE` to point at a specific snapshot file\n- `NEURODIVERGENT_MEMORY_MAX` to cap total memories (integer; default unlimited)\n- `NEURODIVERGENT_MEMORY_EVICTION` to choose eviction policy when max is reached:\n  - `lru` (default)\n  - `access_frequency`\n  - `district_priority`\n\nMounts at `/home/node/.neurodivergent-memory` continue to work without any env override — that is the container's `node` user home and is checked automatically.\n\n\u003e **⚠️ Breaking change (v0.2.0):** The image runs as the `node` user and **cannot read `/root`**, so previous mounts at `/root/.neurodivergent-memory` are silently skipped. Agents may appear to have lost all memories. See [Recovering memories after upgrade](#recovering-memories-after-upgrade) below.\n\n#### Recovering memories after upgrade\n\nIf you previously mounted data at `/root/.neurodivergent-memory`, your snapshot is still intact on the host volume. Re-mount it using one of these options:\n\n**Option A — explicit `/data` mount (recommended):**\n\n```json\n\"-e\", \"NEURODIVERGENT_MEMORY_DIR=/data\",\n\"-v\", \"mydata:/data\"\n```\n\n**Option B — mount at the path the `node` user already owns:**\n\n```json\n\"-v\", \"mydata:/home/node/.neurodivergent-memory\"\n```\n\nNo `NEURODIVERGENT_MEMORY_DIR` override is needed for option B — the server finds the existing snapshot automatically.\n\nFor agents: if memories appear missing after upgrading the container, use `import_memories` to reload from a backup export, or ask your AI assistant to re-run `memory_stats` after the volume is remounted correctly to confirm restoration.\n\n### Multi-Tier Memory Persistence\n\nThe server supports a three-tier memory architecture for agents that work across multiple projects. Each tier\nlives in its own directory and can be synced independently.\n\n| Tier | Purpose | Typical path | Env var |\n|---|---|---|---|\n| **project** | Repo-scoped memories — ephemeral, CI-friendly | `.github/agent-kit/memories` | `NEURODIVERGENT_MEMORY_PROJECT_DIR` |\n| **user** | Cross-project personal knowledge — durable, per-developer | `~/.neurodivergent-memory` | `NEURODIVERGENT_MEMORY_USER_DIR` |\n| **org** | Shared organisational knowledge — optional, team-wide | any shared mount | `NEURODIVERGENT_MEMORY_ORG_DIR` |\n\nThe primary server still reads its active snapshot from `NEURODIVERGENT_MEMORY_DIR` (or the auto-discovered\ndefault). Tier variables are used exclusively by the `sync-memories` helper.\n\n#### Tagging memories for sync\n\nAdd a `persistence:durable` tag to any memory that should be promoted to the user or org tier. Memories\nwithout this tag are treated as ephemeral and stay in the project tier.\n\n```json\n[\"topic:typescript\", \"scope:global\", \"kind:pattern\", \"layer:architecture\", \"persistence:durable\"]\n```\n\nUse `persistence:ephemeral` as an explicit opt-out for memories you never want promoted.\n\n#### Syncing memories between tiers\n\nAfter a build, milestone, or session — promote durable memories from the project tier to the user tier:\n\n```bash\nNEURODIVERGENT_MEMORY_PROJECT_DIR=.github/agent-kit/memories \\\nNEURODIVERGENT_MEMORY_USER_DIR=~/.neurodivergent-memory \\\n  npm run sync-memories -- --from project --to user\n```\n\nOr use explicit paths:\n\n```bash\nnode build/scripts/sync-memories.js \\\n  --from .github/agent-kit/memories \\\n  --to ~/.neurodivergent-memory\n```\n\nFull option reference:\n\n```text\n--from \u003cpath|tier\u003e      Source snapshot directory, or tier name: project | user | org\n--to   \u003cpath|tier\u003e      Target snapshot directory, or tier name: project | user | org\n--tags \u003ctag1,tag2,...\u003e  Promote only memories matching ALL listed tags (default: persistence:durable)\n--any-tag               Match memories that have ANY of the listed tags (OR logic)\n--dry-run               Report counts without writing any data\n```\n\n**Safety note:** stop the MCP server for the target tier before running sync — the script writes directly to\nthe snapshot file and will warn if it detects an open WAL for the target directory.\n\n## Release Security\n\n- GitHub Actions runs on **Node.js 24 LTS** for CI and release automation\n- npm publishes use **OIDC provenance** with `npm publish --provenance --access public`\n- Docker images are built with **Buildx**, published to Docker Hub, and emitted with **SBOM** and **provenance** metadata\n- GitHub Actions generates **artifact attestations** for the npm tarball and the pushed container image digest\n- Tagged releases upload the npm tarball, checksums, and attestation bundles as release assets\n\n## Development RC Channel\n\nPushes to the `development` branch publish **release candidates** using the same npm package name (`neurodivergent-memory`) and container repositories.\n\n- npm prereleases are published as `0.x.x-rc.N` with npm dist-tag `rc`.\n- npm prerelease suffix `N` uses `run_number.run_attempt` to avoid collisions on workflow re-runs.\n- Docker images are published with immutable `rc-0.x.x-rc.N` tags only, where `N` is derived from `run_number.run_attempt`.\n- GitHub releases for RC builds are marked as **pre-release**.\n\nThese builds are intentionally less stable than the research preview line and should be used only for validation and early integration testing.\n\n### Live Readiness Smoke (project_id)\n\nUse the deterministic live smoke harness to validate `project_id` attribution/scoped retrieval end-to-end:\n\n- Local build target:\n\n```bash\nnpm run smoke:project-id\n```\n\n- Latest Docker RC target (PowerShell):\n\n```powershell\n$rc = (Invoke-RestMethod -Uri \"https://hub.docker.com/v2/repositories/twgbellok/neurodivergent-memory/tags?page_size=25\").results |\n  Where-Object { $_.name -match '^rc-' } |\n  Sort-Object { $_.last_updated } -Descending |\n  Select-Object -First 1 -ExpandProperty name\nnode test/live-project-id-smoke.mjs \"docker run --rm -i twgbellok/neurodivergent-memory:$rc\"\n```\n\nThe smoke harness exits non-zero on failed assertions and is suitable as a release-readiness gate.\n\n## Error Contract\n\nMutating and lookup tool failures are returned with a stable operator-facing shape embedded in the text response:\n\n```text\n❌ \u003csummary\u003e\nCode: NM_EXXX\nMessage: Human-readable failure summary\nRecovery: Suggested next action\n```\n\nThe leading summary line is contextual, while the `Code`/`Message`/`Recovery` block remains stable for operators to parse and search. This keeps MCP responses readable in chat clients while giving operators a stable code they can search in logs and release notes. Structured logs are written with Pino to stderr and include the same `code` field on known failure paths.\n\n## Concurrency Safety\n\nMutating tools are serialized through an async mutex to prevent concurrent write races when multiple agents call the server at the same time.\n\nWrite queue behavior:\n\n- Pending write operations are bounded by `NEURODIVERGENT_MEMORY_QUEUE_DEPTH` (default: `50`).\n- When the queue is full, mutating tools return `NM_E010` with a retry-oriented recovery message.\n- Queue high-water/clear transitions are logged with structured Pino warnings.\n\nWIP guardrail behavior:\n\n- `store_memory` checks practical in-progress task saturation per `agent_id` when task tags include in-progress markers.\n- The cap is controlled by `NEURODIVERGENT_MEMORY_WIP_LIMIT` (default: `1`; set `0` to disable).\n- Exceeding the cap emits a warning line in the tool response and logs `NM_E011` for operator visibility.\n\n## Loop Telemetry And Guardrails\n\nThe server tracks loop signals and can surface targeted guardrail responses:\n\n- Repetition detection on `store_memory` compares incoming content against the 10 most recent memories (same `agent_id` when provided) using tokenizer-consistent token-overlap scoring with an exact-match fast path.\n- Stores that meet the repeat threshold set `repeat_detected: true`, increment `repeat_write_count` on the matched memory, and add a `No net-new info` warning to the tool response.\n- Repeated `logical_analysis` reads of `emotional_processing` memories add a `distill_memory` suggestion once the configured threshold is crossed.\n- Read/write ping-pong transitions are tracked in a rolling operation window, increment `ping_pong_counter` when threshold conditions are met, and can optionally start a temporary cross-district write cooldown.\n- `memory_stats` now includes a `loop_telemetry` block with:\n  - `repeat_write_candidates` (top 5)\n  - `ping_pong_candidates` (top 5)\n  - `recent_high_similarity_writes` (last 5)\n\nConfiguration:\n\n- `NEURODIVERGENT_MEMORY_REPEAT_THRESHOLD` (default: `0.85`)\n- `NEURODIVERGENT_MEMORY_LOOP_WINDOW` (default: `20`)\n- `NEURODIVERGENT_MEMORY_PING_PONG_THRESHOLD` (default: `3`)\n- `NEURODIVERGENT_MEMORY_DISTILL_SUGGEST_THRESHOLD` (default: `3`)\n- `NEURODIVERGENT_MEMORY_CROSS_DISTRICT_COOLDOWN_MS` (default: `0`, disabled)\n\n## Performance Benchmark Baseline\n\nIssue #19 adds a deterministic benchmark harness for end-to-end MCP stdio measurements against the built server.\n\nRun it with:\n\n```bash\nnpm run benchmark\n```\n\nThe benchmark:\n\n- Uses an isolated temp persistence directory so it does not mutate your local memory graph.\n- Seeds each dataset tier, then measures `store_memory` throughput across 100 writes at the target tier.\n- Measures `search_memories` and `list_memories` latency over 100 iterations at 1k, 5k, and 10k memories.\n- Measures `traverse_from` latency at depths 2, 3, and 5 on a connected graph of 500 memories.\n- Prints the structured JSON report to stdout for automation-friendly capture.\n- Writes run-specific outputs to timestamped files under `benchmark-results/`.\n- Also writes rolling latest aliases:\n  - `benchmark-results/memory-benchmark-latest.json`\n  - `benchmark-results/memory-benchmark-latest.md`\n\nThere is also a convenience alias:\n\n```bash\nnpm run bench\n```\n\nThe committed baseline is intended as a relative regression reference for RC vs stable comparisons, not as a universal absolute performance guarantee across machines.\n\nTo intentionally refresh the committed baseline files in place:\n\n```bash\nnpm run benchmark -- --update-baseline\n```\n\n## Development\n\nInstall dependencies:\n\n```bash\nnpm install\n```\n\nBuild the server:\n\n```bash\nnpm run build\n```\n\nFor development with auto-rebuild:\n\n```bash\nnpm run watch\n```\n\n## Installation\n\nTo use with Claude Desktop, add the server config:\n\nOn macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`\nOn Windows: `%APPDATA%/Claude/claude_desktop_config.json`\n\nFor npm:\n\n```json\n{\n  \"mcpServers\": {\n    \"neurodivergent-memory\": {\n      \"command\": \"npx\",\n      \"args\": [\"neurodivergent-memory\"]\n    }\n  }\n}\n```\n\nFor Docker:\n\n```json\n{\n  \"mcpServers\": {\n    \"neurodivergent-memory\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\",\n        \"-i\",\n        \"--rm\",\n        \"-e\",\n        \"NEURODIVERGENT_MEMORY_DIR=/data\",\n        \"-v\",\n        \"neurodivergent-memory-data:/data\",\n        \"docker.io/twgbellok/neurodivergent-memory:0.3.0\"\n      ]\n    }\n  }\n}\n```\n\nFully auto-approved tools:\n\n```json\n{\n  \"mcpServers\": {\n    \"neurodivergent-memory\": {\n      \"autoApprove\": [\n        \"store_memory\",\n        \"retrieve_memory\",\n        \"connect_memories\",\n        \"search_memories\",\n        \"update_memory\",\n        \"delete_memory\",\n        \"traverse_from\",\n        \"related_to\",\n        \"list_memories\",\n        \"memory_stats\",\n        \"storage_diagnostics\",\n        \"import_memories\",\n        \"distill_memory\",\n        \"prepare_memory_city_context\",\n        \"prepare_synthesis_context\",\n        \"prepare_packetized_synthesis_context\",\n        \"register_district\"\n      ],\n      \"disabled\": false,\n      \"timeout\": 120,\n      \"type\": \"stdio\",\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\",\n        \"-i\",\n        \"--rm\",\n        \"-e\",\n        \"NEURODIVERGENT_MEMORY_DIR=/data\",\n        \"-v\",\n        \"neurodivergent-memory-data:/data\",\n        \"docker.io/twgbellok/neurodivergent-memory:0.3.0\"\n      ],\n      \"env\": {}\n    }\n  }\n}\n```\n\nIf you want to use the mcp server in Github Copilot Agent Workflows (github spins up a new VM every time, so cross-workflow memory is non-existent. Session memory is working, but is wiped upon job completion.):\n\n```json\n{\n  \"mcpServers\": {\n    \"neurodivergent-memory\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"neurodivergent-memory@0.3.0\"\n      ],\n      \"env\": {\n        \"NEURODIVERGENT_MEMORY_DIR\": \".neurodivergent-memory\"\n      },\n      \"tools\": [\n        \"retrieve_memory\",\n        \"connect_memories\",\n        \"update_memory\",\n        \"delete_memory\",\n        \"traverse_from\",\n        \"related_to\",\n        \"import_memories\",\n        \"storage_diagnostics\",\n        \"distill_memory\",\n        \"prepare_memory_city_context\",\n        \"prepare_synthesis_context\",\n        \"prepare_packetized_synthesis_context\",\n        \"register_district\",\n        \"list_memories\",\n        \"store_memory\",\n        \"search_memories\",\n        \"memory_stats\"\n      ]\n    }\n  }\n}\n```\n\nIf you want per-project isolation instead of a shared global memory file, mount a project-specific host directory and keep the same container-side target. Use the path separator for your OS:\n\n- **Windows**: `${workspaceFolder}\\.neurodivergent-memory:/data`\n- **macOS / Linux**: `${workspaceFolder}/.neurodivergent-memory:/data`\n\n```json\n{\n  \"mcpServers\": {\n    \"neurodivergent-memory\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\",\n        \"-i\",\n        \"--rm\",\n        \"-e\",\n        \"NEURODIVERGENT_MEMORY_DIR=/data\",\n        \"-v\",\n        \"${workspaceFolder}/.neurodivergent-memory:/data\",\n        \"docker.io/twgbellok/neurodivergent-memory:0.3.0\"\n      ]\n    }\n  }\n}\n```\n\n\u003e **Note:** Replace `/` with `\\` on Windows: `${workspaceFolder}\\.neurodivergent-memory:/data`\n\n### Docker Runtime\n\nUse an explicit version tag. The published Docker images intentionally do not maintain a floating `latest` tag.\n\nYou can also run the packaged server image directly:\n\n```bash\ndocker run --rm -i twgbellok/neurodivergent-memory:0.3.0\n```\n\n### Debugging\n\nSince MCP servers communicate over stdio, debugging can be challenging. We recommend using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector), which is available as a package script:\n\n```bash\nnpm run inspector\n```\n\nThe Inspector will provide a URL to access debugging tools in your browser.\n\n## Agent Workflow Setup\n\nThis repository ships a reusable **agent customization kit** whose authoring source lives at [`.github/agent-kit/`](.github/agent-kit/).\nUse the packaged installer to materialize those templates into a consumer repository's `.github/...` folders instead of tracking a live generated agent file in this repo.\n\n### Contents\n\n| File | Purpose |\n|---|---|\n| `templates/neurodivergent-agent.agent.md` | Full-featured Memory-Driven Development Coordinator agent. Five-phase workflow: pull context → research → improve memories → plan → act \u0026 hand off. |\n| `templates/memory-driven-template.agent.md` | Minimal generic agent template — a lighter starting point if you want to build your own workflow on top. |\n| `templates/nd-memory-workflow.instructions.md` | Shared instruction file that reinforces memory-driven habits in day-to-day coding sessions without requiring explicit agent invocation. |\n| `templates/setup-nd-memory.prompt.md` | Guided setup prompt that asks the user to choose an install policy before anything is installed. |\n| `templates/copilot-instructions.md` | Bootstrap reference for GitHub Copilot sessions — tag schema, district table, tool quick-reference, and session checklist in one file. |\n| `templates/explore_memory_city.prompt.md` | Prompt for guided exploration of memory districts and graph structure. |\n| `templates/memory-driven-issue-execution.prompt.md` | Prompt for executing a tracked issue with full memory-driven context (pull → plan → act → update). |\n\n### Install the kit into a project\n\nInstall the current packaged kit into the repo you are standing in:\n\n```bash\nnpx neurodivergent-memory@latest init-agent-kit\n```\n\nUseful options:\n\n- `--target \u003cpath\u003e` installs into a different repository root.\n- `--dry-run` shows what would be copied without writing files.\n- `--force` overwrites existing destination files.\n- `--mode prompt-first|auto-setup` records the intended install policy in command output while leaving template wording unchanged.\n\nThe installer copies templates into standard customization locations such as `.github/agents/`, `.github/instructions/`, `.github/prompts/`, and `.github/copilot-instructions.md`.\n\n### Authoring source and generated files\n\nThe source of truth remains under [`.github/agent-kit/templates/`](.github/agent-kit/templates/). The installed live agent file `.github/agents/neurodivergent-agent.agent.md` is intentionally treated as generated consumer state rather than a tracked repo artifact, so remote Copilot updates cannot keep wiping it out in this repository.\n\n### Manual copy fallback\n\n**Copy** the files you need into your project's standard customization locations — do not move them, so the originals remain available as a reference for future agents or contributors.\n\nThe right target directories vary by agent platform. Use whatever location your agent natively reads from. Common examples:\n\n- `.github/agents/` for agent definitions\n- `.github/instructions/` for shared instructions\n- `.github/prompts/` for prompts\n- `.github/` root for `copilot-instructions.md`\n\n### Install policy handshake\n\nBefore installing neurodivergent-memory MCP in any project, ask the user which policy to apply:\n\n- **`prompt-first`** *(default)* — Ask for explicit approval before installing.\n- **`auto-setup`** — Install automatically without prompting.\n\nUpdate the imported agent file's installation section to reflect the chosen policy. If no preference is stated, default to `prompt-first`.\n\n## Appendix\n\nHere is an example copilot-instructions.md\n\n```copilot-instructions.md\n# neurodivergent-memory — Agent Bootstrap Instructions\n\nThis file is automatically read by GitHub Copilot and compatible agents at the start of every session.\nIt replaces the need to fetch the governance memory (`memory_11`) before working with this MCP server.\n\n---\n\n## What this server is\n\n`neurodivergent-memory` is a **Model Context Protocol (MCP) server** that stores and retrieves memories as a\nknowledge graph. It is designed for neurodivergent thinking patterns: non-linear, associative, tag-rich.\n\nMemories are organised into five **districts** (knowledge domains) and connected via bidirectional edges.\nSearch uses **BM25 semantic ranking** — no embedding model or cloud LLM required.\n\n---\n\n## Canonical Tag Schema\n\nAlways apply tags from the five namespaces below when calling `store_memory`.\nMultiple tags from different namespaces are expected on every memory.\nWhen storing execution-heavy memories, include the reasoning behind the action and, when possible, connect the entry to a durable principle in `logical_analysis` or `creative_synthesis` so retrieval preserves understanding and not just activity.\n\n| Namespace | Purpose | Examples |\n|---|---|---|\n| `topic:X` | Subject matter / domain | `topic:unity-ecs`, `topic:adhd-strategies`, `topic:rust-async` |\n| `scope:X` | Breadth of the memory | `scope:concept`, `scope:project`, `scope:session`, `scope:global` |\n| `kind:X` | Type of knowledge | `kind:insight`, `kind:decision`, `kind:pattern`, `kind:reference`, `kind:task` |\n| `layer:X` | Abstraction level | `layer:architecture`, `layer:implementation`, `layer:debugging`, `layer:research` |\n| `persistence:X` | Sync-tier eligibility | `persistence:durable`, `persistence:ephemeral` |\n\n**Example tag set for a Unity ECS memory:**\n\n```json\n[\"topic:unity-ecs\", \"topic:dots\", \"scope:project\", \"kind:pattern\", \"layer:architecture\"]\n```\n\n**Example tag set for a durable cross-project memory:**\n\n```json\n[\"topic:typescript\", \"scope:global\", \"kind:pattern\", \"layer:architecture\", \"persistence:durable\"]\n```\n\n---\n\n## Districts\n\n| Key | Purpose |\n| --- | --- |\n| `logical_analysis` | Structured thinking, analysis, research findings |\n| `emotional_processing` | Feelings, emotional states, affective responses |\n| `practical_execution` | Tasks, plans, implementations, action items |\n| `vigilant_monitoring` | Risks, warnings, constraints, safety concerns |\n| `creative_synthesis` | Novel connections, creative ideas, cross-domain insights |\n\n---\n\n## Available MCP Tools (quick reference)\n\n| Tool | Purpose |\n| --- | --- |\n| `store_memory` | Create a new memory node |\n| `retrieve_memory` | Fetch one memory by ID |\n| `update_memory` | Modify content, tags, district, valence, or intensity |\n| `delete_memory` | Remove a memory and all its connections |\n| `connect_memories` | Add an edge between two memory nodes |\n| `search_memories` | BM25-ranked search with optional `context`, `recency_weight`, `min_score`, district, tag, valence, and intensity filters |\n| `traverse_from` | BFS graph walk from a node up to N hops |\n| `related_to` | Hop-proximity + BM25 blend for a given memory ID, with optional goal-context boost |\n| `list_memories` | Paginated enumeration of all stored memories |\n| `memory_stats` | Totals, per-district/per-project counts, most-accessed, and orphans |\n| `storage_diagnostics` | Resolved snapshot path, WAL path, and effective persistence source |\n| `import_memories` | Bulk import from inline entries or a snapshot file with dry-run and migration controls |\n| `distill_memory` | Translate an `emotional_processing` memory into a structured logical artifact |\n| `prepare_memory_city_context` | Tool mirror of `explore_memory_city` for prompt-limited clients |\n| `prepare_synthesis_context` | Tool mirror of `synthesize_memories` for prompt-limited clients |\n| `prepare_packetized_synthesis_context` | Tool mirror of `synthesize_memory_packets` for attachment-constrained clients |\n| `register_district` | Register a custom district with LUCA ancestry validation |\n\n---\n\n## Persistence\n\nMemories are automatically saved to `~/.neurodivergent-memory/memories.json` on every write.\nThe graph is restored on server startup — no data is lost between restarts.\n\n---\n\n## Memory Quality Guardrails\n\n- Do not stop at \"what happened\". Important memories should capture why the action was taken, what tradeoff or principle drove it, and whether the insight is reusable.\n- Treat `practical_execution` as the action log, then pair it with `logical_analysis` or `creative_synthesis` when the deeper rationale should survive longer than the implementation details.\n- When a debug trail, handoff, or emotional/raw memory is noisy, use `distill_memory` or an explicit follow-up memory to preserve the signal while stripping incidental detail.\n- Prefer connective synthesis over isolated task logs: link implementation memories back to durable principles such as explicit state over implicit state, bounded growth, or environment-aware validation.\n\n---\n\n## Bootstrap checklist for new agent sessions\n\n1. Call `memory_stats` to see how many memories exist.\n2. Use `search_memories` with a broad query to locate relevant prior context.\n3. Check whether recent memories already explain the rationale or durable principle behind the task, not just the last execution step.\n4. Apply the canonical tag schema when calling `store_memory`.\n5. Connect new memories to related existing ones with `connect_memories`.\n6. Use `traverse_from` or `related_to` for associative retrieval rather than repeated searches.\n7. **No Quick Task exemption**: any file edit, decision, or finding in this repo is memory-worthy — write the memory before moving on. If you catch yourself thinking \"this is too small\" — that is the trigger, not a bypass.\n8. **No execution-only memory exemption**: if a memory says what changed, it should also say why it changed or link to a memory that does.\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmeyer1980%2Fneurodivergent-memory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjmeyer1980%2Fneurodivergent-memory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmeyer1980%2Fneurodivergent-memory/lists"}