Skip to main content
Glama

MemDrive

An MCP server that gives LLMs persistent memory on your own storage: a local folder (Google Drive / OneDrive / iCloud sync folder, or any plain directory) today. WebDAV (NAS, Nextcloud, Alist/Rclone) is interface-reserved behind the StorageBackend interface but not implemented; whether it is implemented later depends on user feedback, and it will only be considered if the user base is large with clear demand.

The model reads and writes Markdown + a sibling assets/ image folder through six small tools. No cloud service, no account, no server to run — the MCP server runs on your own machine and touches only the folder you point it at.

Status: MVP 0.6.0. Local filesystem backend only. WebDAV is interface-reserved behind the StorageBackend interface but not implemented. Whether it is implemented later depends on user feedback, and it will only be considered if the user base is large with clear demand. 0.1.1 added one total response budget to read_file (see Reading back and Limits) and put the clipboard rule first in the save_file tool description. 0.1.2 fixes the preview ladder so previews use the budget instead of stopping at the first coarse shrink step (see TEST-REPORT.md §7). 0.1.3 tries higher JPEG quality at full resolution before shrinking, states the three limit layers (host / server / model) in the read_file tool description, and adds CHANGELOG.md (see TEST-REPORT.md §8). 0.2.0 adds open_image (open an original image in the OS viewer, only when the user explicitly asks) and a setup wizard that finds a sync folder and writes the Claude Desktop config for you (see Setup and TEST-REPORT.md §9). 0.3.0 adds a Cursor adapter to the wizard: the wizard asks which host to configure first and writes Cursor's global config (~/.cursor/mcp.json) as well (see TEST-REPORT.md §12). 0.4.0 adds a VS Code adapter (Copilot Global config, ~/.copilot/mcp-config.json) and a per-host response budget written by the wizard into each host's config (see TEST-REPORT.md §13). 0.5.0 raises the Cursor budget to 10,000,000 on the 2026-10-30 verified read and adds open_containing_folder (open a note's folder in the OS file manager, only when the user explicitly asks, no highlight or selection — see TEST-REPORT.md §14). 0.6.0 adds a Claude Code adapter to the wizard (user scope, ~/.claude.json top-level mcpServers, budget 10,000,000) — UNVERIFIED on a real machine, budget estimated by the author's decision, not measured; see Claude Code config and TEST-REPORT.md §17.

Quick start

Requires Node.js 18+.

Easiest — setup wizard (recommended for first install). Download the release zip, extract it, and run the launcher for your system (it installs dependencies, builds, and starts the wizard, which asks which host to configure and which folder to use, and writes the Claude Desktop, Cursor, VS Code, or Claude Code config):

  • Windows: double-click setup.bat

  • macOS: double-click setup.command (or run ./setup.sh in a terminal)

  • Linux: run ./setup.sh in a terminal

The wizard needs Node.js 18+ already installed; if it is missing, the launcher says so and offers to open https://nodejs.org for you. It never installs anything silently and never changes a config file without backing it up first (see Setup).

# Run without installing (after this package is published to npm):
npx -y memdrive-mcp

# Or from a checkout:
npm install
npm run build
node dist/index.js

The library root defaults to ~/memdrive (created automatically). Override it with MEMDRIVE_ROOT:

MEMDRIVE_ROOT=~/Documents/memory npx -y memdrive-mcp

Related MCP server: mor

Claude Desktop config

The setup wizard (see Setup) writes this for you. Only edit it by hand if the wizard could not find your config file — it then prints a ready-to-paste snippet instead.

Add this to your Claude Desktop config file (claude_desktop_config.json):

{
  "mcpServers": {
    "memdrive": {
      "command": "npx",
      "args": ["-y", "memdrive-mcp"],
      "env": {
        "MEMDRIVE_ROOT": "/Users/you/Library/CloudStorage/GoogleDrive-you@example.com/My Drive/memory"
      }
    }
  }
}

Point MEMDRIVE_ROOT at a folder your sync client already manages and the official client syncs everything to the cloud in the background — MemDrive itself does zero network auth and zero uploads.

On Windows use a Windows path (C:\\Users\\you\\OneDrive\\memory); on macOS/Linux use a POSIX path. Restart Claude Desktop after editing the config.

Cursor config

The setup wizard (see Setup) writes this for you, in Cursor's global config file: %USERPROFILE%\.cursor\mcp.json on Windows, ~/.cursor/mcp.json on macOS/Linux. If that file does not exist yet but the .cursor directory does, the wizard creates it (no backup is needed — there is nothing to back up); if the directory does not exist, the wizard writes nothing and prints a ready-to-paste snippet instead. Project-level .cursor/mcp.json files are not written: the global config makes the server available in every project. Only the Windows path has been verified on a real machine; the macOS/Linux paths use the same home-based logic and are marked untested.

{
  "mcpServers": {
    "memdrive": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/memdrive-mcp/dist/index.js"],
      "env": {
        "MEMDRIVE_ROOT": "/absolute/path/to/your/library",
        "MEMDRIVE_RESPONSE_BUDGET_BYTES": "10000000"
      }
    }
  }
}

The type: "stdio" field is required by Cursor; Claude Desktop entries carry no type field. The wizard writes the 10,000,000-byte budget above into Cursor's entry (see Limits for the evidence: verified 2026-10-30, exact ceiling unmeasured). Restart Cursor after editing the config, and make sure the server is enabled in Cursor's MCP settings. Cursor's MCP logs (Output panel → "MCP Logs") are the first place to look when a tool does not appear.

VS Code config

The setup wizard (see Setup) writes this for you, in VS Code's Copilot Global config file: %USERPROFILE%\.copilot\mcp-config.json on Windows, ~/.copilot/mcp-config.json on macOS/Linux. If that file does not exist yet but the .copilot directory does, the wizard creates it (no backup is needed — there is nothing to back up); if the directory does not exist, the wizard writes nothing and prints a ready-to-paste snippet instead. Only the Windows path has been verified on a real machine; the macOS/Linux paths use the same home-based logic and are marked untested. The COPILOT_HOME environment variable is not read — only the home-directory location above is used.

