{
  "markdown": "# Memory MCP\n\n<!-- markdownlint-disable MD033 -->\n\n[![npm version](https://img.shields.io/npm/v/@j0hanz/memory-mcp?style=flat-square&logo=npm&logoColor=white&color=CB3837)](https://www.npmjs.com/package/@j0hanz/memory-mcp) [![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](https://github.com/j0hanz/memory-mcp/blob/master/package.json) [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D24-339933?style=flat-square&logo=nodedotjs&logoColor=white)](https://github.com/j0hanz/memory-mcp/blob/master/package.json) [![TypeScript](https://img.shields.io/badge/TypeScript-5.9%2B-3178C6?style=flat-square&logo=typescript&logoColor=white)](https://github.com/j0hanz/memory-mcp/blob/master/package.json)\n\n[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=memory-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemory-mcp%40latest%22%5D%7D) [![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=memory-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemory-mcp%40latest%22%5D%7D&quality=insiders)\n\n[![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=memory-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovbWVtb3J5LW1jcEBsYXRlc3QiXX0=)\n\nA SQLite-backed MCP server for persistent memory storage, full-text retrieval, and relationship graph traversal.\n\n## Overview\n\nMemory MCP provides a local, persistent memory layer for MCP-enabled assistants. It stores SHA-256-addressed memory items in SQLite with FTS5-powered full-text search, a directed relationship graph, BFS recall traversal, and token-budget-aware context retrieval — all accessible over stdio transport with no external dependencies.\n\n## Key Features\n\n- **13 MCP tools** for CRUD, batch operations, FTS5 search, BFS graph recall, token-budget context retrieval, relationships, and stats.\n- **Full-text search** over content and tags via SQLite FTS5 with importance and type filters.\n- **Graph recall** with BFS traversal, bounded frontier, and MCP progress notifications per hop.\n- **Token-budget retrieval** (`retrieve_context`) selects memories that fit a caller-specified token budget — no manual pagination needed.\n- **Strict Zod input validation** with typed output envelopes and SHA-256 hash addressing.\n- **Resource support** with `internal://instructions` (Markdown guide) and `memory://memories/{hash}` URI template with hash auto-completion.\n- **stdio transport** with clean shutdown handling (`SIGINT`, `SIGTERM`) and no HTTP endpoints. |\n\n## Requirements\n\n- Node.js `>=24`.\n- SQLite with FTS5 support (verified at startup).\n- Any MCP client that supports stdio command servers.\n\n## Quick Start\n\nUse the npm package directly with `npx` — no installation required:\n\n```json\n{\n  \"mcpServers\": {\n    \"memory-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@j0hanz/memory-mcp@latest\"]\n    }\n  }\n}\n```\n\n> [!TIP]\n> The server uses stdio transport only; no HTTP endpoint is exposed. Stdout must not be polluted by custom logging.\n\nOr run with Docker:\n\n```bash\ndocker run --rm -i ghcr.io/j0hanz/memory-mcp:latest\n```\n\n## Client Configuration\n\n<details>\n<summary><b>Install in VS Code</b></summary>\n\n[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=memory-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemory-mcp%40latest%22%5D%7D)\n\nWorkspace file `.vscode/mcp.json`:\n\n```json\n{\n  \"servers\": {\n    \"memory-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@j0hanz/memory-mcp@latest\"]\n    }\n  }\n}\n```\n\nCLI:\n\n```bash\ncode --add-mcp '{\"name\":\"memory-mcp\",\"command\":\"npx\",\"args\":[\"-y\",\"@j0hanz/memory-mcp@latest\"]}'\n```\n\n</details>\n\n<details>\n<summary><b>Install in VS Code Insiders</b></summary>\n\n[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=memory-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemory-mcp%40latest%22%5D%7D&quality=insiders)\n\nCLI:\n\n```bash\ncode-insiders --add-mcp '{\"name\":\"memory-mcp\",\"command\":\"npx\",\"args\":[\"-y\",\"@j0hanz/memory-mcp@latest\"]}'\n```\n\n</details>\n\n<details>\n<summary><b>Install in Cursor</b></summary>\n\n[![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=memory-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovbWVtb3J5LW1jcEBsYXRlc3QiXX0=)\n\n`~/.cursor/mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"memory-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@j0hanz/memory-mcp@latest\"]\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><b>Install in Claude Desktop / Claude Code</b></summary>\n\n`claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"memory-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@j0hanz/memory-mcp@latest\"]\n    }\n  }\n}\n```\n\nCLI:\n\n```bash\nclaude mcp add memory-mcp -- npx -y @j0hanz/memory-mcp@latest\n```\n\n</details>\n\n<details>\n<summary><b>Install in Windsurf</b></summary>\n\nMCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"memory-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@j0hanz/memory-mcp@latest\"]\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><b>Run with Docker</b></summary>\n\n```bash\n# Pull and run (stdio mode)\ndocker run --rm -i \\\n  -e MEMORY_DB_PATH=/data/memory.db \\\n  -v memory-data:/data \\\n  ghcr.io/j0hanz/memory-mcp:latest\n```\n\nMCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"memory-mcp\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\",\n        \"--rm\",\n        \"-i\",\n        \"-e\",\n        \"MEMORY_DB_PATH=/data/memory.db\",\n        \"-v\",\n        \"memory-data:/data\",\n        \"ghcr.io/j0hanz/memory-mcp:latest\"\n      ]\n    }\n  }\n}\n```\n\n</details>\n\n## Documentation Maintenance\n\n- **Owner**: maintainers updating MCP behavior in `src/` must update `README.md` and affected `mcp/` mirror pages in the same PR.\n- **Link/version policy**: use pinned `https://modelcontextprotocol.io/specification/2025-11-25/...` links for protocol references; avoid `latest` and mixed legacy targets.\n- **Drift-check checklist**:\n  - Re-verify capability declarations in `src/server.ts`.\n  - Reconcile tool/resource/prompt docs with `src/tools/index.ts`, `src/resources/index.ts`, and `src/prompts/index.ts`.\n  - Confirm limitations/gotchas in `src/instructions.md` match runtime behavior.\n- **Validation commands**: `npm run type-check`, `npm run test:fast`, `npm run build`.\n\n## MCP Surface\n\n### Tools Summary\n\n| Tool                  | Category | Notes                                   |\n| --------------------- | -------- | --------------------------------------- |\n| `store_memory`        | Write    | Idempotent by content+sorted tags hash  |\n| `store_memories`      | Write    | Batch (1–50), transaction-wrapped       |\n| `get_memory`          | Read     | Hash lookup                             |\n| `update_memory`       | Write    | Returns `old_hash` + `new_hash`         |\n| `delete_memory`       | Write    | Cascades relationship deletion          |\n| `delete_memories`     | Write    | Batch (1–50), transaction-wrapped       |\n| `search_memories`     | Read     | FTS5 + importance/type filters + cursor |\n| `create_relationship` | Write    | Idempotent directed edge creation       |\n| `delete_relationship` | Write    | Deletes exact directed edge             |\n| `get_relationships`   | Read     | Direction filter + linked memory fields |\n| `recall`              | Read     | FTS5 seed + BFS traversal (depth 0–3)   |\n| `retrieve_context`    | Read     | Token-budget-aware context retrieval    |\n| `memory_stats`        | Read     | Store aggregates and type breakdown     |\n\n---\n\n### `store_memory`\n\nStore a new memory with content, tags, and optional type/importance. Idempotent — storing the same content+tags returns the existing hash with `created: false`.\n\n| Name          | Type       | Required | Default   | Description                                                                        |\n| ------------- | ---------- | -------- | --------- | ---------------------------------------------------------------------------------- |\n| `content`     | `string`   | Yes      | —         | Memory content (1–100000 chars)                                                    |\n| `tags`        | `string[]` | Yes      | —         | 1–100 tags, each max 50 chars, no whitespace                                       |\n| `memory_type` | enum       | No       | `general` | `general`, `fact`, `plan`, `decision`, `reflection`, `lesson`, `error`, `gradient` |\n| `importance`  | `integer`  | No       | `0`       | Priority 0–10                                                                      |\n\nReturns: `{ hash, created }`\n\n---\n\n### `store_memories`\n\nStore multiple memories in one transaction (max 50 items).\n\n| Name    | Type                     | Required | Description                                                                            |\n| ------- | ------------------------ | -------- | -------------------------------------------------------------------------------------- |\n| `items` | `Array<StoreMemoryItem>` | Yes      | 1–50 items, each with `content`, `tags`, optional `memory_type`, optional `importance` |\n\nReturns: `{ items, succeeded, failed }`\n\n---\n\n### `get_memory`\n\nRetrieve one memory by its SHA-256 hash.\n\n| Name   | Type     | Required | Description                   |\n| ------ | -------- | -------- | ----------------------------- |\n| `hash` | `string` | Yes      | 64-char lowercase SHA-256 hex |\n\nReturns: `Memory` or `{ ok: false, error }` on `E_NOT_FOUND`.\n\n---\n\n### `update_memory`\n\nUpdate content and optionally tags for an existing memory. Returns both hashes.\n\n| Name      | Type       | Required | Default       | Description          |\n| --------- | ---------- | -------- | ------------- | -------------------- |\n| `hash`    | `string`   | Yes      | —             | Existing memory hash |\n| `content` | `string`   | Yes      | —             | Replacement content  |\n| `tags`    | `string[]` | No       | Existing tags | Replacement tags     |\n\nReturns: `{ old_hash, new_hash }`\n\n---\n\n### `delete_memory`\n\nDelete one memory by hash. Cascades to related relationship rows.\n\n| Name   | Type     | Required | Description |\n| ------ | -------- | -------- | ----------- |\n| `hash` | `string` | Yes      | Memory hash |\n\nReturns: `{ hash, deleted }`\n\n---\n\n### `delete_memories`\n\nDelete multiple memories by hash in one transaction.\n\n| Name     | Type       | Required | Description        |\n| -------- | ---------- | -------- | ------------------ |\n| `hashes` | `string[]` | Yes      | 1–50 memory hashes |\n\nReturns: `{ items, succeeded, failed }`\n\n---\n\n### `search_memories`\n\nFull-text search over memory content and tags using FTS5. Supports importance and type filters with cursor pagination.\n\n| Name             | Type      | Required | Default | Description                                               |\n| ---------------- | --------- | -------- | ------- | --------------------------------------------------------- |\n| `query`          | `string`  | Yes      | —       | Search text (1–1000 chars)                                |\n| `limit`          | `integer` | No       | `20`    | Results per page (1–100)                                  |\n| `cursor`         | `string`  | No       | —       | Pagination cursor from previous response                  |\n| `min_importance` | `integer` | No       | —       | Only return memories with importance >= this value (0–10) |\n| `max_importance` | `integer` | No       | —       | Only return memories with importance <= this value (0–10) |\n| `memory_type`    | enum      | No       | —       | Filter by memory type                                     |\n\nReturns: `{ memories, total_returned, nextCursor? }`\n\n---\n\n### `create_relationship`\n\nCreate a directed relationship edge between two memories. Idempotent.\n\nSuggested `relation_type` values: `related_to`, `causes`, `depends_on`, `parent_of`, `child_of`, `supersedes`, `contradicts`, `supports`, `references`.\n\n| Name            | Type     | Required | Description                                       |\n| --------------- | -------- | -------- | ------------------------------------------------- |\n| `from_hash`     | `string` | Yes      | Source memory hash                                |\n| `to_hash`       | `string` | Yes      | Target memory hash                                |\n| `relation_type` | `string` | Yes      | Edge label (1–50 chars, no whitespace, free-form) |\n\nReturns: `{ created }`\n\n---\n\n### `delete_relationship`\n\nDelete one directed relationship edge.\n\n| Name            | Type     | Required | Description       |\n| --------------- | -------- | -------- | ----------------- |\n| `from_hash`     | `string` | Yes      | Source hash       |\n| `to_hash`       | `string` | Yes      | Target hash       |\n| `relation_type` | `string` | Yes      | Relationship type |\n\nReturns: `{ deleted }` or `{ ok: false, error }` on `E_NOT_FOUND`.\n\n---\n\n### `get_relationships`\n\nRetrieve relationships for a memory, with optional direction filter.\n\n| Name        | Type     | Required | Default | Description                       |\n| ----------- | -------- | -------- | ------- | --------------------------------- |\n| `hash`      | `string` | Yes      | —       | Memory hash                       |\n| `direction` | enum     | No       | `both`  | `outgoing`, `incoming`, or `both` |\n\nReturns: `{ relationships, count }`\n\nEach relationship includes `from_hash`, `to_hash`, `relation_type`, `created_at`, `linked_hash`, `linked_content`, and `linked_tags`.\n\n---\n\n### `recall`\n\nSearch memories by full-text query, then traverse the relationship graph up to `depth` hops via BFS. Emits MCP progress notifications per hop.\n\n| Name             | Type      | Required | Default | Description                                                |\n| ---------------- | --------- | -------- | ------- | ---------------------------------------------------------- |\n| `query`          | `string`  | Yes      | —       | Seed search query (1–1000 chars)                           |\n| `depth`          | `integer` | No       | `1`     | BFS hops (0–3)                                             |\n| `limit`          | `integer` | No       | `10`    | Seed memory count (1–50)                                   |\n| `cursor`         | `string`  | No       | —       | Pagination cursor from previous response                   |\n| `min_importance` | `integer` | No       | —       | Seed filter: only memories with importance >= value (0–10) |\n| `max_importance` | `integer` | No       | —       | Seed filter: only memories with importance <= value (0–10) |\n| `memory_type`    | enum      | No       | —       | Seed filter: only memories of this type                    |\n\nReturns: `{ memories, graph, depth_reached, aborted?, nextCursor? }`\n\nEach item in `graph` uses the shape:\n\n```json\n{ \"from_hash\": \"...\", \"to_hash\": \"...\", \"relation_type\": \"...\" }\n```\n\n> [!NOTE]\n> `aborted: true` indicates the traversal hit a safety limit (`RECALL_MAX_FRONTIER_SIZE`, `RECALL_MAX_EDGE_ROWS`, or `RECALL_MAX_VISITED_NODES`). Partial results are still returned.\n\n---\n\n### `retrieve_context`\n\nSearch memories and return relevance-ranked results that fit within a caller-specified token budget. Eliminates manual pagination and token counting for context window management.\n\n| Name           | Type      | Required | Default     | Description                                                                                |\n| -------------- | --------- | -------- | ----------- | ------------------------------------------------------------------------------------------ |\n| `query`        | `string`  | Yes      | —           | Search query (1–1000 chars)                                                                |\n| `token_budget` | `integer` | No       | `4000`      | Maximum estimated tokens to return (100–200000)                                            |\n| `strategy`     | enum      | No       | `relevance` | Sort order: `relevance` (FTS rank), `importance` (highest first), `recency` (newest first) |\n\nReturns: `{ memories, estimated_tokens, truncated }`\n\n> [!TIP]\n> Token estimation is approximate (content length ÷ 4). `truncated: true` means the budget was reached before all candidates were included.\n\n---\n\n### `memory_stats`\n\nReturn aggregate memory and relationship stats. Takes no input.\n\nReturns:\n\n```json\n{\n  \"memories\": {\n    \"total\": 0,\n    \"oldest\": null,\n    \"newest\": null,\n    \"avg_importance\": null\n  },\n  \"relationships\": { \"total\": 0 },\n  \"by_type\": {}\n}\n```\n\n---\n\n### Resources\n\n| URI                        | MIME               | Description                                           |\n| -------------------------- | ------------------ | ----------------------------------------------------- |\n| `internal://instructions`  | `text/markdown`    | Markdown usage guide for all tools and workflows      |\n| `memory://memories/{hash}` | `application/json` | Returns one memory as JSON; hash completion supported |\n\n### Prompts\n\n| Name       | Arguments | Purpose                                       |\n| ---------- | --------- | --------------------------------------------- |\n| `get-help` | none      | Returns full usage instructions for all tools |\n\n## Configuration\n\n### Environment Variables\n\n| Variable                   | Description                                             | Default               | Required |\n| -------------------------- | ------------------------------------------------------- | --------------------- | -------- |\n| `MEMORY_DB_PATH`           | SQLite database file path                               | `memory_db/memory.db` | No       |\n| `RECALL_MAX_FRONTIER_SIZE` | Max BFS frontier nodes per hop (100–50000)              | `1000`                | No       |\n| `RECALL_MAX_EDGE_ROWS`     | Max relationship rows fetched per traversal (100–50000) | `5000`                | No       |\n| `RECALL_MAX_VISITED_NODES` | Max visited nodes across entire traversal (100–50000)   | `5000`                | No       |\n\n> [!IMPORTANT]\n> If `MEMORY_DB_PATH` is relative (including the default `memory_db/memory.db`), it resolves from the process working directory.\n\n> [!TIP]\n> Add `memory_db/` to your `.gitignore` to keep the database out of version control — it contains local session data and should not be shared or committed.\n\n### Limits and Constraints\n\n| Item                            | Value                                             |\n| ------------------------------- | ------------------------------------------------- |\n| Content length                  | 1–100000 chars                                    |\n| Tag count                       | 1–100 per memory                                  |\n| Tag length                      | 1–50 chars, no whitespace                         |\n| Hash format                     | 64-char lowercase hex SHA-256                     |\n| Search query length             | 1–1000 chars                                      |\n| `search_memories.limit`         | 1–100 (default 20)                                |\n| `recall.depth`                  | 0–3 (default 1)                                   |\n| `recall.limit`                  | 1–50 (default 10)                                 |\n| `retrieve_context.token_budget` | 100–200000 (default 4000)                         |\n| Batch size                      | 1–50 items (`store_memories`, `delete_memories`)  |\n| Recall frontier guard           | `RECALL_MAX_FRONTIER_SIZE` (default 1000 per hop) |\n| SQLite busy timeout             | 5000 ms                                           |\n\n> [!NOTE]\n> Cursor values are opaque base64url-encoded tokens. Treat them as opaque and do not parse them.\n\n## Security\n\n- Transport is stdio-only (`StdioServerTransport`) — no HTTP endpoints.\n- Fatal process errors are written to `stderr`; stdout must remain clean for the MCP protocol.\n- All inputs are validated with strict Zod schemas and bounded field constraints before any database access.\n- Hashes are validated against a lowercase 64-char SHA-256 hex regex.\n- Search input is tokenized to alphanumeric terms before FTS `MATCH` execution (non-alphanumeric characters act as delimiters, preventing FTS injection).\n- SQLite foreign keys are enabled; relationship rows cascade-delete when a memory is removed.\n\n## Development\n\nInstall dependencies:\n\n```bash\nnpm install\n```\n\nCore scripts:\n\n| Script       | Command              | Purpose                                                              |\n| ------------ | -------------------- | -------------------------------------------------------------------- |\n| `build`      | `npm run build`      | Clean, compile, validate instructions, copy assets, chmod executable |\n| `dev`        | `npm run dev`        | TypeScript watch mode                                                |\n| `dev:run`    | `npm run dev:run`    | Run built server with `.env` and file watch                          |\n| `start`      | `npm run start`      | Start built server                                                   |\n| `test`       | `npm run test`       | Full build + tests via task runner                                   |\n| `test:fast`  | `npm run test:fast`  | Run TS tests directly with Node test runner                          |\n| `lint`       | `npm run lint`       | ESLint checks                                                        |\n| `lint:fix`   | `npm run lint:fix`   | ESLint auto-fix                                                      |\n| `type-check` | `npm run type-check` | Strict TypeScript checks                                             |\n| `format`     | `npm run format`     | Prettier format                                                      |\n| `inspector`  | `npm run inspector`  | Build and open MCP Inspector against stdio server                    |\n\nInspect with MCP Inspector:\n\n```bash\nnpx @modelcontextprotocol/inspector node dist/index.js\n```\n\n## Build & Release\n\nGitHub Actions release workflow (`.github/workflows/release.yml`) handles versioning, validation, and publishing via a single `workflow_dispatch` trigger:\n\n```\nworkflow_dispatch (patch / minor / major / custom)\n    │\n    ▼\n  release — bump package.json + server.json → lint → type-check → test → build → tag → GitHub Release\n    │\n    ├──► publish-npm ──► publish-mcp   (npm Trusted Publishing OIDC → MCP Registry)\n    │\n    └──► publish-docker                (GHCR, linux/amd64 + linux/arm64)\n```\n\nTrigger a release:\n\n```bash\ngh workflow run release.yml -f bump=patch\n```\n\nOr use the GitHub UI: **Actions → Release → Run workflow**.\n\n> [!NOTE]\n> npm publishing uses OIDC Trusted Publishing — no `NPM_TOKEN` secret required. MCP Registry uses GitHub OIDC. Docker uses the built-in `GITHUB_TOKEN`.\n\n## Troubleshooting\n\n| Symptom                       | Cause                        | Fix                                                      |\n| ----------------------------- | ---------------------------- | -------------------------------------------------------- |\n| Startup fails with FTS5 error | Node.js build without FTS5   | Use Node.js 24+ with SQLite FTS5 support                 |\n| `E_NOT_FOUND` on `get_memory` | Hash doesn't exist           | Verify via `search_memories` first                       |\n| `E_INVALID_CURSOR`            | Stale or malformed cursor    | Retry the request without the `cursor` parameter         |\n| MCP client can't connect      | Custom stdout logging added  | Ensure nothing writes to stdout in the server process    |\n| `aborted: true` in recall     | Traversal hit a safety limit | Reduce `depth`, or tune `RECALL_MAX_*` env vars          |\n| Database locked errors        | High concurrent write load   | SQLite busy timeout is 5000 ms; reduce concurrent writes |\n\n## License\n\nMIT\n\n<!-- markdownlint-enable MD033 -->\n",
  "bytes": 24417,
  "sha": "762209ea3b64a54ec4431a9113a26c7e4403f4fd1203d7d290b0398649c98173",
  "repo_slug": "j0hanz/memory-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_j0hanz_memory_mcp_487ec17a/readme"
}