Special Thanks
timkjr, for #237: found and fixed a timezone-boundary bug in timeframe deletion that had been silently missing memories near day boundaries on any host away from UTC.
PATCH release. The two Docker fixes are the reason to upgrade if you run the published images -- both were reproduced against doobidoo/mcp-memory-service:slim and :latest as published, not just against a local build. timkjr's timezone-boundary fix for timeframe deletion rides along.
Fixed
- fix(docker): move the remaining images off Python 3.10 (#295). The :slim image is the multi-arch one and was the only image left on an interpreter EOL in October 2026 while the standard image, CI, and local development had all moved to 3.12. Past that EOL, onnxruntime stopped publishing cp310 wheels after 1.23.2, so :slim was resolving six minor versions behind the 1.29.0 that everything else runs -- on the embedding runtime, that is the whole point of the image. Verified by building for both linux/amd64 and linux/arm64 exactly as release.yml does: both come up on Python 3.12.14 with onnxruntime 1.29.0, tokenizers 0.23.1, and sqlite-vec v0.1.9; the arm64 image is 636MB against 656MB before; an HTTP container serves {"status":"healthy"}, and a store followed by a semantic search returns the memory it just wrote. Dockerfile.glama and three deprecated compose files moved to the same interpreter in the same change.
- fix(docker): make the images start without a path override (#297). Every published image set MCP_MEMORY_SQLITE_PATH to /app/sqlite_db, which is the volume mount point and therefore always a directory -- a bare docker run exited on startup with "unable to open database file". Reproduced against doobidoo/mcp-memory-service:slim and :latest as published. The compose files papered over it with a real file path, including one of the documented docker run recipes, so the bug only showed up for anyone running the image the way the README's plain docker run example shows it. The default is now /app/sqlite_db/memory.db, and a directory is rejected before the connect attempt with a message that names both the problem and the fix, which is what anyone still carrying the old value in their own config will see on upgrade. The docs recipes that mounted /app/sqlite_data while the images declared /app/sqlite_db are corrected too -- following them as written never persisted anything. Closes #296.
- fix(storage): use UTC midnight for timeframe-delete date boundaries (#237, thanks timkjr). delete_by_timeframe and delete_before_date built their SQL date-range boundaries with datetime.combine(date, time()).timestamp(), which interprets a naive datetime as host-local time, while created_at is stored as a UTC epoch everywhere else in the codebase. On any host away from UTC this silently missed memories near day boundaries. Fixed across the sqlite-vec mixin, Cloudflare, and Milvus, plus the delete_memories time-only path in storage/base.py. Verified with base.py reverted and the contributor's regression test in place: it fails with deleted_count 1 instead of 2, the memory sitting in the nine-hour gap survives.
- test(tz): give the timezone back after a test borrows it (#298). Follow-up to #237. The regression test set TZ=Asia/Tokyo and undid it with a tzset() call in a finally block, which runs before monkeypatch restores the environment variable, so the C library kept JST for every test that ran afterward in the same worker. Restoring in the right order now lives in a reusable local_timezone fixture.
Full changelog: https://codeberg.org/doobidoo/mcp-memory-service/blob/main/CHANGELOG.md#1185---2026-08-25