Skip to content

v1.0.0 — first release

Choose a tag to compare

@st412m st412m released this 14 Oct 15:28
· 2 commits to main since this release

Continues ha-filesystem-mcp 2.9.0: the same server, now a standalone npm package that runs on Linux, in Docker and as the Home Assistant app.

Added

  • Documents. read_text_file, read_multiple_files, read_pdf_text and grep_files read PDF, Word (DOCX, DOC), Excel (XLSX, XLS), OpenDocument (ODT, ODS, ODP), PowerPoint (PPTX, PPT), EPUB, FB2, RTF, HTML and mail (EML, MSG, with attachments) as numbered lines with page, sheet, slide and attachment markers, through the doclines package. HTML, RTF, EML and FB2 read raw by default; extract: true gives their text. A scanned PDF is refused with the pages to read as images with read_pdf_page; a PDF with some pages without text lists those pages. Documents are read-only. Extracted text is cached in the state directory, outside the vault.
  • One folder, the vault. Every tool works inside one directory tree. A path outside it, a path that climbs out with .., a sibling directory whose name starts with the vault's own, or a symlink that leads out is refused with PATH_OUTSIDE_VAULT, and nothing is read or written.
  • 20 tools, each with a title and MCP annotations: reading (read_text_file, read_file, read_multiple_files, read_media_file, read_pdf_text, read_pdf_page), searching (grep_files, search_files), writing (write_file, edit_file, create_directory, move_file, trash_file), listing (list_directory, list_directory_with_sizes, directory_tree, get_file_info, list_allowed_directories), SQLite (sqlite_schema, sqlite_query). Tool descriptions say when to use a tool instead of its neighbour.
  • Search and line edits. grep_files returns path, rev and line count per file and numbered matching lines; read_text_file with offset/limit returns a range with the file's rev; edit_file replaces, inserts and deletes by line number in one atomic pass, guarded by rev (the first 8 hex characters of the SHA-256 of the content). A stale rev is refused and nothing is written.
  • Write policies. A .vault-policy marker in a directory sets its zone: read-only, edits only with the current rev, new files only, or free writes. Fields are inherited per field by the directories below. A marker that cannot be read locks its whole zone against writes. The listing tools print the policy in force.
  • Trash instead of delete. trash_file moves a file into its zone's trash with the arrival time stamped into the name; move_file brings it back. Auto-purge, off by default, erases files older than a set number of days from a zone's trash, once after start and then daily.
  • Policy editing outside the tools. everkeep policy show|set|clear on the server; in the Home Assistant app, the Vault policies page. Both write the same marker, and a directory's marker holds only what the directory sets itself: a subdirectory that changes only its mode shares the trash of the directory above. MCP tools cannot create, change, move or discard a marker, or a file or directory named like one.
  • PDF pages as images (read_pdf_page, read_media_file with #N) through poppler's pdftoppm.
  • SQLite, read-only. sqlite_schema and sqlite_query run sqlite3 -readonly -safe under a 256 MiB memory limit; one SELECT, WITH, VALUES or EXPLAIN statement, checked by a tokenizer before sqlite3 starts; a database with a live -wal is read from a private copy.
  • Case-insensitive file systems. The marker and trash names are compared regardless of case, and two paths that differ only in case are compared by the file they lead to, so a vault on exFAT, NTFS, a Windows or macOS folder mounted into Docker, or ext4 with casefold keeps its policies.
  • A path segment named like the marker is refused in any position, so no tool can create a directory called .vault-policy.
  • Two transports in one process. everkeep serve: MCP Streamable HTTP on /mcp, JSON responses. everkeep with no command: MCP on stdio, the same tools and policies.
  • Token. Generated by the server on its first start (32 random bytes as 64 hex characters, file mode 0600) and shown once; everkeep token shows it again, everkeep token --new replaces it. Accepted as the secret path /private_<token>/mcp (for claude.ai custom connectors) or as Authorization: Bearer <token> on /mcp. A wrong path gets an empty 404, a wrong Bearer token 401, /.well-known/* 404. On a localhost bind, a Host or Origin that is not localhost gets 403; allowed_hosts names the public host of a tunnel or proxy on the same machine that is accepted like localhost.
  • Configuration from flags, environment and a JSON file (EVERKEEP_CONFIG or ~/.config/everkeep/config.json); everkeep check-config validates it and checks pdfinfo, pdftoppm, sqlite3 and the case sensitivity of the vault. everkeep.example.json lists every key with its default.
  • Docker image ghcr.io/st412m/everkeep for linux/amd64 and linux/arm64: Node 22 on Alpine with poppler and sqlite, runs as uid 1000, vault at /vault, state at /data. compose.example.yaml shows a complete setup.
  • Optional one-line request log (log_requests), with the token masked.
  • Refuses to start natively on Windows and macOS, pointing to Docker.