{
  "mcpServers": {
    "memdrive": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/memdrive-mcp/dist/index.js"],
      "env": {
        "MEMDRIVE_ROOT": "/absolute/path/to/your/library",
        "MEMDRIVE_RESPONSE_BUDGET_BYTES": "10000000"
      }
    }
  }
}

The entry shape above was verified on a real Windows machine (manual MCP: Add Server flow, Copilot Global config): top-level mcpServers, type: "stdio", command: "node", absolute dist/index.js args, and VS Code's own "tools": ["*"] field alongside them. When the wizard merges into an existing entry, that tools field is preserved, as are every other key and every other server; a freshly created entry gets no tools field. The wizard writes the 10,000,000-byte budget above into VS Code's entry (see Limits for the evidence: partly verified, exact ceiling unmeasured). Fully quit and restart VS Code after editing the config, and make sure the server is enabled in VS Code's MCP settings. VS Code's MCP logs are the first place to look when a tool does not appear. Only list_directory and a bundled image read have been verified in VS Code on a real machine so far; the other tools still need a real-machine check (see Roadmap).

Claude Code config

UNVERIFIED — read this first. The Claude Code adapter was added from Anthropic's official docs only (checked 2026-10-31) and has never been tested on a real machine, in any host. The 10,000,000-byte budget below is an estimate set by the author's decision (Claude Code is a paid product; a limit as stingy as Claude Desktop's would make no sense for paying users), not a measurement. If a bundled read fails or comes back truncated in Claude Code, please report the exact error — that report is how the default gets corrected.

The setup wizard (see Setup) writes this for you, in Claude Code's user scope: the top-level mcpServers key of the one ~/.claude.json file (%USERPROFILE%\.claude.json on Windows, ~/.claude.json on macOS/Linux). When CLAUDE_CONFIG_DIR is set, the file lives inside that directory instead. Local scope (per-project entries inside the same file) and project scope (.mcp.json in a project root) are not written: the wizard writes the user-global config only, so the server is available in every project. If ~/.claude.json does not exist, the wizard writes nothing and prints a ready-to-paste snippet instead — it never creates the file, because ~/.claude.json is Claude Code's own main state file (it also holds project records), not a dedicated MCP file, and creating a bare copy was never verified.

{
  "mcpServers": {
    "memdrive": {
      "command": "node",
      "args": ["/absolute/path/to/memdrive-mcp/dist/index.js"],
      "env": {
        "MEMDRIVE_ROOT": "/absolute/path/to/your/library",
        "MEMDRIVE_RESPONSE_BUDGET_BYTES": "10000000"
      }
    }
  }
}

The entry carries no type field: Claude Code reads an entry without a type as a stdio server, the same shape as a Claude Desktop entry. The budget above controls only how much this server sends. Claude Code applies its own output limits on top (default 25,000 tokens per tool result; long text results are spilled to a file for the model to read back), so a large bundled read may arrive as a file reference rather than inline content. To raise Claude Code's own limit, set MAX_MCP_OUTPUT_TOKENS in the shell before starting Claude Code (for example MAX_MCP_OUTPUT_TOKENS=50000 claude). Check the connection with claude mcp list or the /mcp panel.

Optional: raise (or lower) the read_file total response budget if your client allows larger tool results than Claude Desktop's ~1 MB ceiling:

"env": {
  "MEMDRIVE_ROOT": "...",
  "MEMDRIVE_RESPONSE_BUDGET_BYTES": "5000000"
}

The default is 950,000 bytes; values are clamped to 100,000–50,000,000. See Limits before raising it.

Setup wizard & launchers

node dist/index.js setup runs an interactive wizard (no new dependencies — plain Node readline). After npm publish, the same wizard runs as npx memdrive-mcp setup; until the package is published, use the zip + launcher form below.

What the wizard does, in order:

  1. Chooses a host. The wizard asks which host to configure — 1 Claude Desktop, 2 Cursor, 3 VS Code, 4 Claude Code (Enter = 1). You can skip the question with an argument: node dist/index.js setup cursor (or setup claude / setup claude-desktop, setup vscode — only that one word, no vs-code / code alias, setup claude-code — only that spelling, code is not an alias). The argument is an optional shortcut for people who already know which host they want; the prompt is the default, foolproof path, including for npx memdrive-mcp setup and the launchers, which call the wizard with no argument. An unrecognised argument falls back to the prompt instead of guessing a host.

  2. Finds a library folder. It probes for existing sync folders — OneDrive, Google Drive, iCloud — plus the ~/memdrive default, and shows a numbered menu. Google Drive on Windows is probed in three steps: the DriveFS install folder must exist, then a PowerShell volume-label probe finds the drive letter, then common paths (G:\My Drive, H:\My Drive, …) are checked for existence — no drive letter is ever assumed. You can also type a custom absolute path (~ is expanded). The chosen folder is created if it does not exist.

  3. Finds the host config by probing the known locations. Claude Desktop: macOS Application Support; Windows %APPDATA%\Claude plus the %LOCALAPPDATA% Store/per-user locations. Cursor: the global config file only, %USERPROFILE%\.cursor\mcp.json on Windows and ~/.cursor/mcp.json on macOS/Linux, returned only when the .cursor directory exists. VS Code: the Copilot Global config file only, %USERPROFILE%\.copilot\mcp-config.json on Windows and ~/.copilot/mcp-config.json on macOS/Linux, returned only when the .copilot directory exists. Claude Code: the user scope only, the top-level mcpServers key of the one ~/.claude.json file (%USERPROFILE%\.claude.json on Windows, ~/.claude.json on macOS/Linux, or inside CLAUDE_CONFIG_DIR when that variable is set), returned only when the file already exists. Exactly one file → it is used; several → you pick one; none → nothing is written and the wizard prints a ready-to-paste snippet instead.

  4. Writes the config safely. An existing file is backed up first (<file>.bak, or <file>.bak-<timestamp> when a backup already exists, so an earlier backup is never overwritten). The mcpServers.memdrive entry (command: node, args: [<absolute path to dist/index.js>], env: {MEMDRIVE_ROOT: <chosen folder>}, plus type: "stdio" for Cursor and VS Code, plus the host's response budget in env for Cursor, VS Code, and Claude Code — see Limits; Claude Desktop entries carry no budget env, and Claude Code entries carry no type field) is merged in; every other key and every other server is preserved, and an existing entry's "tools": ["*"] field (VS Code) is carried over. For Cursor and VS Code, a missing config file is created instead (the host directory already exists), with no backup to take. A missing Claude Desktop or Claude Code file is never created. A corrupt config file aborts the write entirely — nothing is backed up, nothing is changed. Then it tells you to fully quit and restart the host you configured.

The launchers (setup.bat for Windows, setup.sh for macOS/Linux, setup.command for double-clicking on macOS) are thin shells: they check for Node.js 18+, run npm install + npm run build (failures shown plainly, script stops), then run the wizard. All logic stays in Node; the scripts contain no configuration of their own.

Windows SmartScreen note. If you downloaded the zip from the internet, Windows may show "Windows protected your PC" when you run setup.bat. That is SmartScreen reacting to a downloaded file, not evidence of a problem: setup.bat is plain text — open it in Notepad and read it before running if you like. To proceed, click More info, then Run anyway. No code signing is used (a paid certificate is only worth it once the project earns revenue).

Other hosts. The wizard writes Claude Desktop, Cursor, VS Code, and Claude Code config (global config for Cursor, Copilot Global config for VS Code, user scope for Claude Code). The config-writing code is isolated behind a small per-host adapter so another host can be added later, but only after that host's config surface is verified on a real machine — with one exception: Claude Code was added from Anthropic's official docs only and is unverified (see Claude Code config). Codex/Gemini are CLIs with no desktop config file, Grok has no desktop MCP config surface, and no Muse desktop app exists. New hosts are added only on user feedback after these four.

Tools

Tool

What it does

list_directory(path?)

Lists the immediate children of a directory in the library (root by default).

search_files(keyword, path?)

Recursive keyword search: file names and, for small text files, contents.

save_file(path, content, mode?, images?)

Writes text (usually Markdown). Modes: new (default, refuses to overwrite), overwrite, append. Parent folders are created automatically. Say "把截图存下来" and the model passes images: ["clipboard"] — the server reads the clipboard on your machine; never paste the image into the chat.

read_file(path, include_images?)

Reads text, or a Markdown file together with its referenced images in one response, within one total response budget. Pass include_images: false for text only plus the image-path list (step 1 of two-step reading).

open_image(path)

Opens an image file in the OS default image viewer, at full original quality. Only when the user explicitly asks to view the original — never automatically, and never returns image bytes to the model.

open_containing_folder(path?)

Opens the folder containing a file (or the folder itself) in the OS file manager, without highlighting or selecting any file. Only when the user explicitly asks to open the folder — never automatically, and never returns folder contents to the model. Omit the path to open the library root.

Reading back: packed, two-step, and single-image

One total budget governs every read_file response (text bytes + base64 bytes of all image blocks together, default 950,000). Text is guaranteed first; images share only what the text leaves. An image that does not fit is downscaled in memory to fit the remaining budget, or skipped with a note — the read never fails as a whole because of an image, and the file on disk is never modified. Three ways to read:

  1. Packed read (default). read_file on a Markdown file returns the text together with its referenced images in one response. Best for short notes with one or two small pictures. A large screenshot (for example ~800 KB on disk, ~1.1 MB as base64) is downscaled in memory to fit the budget instead of blowing up the whole response the way it did before 0.1.1.

  2. Two-step read (several images, or one large image). First call read_file with include_images: false: you get the text plus the list of referenced image paths (library-relative, e.g. notes/assets/shot-....png). Then call read_file once per image path. Each direct image read gets the whole budget to itself, so each picture keeps the best quality the budget allows — this is the way to get a large screenshot back at full usable quality.

  3. Single-image read. read_file on an image path directly returns that one image. It is subject to the same total budget: the image is returned untouched when it fits, and downscaled in memory only when the image itself exceeds the budget (or the 3.5 MB per-image ceiling). If an image cannot be fitted within the budget at all (for example a format the built-in decoder cannot shrink), the result is text explaining that, not an error.

Viewing an original image: open_image

read_file returns a preview that fits the response budget — good enough to read, not always the original pixels. When the user explicitly asks to view the original ("open this image", "在系统里打开这张图"), open_image opens the file in the operating system's default image viewer (Photos on Windows/macOS, the default viewer on Linux) at full quality. The tool returns only a short text confirmation; no image bytes go to the model.

The rule is written into the tool description itself: the model must only call open_image on an explicit user request, never automatically after a read or a save. Opening a viewer window is a visible side effect on the user's screen, and unprompted popups are not acceptable. Only image files inside the library root open; non-images, directories, missing files, and sandbox escapes are rejected, and the viewer is launched with an argument array (never a shell string), so a crafted filename cannot inject a command.

Opening a note's folder: open_containing_folder

When the user explicitly asks to open a note's folder in the system ("open the folder", "在系统里打开这个笔记所在的文件夹"), open_containing_folder opens that folder in the operating system's file manager (Explorer on Windows, Finder on macOS, the default file manager on Linux). A file opens its parent folder; a folder opens itself; an empty path opens the whole library root. The folder opens without highlighting or selecting any file — no explorer /select, no Finder selection, no reveal-with-selection.

The rule is written into the tool description itself, the same way as open_image: only on an explicit user request, never automatically after a read or a save. The tool returns only a short text confirmation naming the folder opened; no folder contents go to the model (use list_directory to see what is in the folder). Only paths inside the library root open; missing paths and sandbox escapes are rejected, nothing is modified, and the folder is launched with an argument-array launcher (never a shell string), so a crafted filename cannot inject a command. On Windows the folder launch goes through the shell (cmd /c start "" explorer.exe /n,<path>, switch and path in one comma-joined argument), so the folder opens as a new Explorer window every time instead of a hidden tab in an already-open Explorer window; image files still open through the normal viewer launch, unchanged.

Saving with images

save_file accepts an images array mixing three source kinds. Clipboard comes first, because it is the one people get wrong:

  • The literal string "clipboard" — first choice for screenshots. Just tell the model "把截图存下来" / "把剪贴板里的图存下来". The server reads the clipboard directly on your own machine. You do not need to paste, upload, or send the image into the chat, and the model must never claim it cannot read the clipboard or that the library is text-only. (This rule is written at the very top of the save_file tool description, so the model sees it before anything else.)

  • Local file paths — e.g. ~/Pictures/shot.png (quotes stripped, ~ expanded).

  • http(s) URLs — downloaded directly, zero token cost.

Images land in a sibling assets/ folder, renamed <document-name>-<timestamp>.<ext>, and for Markdown files a standard ![alt](assets/...) reference is appended automatically. Originals are always kept at full quality.

Interaction rule (built into the tool description): before calling save_file, the model must show you the exact destination path and filename and get your confirmation in the chat. There is no popup — the confirmation happens in the conversation.

Clipboard edge cases

  • Clipboard empty or holding text instead of an image: the text is still saved; the result tells you to re-screenshot.

  • Headless environments (Docker, servers, NAS): clipboard capture reports itself as unsupported with a suggestion to use a file path or URL. The server never crashes on clipboard/image failures.

Limits (all in src/config.ts, nowhere else — except the response budget, which is also env-overridable)

Constant

Value

Meaning

RESPONSE_BUDGET_DEFAULT_BYTES

950,000

Default total budget for one read_file response: UTF-8 bytes of the text block plus base64 bytes of every image block, counted together. Overridable with MEMDRIVE_RESPONSE_BUDGET_BYTES, clamped to 100,000–50,000,000 (RESPONSE_BUDGET_MIN/MAX_BYTES). The wizard writes a per-host override into Cursor's, VS Code's, and Claude Code's config entries (see the per-host table below); Claude Desktop and unknown hosts keep this default.

TEXT_MAX_BYTES

1,000,000

Text returned by read_file is truncated here (with a note) — and also at the total budget, whichever is smaller. Text is guaranteed first; images get only the remainder.

IMAGE_PREVIEW_MAX_BYTES

3,500,000

Per-image preview ceiling (binary bytes). Image previews are downscaled in memory below this and below what the remaining response budget allows, whichever is smaller. The preview ladder tries a full-resolution JPEG re-encode first, trying JPEG qualities 95, 90, then 80 before shrinking, then shrinks in 0.9 steps at quality 80, returning the first attempt that fits — so the preview stays close to the largest size the budget allows instead of stopping at a coarse first shrink, and spends headroom on sharpness when full resolution already fits. The on-disk original is never modified.

Why a total budget, and why 950,000: Claude Desktop rejects a whole tool result over 1,048,576 bytes. The old per-part caps (1 MB text, 3.5 MB per image, no combined check) let a bundled read blow past that wall — in the real 2026-10-28 test, an 813.5 KB screenshot became ~1.11 MB of base64 and the entire read was rejected. 950,000 leaves ~98 KB of headroom for JSON framing and notes. Raise the budget only if your client demonstrably accepts larger results; the server cannot detect a client's limit (MCP initialize carries no host/limit information, and no clientInfo identification is done), so the default stays at the lowest known ceiling and is treated as universal across Claude Desktop plans and unknown hosts. Three different limits are at work — the host's result cap, this server's budget and 3.5 MB per-image ceiling, and the model's own pixel/token scaling — and the read_file tool description states all three, so the model does not have to guess which one bit.

Per-host response budgets (written by the wizard into each host's config entry as MEMDRIVE_RESPONSE_BUDGET_BYTES; the server cannot identify the host, so the env value is the only way to pass the budget through). Do not read more into the Cursor and VS Code rows than the evidence states: Cursor is verified and VS Code is partly verified, and neither exact ceiling was measured.

Host

Budget

Evidence

Claude Desktop

950,000

Verified: 2026-10-28 single-variable experiment — with the budget disabled via the environment variable, the same bundled read failed twice with the exact 1,048,576 error; 950,000 leaves ~98 KB of headroom for JSON framing and notes.

Cursor

10,000,000

Verified: 2026-10-30 single bundled read passed (notes/测试A.md, four distinct image references, include_images default true, test budget 50,000,000, 26 seconds, no host size error); each preview reported as 2.24 MB downscaled in memory, original untouched, totalling ~8.96 MB binary / ~11.95 MB base64; ~2 MB of headroom is left; the exact ceiling was not measured and the ladder is closed. The test line was then restored to 10,000,000 and a normal read re-verified.

VS Code

10,000,000

Partly verified: 2026-10-29 four-image bundled read passed (notes/测试A.md, four distinct copies of a 10.44 MB PNG); each preview reported as 2.24 MB to two decimals, totalling ~8.96 MB binary / ~11.95 MB base64; ~2 MB of headroom is left; the exact ceiling was not measured and the ladder is closed — no further probing.

Claude Code

10,000,000

ESTIMATED, UNVERIFIED. Set by the author's decision 2026-10-31, never tested on a real machine: Claude Code is a paid product, so a limit as stingy as Claude Desktop's would make no sense for paying users; if the estimate is wrong, user reports of oversized-result errors are the feedback path. Claude Code also applies its own output limits on top of this server-side budget (default 25,000 tokens per tool result; long text results spilled to a file), so this value controls only how much the server sends. Raise Claude Code's own limit with MAX_MCP_OUTPUT_TOKENS before starting it.

ChatGPT, Grok, and other hosts are untested for the limit; the 950,000 default is treated as universal for unknown hosts rather than assuming a larger limit any of them has not demonstrated.

Why 3.5 MB: base64 inflates binary by 4/3, so 3.5 MB becomes ~4.67 MB of base64 text, under every vendor image cap checked in the official docs (5 MB Bedrock/Vertex, 7 MB Gemini, 10 MB Claude API, 20 MB OpenAI). Do not raise it without re-checking those docs. It still caps any single preview even when the total budget is raised above it.

Other caps: at most 20 referenced images per read_file response (the total budget usually binds first); search_files returns at most 200 hits and only content-searches files under 256 KB; URL downloads have a 30 s timeout and a 500 MB safety ceiling (a disk-exhaustion guard, not a product limit).

Security

  • Root sandbox (hard). Every path is locked to MEMDRIVE_ROOT. ../ escapes, absolute paths outside the root, and symlinks inside the root that point outside are all rejected — including symlinks in the parent chain of not-yet-created files. Violations return a clear error.

  • Local image sources are OS paths, not library paths. A save_file image entry like ~/Pictures/shot.png intentionally reads from outside the root; only the destination is sandboxed.

  • No network listeners. stdio transport only; nothing is exposed.

  • Zero native dependencies. Pure-JS dependency tree (MCP SDK, zod, jimp). No node-gyp, no C++ builds, no Sharp.

  • Image formats. jimp (the pure-JS decoder) reads PNG/JPEG/GIF/BMP/ TIFF. WebP files pass through untouched when under the preview cap and are reported (not crashed on) when over it; SVG files are returned as text, never as image blocks; GIFs read as their first frame.

Verifying with MCP Inspector (step 1, zero model cost)

npm run build
npx -y @modelcontextprotocol/inspector --cli node dist/index.js --method tools/list
npx -y @modelcontextprotocol/inspector --cli node dist/index.js --method tools/call --tool-name list_directory

Note: the Inspector CLI spawns the server with its own environment, so MEMDRIVE_ROOT set in your shell may not reach it — it defaults to ~/memdrive. The interactive Inspector UI (npx @modelcontextprotocol/inspector without --cli) lets you set environment variables explicitly.

Development

npm install
npm run build      # tsc, strict
npm run typecheck  # tsc --noEmit
npm test           # protocol tests: SDK Client over stdio (see TEST-REPORT.md)

The SDK version is pinned exactly (@modelcontextprotocol/sdk 1.32.2, the v1.x maintenance line) and package-lock.json is committed. The SDK has a v2 line under separate package names; this project deliberately stays on v1.x until there is a reason to migrate.

Roadmap (not in this MVP)

  • WebDAV: interface reserved behind the existing StorageBackend interface but not implemented. Whether it is implemented later depends on user feedback, and it will only be considered if the user base is large with clear demand.

  • Windows clipboard capture verified on real hardware (2026-10-28, screenshot save via Claude Desktop); the macOS clipboard branch is still implemented from the documented OS pattern only — no macOS machine was available. The 0.1.3 quality ladder passed its real-conversation retest in Claude Desktop (2026-10-28: 359.0 KB preview of the 1.22 MB comment screenshot, original untouched).

  • Still to verify on a real Windows machine (see TEST-REPORT.md §14): the setup wizard's VS Code path end-to-end (host prompt choice 3 and setup vscode argument, Copilot Global config creation/merge with "tools": ["*"] preserved, restart VS Code, all six tools in VS Code — only list_directory and a bundled image read have been verified there so far), the wizard's Cursor path end-to-end (host prompt and argument, global config creation, restart Cursor, tools + read/save/open_image/ open_containing_folder in Cursor), open_containing_folder opening a folder once in each host, and a Claude Desktop regression check (its entry is byte-identical); the macOS wizard branches (setup.command, iCloud/Google Drive candidates, open) and the PowerShell Google Drive probe are untested on real hardware. No further Cursor or VS Code size-limit probing is planned.

License

MIT — see LICENSE.

Support

If MemDrive saves you time, you can support its development. Thank you!

  • Ko-fi: ko-fi.com/newmannn91

  • USDT (TRC-20 only): send only TRC-20 USDT to the address below. Do not send other tokens or use another network — they cannot be recovered.

TU9GBiQ1Ji1Fm5YECYThjcchTofj8B6uCD
  • WeChat Pay: scan the code below.

微信用户可扫码赞赏。

Available Tools

6 tools
list_directoryA

List the immediate children (subfolders and files) of a directory inside the MemDrive memory library. Returns one line per entry with type, size, and modification time. Directories sort first. Use this to explore what is already stored before reading or saving. Paths are relative to the library root (MEMDRIVE_ROOT). Omit path or pass "" for the root. Absolute paths are accepted only when they stay inside the root.

NameRequiredDescriptionDefault
pathNoDirectory to list, relative to the library root. Omit or pass "" for the root.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden and does well: it discloses return format (one line per entry with type, size, modification time), sort order (directories first), and a real constraint (absolute paths accepted only when inside the root). It doesn't explicitly state read-only-ness, but listing semantics make that clear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then behavior, then usage, then path handling. Every sentence earns its place and none is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no annotations and no output schema, the description explains the return format, sorting, and path constraints, so an agent has everything needed to call it correctly and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds value beyond the schema by noting absolute paths are accepted only when they stay inside the root — a constraint not present in the schema's path property. This meaningfully enriches the single parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (immediate children of a directory) with precise scope ('immediate', not recursive), making it clearly distinct from siblings like search_files and read_file. An agent can tell what this does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use this to explore what is already stored before reading or saving' gives a clear when-to-use context. It doesn't explicitly name search_files as the alternative for finding a specific file, but the exploration framing adequately distinguishes listing from searching/reading.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

open_containing_folderA

Open the folder containing a file or directory from the MemDrive memory library in the operating system's file manager (Explorer on Windows, Finder on macOS, the default file manager on Linux). A file opens its parent folder; a folder opens itself; an empty path opens the whole library root. The folder is opened without highlighting or selecting any file. USE ONLY WHEN THE USER EXPLICITLY ASKS TO OPEN THE FOLDER — for example "open the folder", "show me this note in the file manager", or "在系统里打开这个笔记所在的文件夹". NEVER call open_containing_folder automatically after a read_file, a save_file, or any other tool call, and never open a folder the user has not asked to open. Opening a file manager window is a visible side effect on the user's screen; the model must not cause it unprompted. The folder contents are never returned to the model: the result is only a short text confirmation naming the folder that was opened (or a note when no file manager is available, for example on a headless machine). To see what is in the folder, use list_directory instead. Only paths inside the library root can be opened. Missing paths and paths escaping the root are rejected with a note. Nothing is modified. Paths are relative to the library root (MEMDRIVE_ROOT). Absolute paths are accepted only when they stay inside the root.

NameRequiredDescriptionDefault
pathNoFile or folder whose containing folder to open, relative to the library root (for example "notes/2026-10-28.md" opens "notes"). Omit or pass "" to open the library root. Only call this when the user explicitly asked to open the folder.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations present, the description carries the full burden and does so: it discloses the visible side effect on the user's screen, that no file is highlighted/selected, that contents are never returned to the model, that the result is only a short text confirmation, and that headless machines yield a note instead. It also states safety boundaries — paths escaping the root are rejected and nothing is modified.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the action and the three path cases, then usage rules, then behavioral caveats — a sensible ordering with no filler. It is somewhat longer than needed because the usage restriction is repeated in the schema and again in the paragraph, but every sentence still carries real information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-optional-parameter side-effecting tool with no annotations and no output schema, the description covers everything an agent needs: invocation conditions, path resolution, failure modes (missing paths, root escape, no file manager), and what the result looks like.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3; the description adds genuine meaning on top by defining the empty-string case, the parent-folder resolution rule, and that absolute paths are accepted only when they remain inside MEMDRIVE_ROOT. It does not add format/syntax detail beyond the schema examples, so it stops short of a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource ("Open the folder containing a file or directory") and immediately disambiguates the three input cases: a file opens its parent, a folder opens itself, an empty path opens the library root. It is clearly distinguishable from list_directory, which is named as the way to actually see contents.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states the when ("USE ONLY WHEN THE USER EXPLICITLY ASKS TO OPEN THE FOLDER"), gives example phrasings including a non-English one, names explicit exclusions (never after read_file/save_file or any other tool call), and routes to the alternative (list_directory) for the different need of inspecting contents.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

open_imageA

Open an image file from the MemDrive memory library in the operating system's default image viewer (Photos on Windows/macOS, the default viewer on Linux), at full original quality. USE ONLY WHEN THE USER EXPLICITLY ASKS TO VIEW THE ORIGINAL IMAGE — for example "open this image", "show me the original", or "在系统里打开这张图". NEVER call open_image automatically after a read_file, a save_file, or any other tool call, and never open an image the user has not asked to view. Opening a viewer window is a visible side effect on the user's screen; the model must not cause it unprompted. The image itself is never returned to the model: the result is only a short text confirmation (or a note when no viewer is available, for example on a headless machine). To see the picture in the conversation, use read_file on the image path instead. Only image files inside the library root can be opened. Non-image files, directories, missing files, and paths escaping the root are rejected with a note. The file on disk is never modified. Paths are relative to the library root (MEMDRIVE_ROOT). Absolute paths are accepted only when they stay inside the root.

NameRequiredDescriptionDefault
pathYesImage file to open, relative to the library root (for example "notes/assets/shot-20261028-120000-000.png"). Only call this when the user explicitly asked to view the original image.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does: it discloses the visible side effect (a viewer window on the user's screen), that the image is never returned to the model, that the result is only a short text confirmation, that headless machines yield a note rather than an error, and that the file on disk is never modified.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, and the trigger/gating rule follows immediately. The gating rule is partially duplicated by the path parameter's schema description and a few clauses (Linux viewer specifics, restating the no-modification guarantee) could be trimmed without loss.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers everything an agent needs for a one-parameter, no-output-schema tool: what it does, when it is permitted, what it returns and does not return, error behavior for bad paths, and the path resolution model. No meaningful gap remains.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuinely new semantics: paths resolve relative to MEMDRIVE_ROOT, absolute paths are only accepted inside the root, and out-of-root or non-image paths are rejected. It stops short of describing other edge cases, but the added value is real.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (open an image file from the MemDrive library) and names the exact mechanism (OS default viewer, full original quality). It also distinguishes itself from read_file, which is the sibling an agent would otherwise confuse it with.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use triggers with example phrasings, explicit when-NOT-to-use rules ('NEVER call after read_file, save_file, or any other tool call'), and the alternative to use instead (read_file for in-conversation viewing). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_fileA

Read a file from the MemDrive memory library. TOTAL RESPONSE BUDGET — THREE LIMITS ON THREE DIFFERENT LAYERS. (1) HOST: the MCP host (Claude Desktop, the only host verified so far) rejects a whole tool result over about 1 MB ("Tool result is too large. Maximum size is 1MB"). That limit lives in the host, outside this server, and is NOT a model or context-window limit; other hosts (ChatGPT, Grok) are untested, so this server assumes the same ~1 MB ceiling for all of them. (2) SERVER: text bytes plus the base64 bytes of every image block in one response must together fit inside a single total budget — default 950,000 bytes, overridable with MEMDRIVE_RESPONSE_BUDGET_BYTES (clamped to 100,000–50,000,000) — a safety margin under the host limit. Text comes first and is guaranteed; images share only the budget the text leaves. An image that does not fit is downscaled in memory to fit it, or skipped with a note — a read never fails as a whole because of an image. The file on disk is never modified. Previews are built at full resolution first, trying higher JPEG quality before shrinking, so a preview uses the budget for sharpness instead of stopping far below it. At the default budget the effective per-image cap is about 712,000 binary bytes (after base64 inflation), so the separate 3.5 MB per-image preview ceiling only binds when the budget is raised for a host with a larger limit. HISTORY: before v0.1.1 this server had NO total budget, so a bundled read whose base64 exceeded the host limit was rejected wholesale by the host — that is what happened to the first read of an 813.5 KB image (~1.11 MB as base64). (3) MODEL: once the model receives an image it scales it by pixels into tokens under its own limits — a separate layer from the byte limits above, not something this server controls. TWO-STEP READING — USE THIS WHENEVER A DOCUMENT REFERENCES SEVERAL IMAGES, OR ONE LARGE IMAGE: Step 1, call read_file with include_images=false to read the text and get the list of referenced image paths. Step 2, call read_file once per referenced image, passing that image path itself as path, so the image alone gets the whole response budget and keeps the best quality the budget allows. Reading an image file directly is also limited by the same total budget: a single image is returned untouched when it fits, and downscaled in memory only when the image itself exceeds the budget. Text files: returned as text (truncated at the smaller of the 1 MB text cap and the total budget, with a note when truncated). Markdown files: with include_images=true (the default), the text is returned TOGETHER WITH every locally-referenced image that fits the remaining budget in the same response — each image becomes an image content block, so the model sees words and pictures together. Remote (http) and data: images are skipped with a note. Images over the 3.5 MB preview cap are downscaled in memory only; the file on disk is never modified. Image files: returned as a single image content block (downscaled in memory only when over the preview cap or the total budget). If an image cannot be fitted within the budget at all, the result is text explaining that, not an error — the original is untouched. SVG files are returned as text (they are XML), never as image blocks. Paths are relative to the library root (MEMDRIVE_ROOT). Absolute paths are accepted only when they stay inside the root.

NameRequiredDescriptionDefault
pathYesFile to read, relative to the library root (for example "notes/2026-10-28.md").
include_imagesNoFor Markdown files: true (default) returns the text together with its referenced images, within the total response budget; false returns text only plus the list of referenced image paths (step 1 of two-step reading). Ignored for non-Markdown files.

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so: it states the file on disk is never modified (read-only), that images are downscaled in memory or skipped with a note rather than failing the read, that SVG is returned as text, that remote/data: images are skipped, and that text is truncated with a note. Error and degradation semantics are all disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded, but the body is an essay: three-layer budget theory, host-specific notes on ChatGPT/Grok being untested, env-var clamping ranges, and a historical anecdote about a v0.1.1 813.5 KB image failure that an agent cannot act on. A large fraction of the text does not help selection or invocation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates fully: return forms per file type (text, markdown with image blocks, single image block, text explaining an unfittable image), truncation behavior, and path/root constraints are all covered. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented in the schema, including that include_images defaults to true and is ignored for non-Markdown files. The description largely restates that (the two-step guidance is usage rather than parameter semantics), so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource ("Read a file from the MemDrive memory library") plus a scope statement on paths. It never explicitly distinguishes itself from the sibling open_image, which is a plausible source of confusion since read_file also returns image content blocks for image files.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The "TWO-STEP READING" block gives explicit when-to-use guidance: use it whenever a document references several images or one large image, with the exact sequence (include_images=false, then one call per image path). No guidance is given for choosing between read_file and siblings like search_files or list_directory, but within its own workflow the routing is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

save_fileA

CLIPBOARD FIRST — READ THIS BEFORE ANYTHING ELSE: When the user says to save a screenshot or an image from the clipboard — for example "把截图存下来", "把剪贴板里的图存下来", "save the screenshot", or any equivalent wording — pass images: ["clipboard"]. That is all it takes: the server reads the clipboard directly on the user's own machine. You do NOT need to see the clipboard or the image. NEVER ask the user to paste, upload, or send the image into the chat. NEVER say you cannot read the clipboard, that you cannot see images, or that this memory library can only store text. If the clipboard holds no image, the server reports that in the result and the text is still saved — tell the user to take the screenshot again and retry; do not invent a clipboard failure. Interaction rule — read before calling: Before calling this tool, show the user the EXACT destination path and filename you intend to write (for example: "notes/2026-10-28.md") and get their explicit confirmation in the chat. Never call save_file with a path or filename the user has not confirmed. If the user has not confirmed a location yet, ask them first instead of calling. There is no popup or confirmation dialog: confirmation happens here, in the conversation, through you. Save text (usually Markdown) into the MemDrive memory library. Modes: "new" (default) fails when the file already exists; "overwrite" replaces it; "append" adds to the end, creating the file when missing. Parent directories are created automatically. Images: pass an "images" array with any mix of the literal string "clipboard" (capture the latest screenshot from the OS clipboard — see the clipboard rule above), local file paths, or http(s) image URLs. Images are copied/downloaded/captured into a sibling assets/ folder, renamed "-.", and for Markdown files a standard image reference is appended to the document automatically. The on-disk original is always kept at full quality; only the preview handed to a model is ever downscaled. Clipboard behavior: when the clipboard is empty or holds text instead of an image, the text is still saved and the result explains what to do (re-screenshot). Clipboard capture never crashes the server; in headless environments it reports itself as unsupported and suggests a file path or URL instead. Paths are relative to the library root (MEMDRIVE_ROOT). Absolute paths are accepted only when they stay inside the root. The root is a hard sandbox: "../" escapes and symlinks pointing outside are rejected. Path cleaning: surrounding quotes are stripped, a leading ~ expands to the home directory, and separators are normalized.

NameRequiredDescriptionDefault
modeNoWrite mode: "new" (default, fails if the file exists), "overwrite", or "append".
pathYesDestination file path, relative to the library root (for example "notes/2026-10-28.md"). Must be confirmed with the user before calling.
imagesNoImages to archive with the document — CLIPBOARD FIRST: the literal string "clipboard" captures the latest screenshot/image from the OS clipboard on the machine running the server. Use it whenever the user mentions a screenshot or the clipboard: never ask them to paste the image into the chat, and never claim the clipboard cannot be read. Local file paths and http(s) image URLs are also accepted.
contentYesText content to save (usually Markdown).

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does: it discloses that parent directories are auto-created, that images are copied into a sibling assets/ folder and renamed "<document-name>-<timestamp>.<ext>" with a Markdown reference appended, that the on-disk original stays full quality while only the model preview is downscaled, and that the root is a hard sandbox rejecting "../" and out-of-root symlinks. It also pre-empts failure interpretation — empty clipboard still saves text and reports re-screenshot guidance, headless environments report clipboard as unsupported rather than crashing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The clipboard rule is stated three separate times (the CLIPBOARD FIRST block, the Images paragraph, and the Clipboard behavior paragraph), and the "never ask the user to paste" instruction is repeated again in the schema. The most important fact — what the tool does — is not front-loaded, appearing only after the clipboard and confirmation sections.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter mutation tool with no annotations and no output schema, the description covers everything an agent needs: write-mode semantics, directory creation, image handling and placement, sandbox limits, path normalization, and how to read the result on clipboard failure. Nothing material is left to inference.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema: path cleaning behavior (quote stripping, ~ expansion, separator normalization), sandbox containment rules for absolute paths, and the downstream effects of the images array (where files land, how they are named, what gets appended to Markdown). Only the mode and content parameters are left to the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource — "Save text (usually Markdown) into the MemDrive memory library" — and the images paragraph makes clear it also archives binary images, which separates it from read-only siblings like read_file and search_files. The purpose statement is buried in the fourth paragraph behind a clipboard preamble, so an agent must read past a lot of material before learning what the tool fundamentally does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit routing rules for the clipboard case (use images: ["clipboard"] whenever the user mentions a screenshot, never ask for a paste), a mandatory pre-call confirmation workflow with a concrete example, and mode selection guidance ("new" fails when the file exists; "overwrite"; "append" creates when missing). These are when-to-use and how-to-behave rules an agent cannot infer from the schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_filesA

Search the memory library for files by keyword: matches file names (case-insensitive substring) and, for small text files, file contents. Searches recursively under the given directory. Returns root-relative paths with a match kind (name/content) and, for content matches, the first matching line. Paths are relative to the library root (MEMDRIVE_ROOT). Omit path or pass "" to search the whole library.

NameRequiredDescriptionDefault
pathNoDirectory to search under, relative to the library root. Omit or pass "" for the whole library.
keywordYesKeyword to search for (case-insensitive substring).

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses matching rules (case-insensitive substring), recursion, the small-text-file caveat for content scanning, the path base (MEMDRIVE_ROOT), and the return shape including match kind and first matching line. It stops short of noting result limits, ordering, or pagination behavior, which matters for a recursive search.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with the core match semantics before the return format and path defaults. The final sentence largely duplicates the schema's path description, a small redundancy, but nothing else is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only, two-parameter search with no output schema, the description is nearly complete: it explains matching, scope, base path, and the return structure. The remaining gap is absence of any note on result caps or ordering when a broad search hits many files.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented in the schema; the description largely restates them (keyword matching semantics, path resolution). It adds only the MEMDRIVE_ROOT-relative framing, so baseline 3 is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("search the memory library for files by keyword") and defines exactly what is matched: file names via case-insensitive substring and, for small text files, contents. It does not explicitly name or contrast with the sibling tools list_directory or read_file, so the verb alone has to carry the differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides scope guidance ("omit path or pass \"\" to search the whole library") and implies usage via "searches recursively under the given directory." It never says when to prefer this over list_directory or read_file, nor when search is a poor fit (e.g. binary files, very large trees), leaving the choice to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv0.6.0
    • First observedlist_directory
    • First observedopen_containing_folder
    • First observedopen_image
    • First observedread_file
    • First observedsave_file
    • First observedsearch_files

TDQS

A4.2/5.0

Scored across 6 tools

Disambiguation5/5

Each tool maps to a distinct operation: browsing (list_directory), recursive lookup (search_files), write (save_file), read (read_file), and two explicit OS-side actions (open_image, open_containing_folder). The read_file vs open_image vs open_containing_folder boundary is spelled out in the descriptions ('returned to the model' vs 'opens a viewer window'), so misselection is unlikely.

Naming Consistency5/5

All six tools follow a strict snake_case verb_noun pattern: list_directory, search_files, save_file, read_file, open_image, open_containing_folder. Verbs are accurate and never clash (no duplicate verbs across the set).

Tool Count5/5

Six tools is well-scoped for a sandboxed file/memory library: one per core operation plus two narrowly gated OS-integration tools. Nothing feels redundant or padded.

Completeness3/5

Read, write (new/overwrite/append), list, and search are covered, but there is no delete, rename, or move operation — agents cannot clean up or reorganize the library, a likely dead end for memory-management workflows. The surface is usable but missing lifecycle operations.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides persistent long-term memory for AI assistants with tag-based retrieval, wiki-style linking, and source references, storing memories as markdown files with SQLite index.
    1
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI assistants to search, read, create, update, and remove personal markdown notes stored locally, providing persistent memory across sessions.
    84 npm
    2
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A personal, offline-first memory for AI assistants that enables them to read, search, and write to a shared folder of Markdown files, so they all remember you without needing a cloud.
    1
    MIT