Skip to content

feat(mcp): add mempalace_sync_status tool and freshness hook - #1347

Open
rusel95 wants to merge 1 commit into
MemPalace:developfrom
rusel95:feat/sync-mcp-tool-v2
Open

feat(mcp): add mempalace_sync_status tool and freshness hook#1347
rusel95 wants to merge 1 commit into
MemPalace:developfrom
rusel95:feat/sync-mcp-tool-v2

Conversation

@rusel95

@rusel95 rusel95 commented May 4, 2026

Copy link
Copy Markdown

🤔 The problem

An AI agent searches the palace and gets results. Are those results current? Were the source files modified since the last mine? There is no way to know — the agent just has to trust that the memories are fresh.

This is a correctness risk. Stale memories can inject outdated or contradictory context into live reasoning.

✅ What this does

MCP tool: mempalace_sync_status

A read-only tool that tells the agent exactly what is fresh, what is stale, and what to do about it:

// All good
{"status": "fresh", "total_source_files": 58, "fresh": 58, "stale": 0}

// Something changed
{
  "status": "stale",
  "fresh": 52, "stale": 6,
  "stale_files": [{"file": "/path/to/README.md", "drawers": 55, "wing": "my-project"}],
  "remine_commands": ["mempalace mine /path --wing my-project --force"],
  "message": "6 files changed since last mine. Run the remine_commands to refresh."
}

// Mined before content_hash support
{"status": "unknown", "message": "All 58 source files lack content_hash. Re-mine with latest version to enable freshness tracking."}

No side effects. The agent can call this before trusting search results, then suggest re-mine commands to the user.

Hook: mempal_freshness_hook.sh

Stop hook that checks freshness once per session (configurable CHECK_INTERVAL, default 3600s). Warns the agent when stale files are detected.

🔒 Security

  • SESSION_ID sanitized via tr -cd A-Za-z0-9_- to prevent path traversal in stamp file
  • Directory filter enforces path boundary (trailing separator) — /project does not match /project_other
  • Uses sed instead of grep -P for macOS compatibility
  • $CHECK_DIR quoted to handle paths with spaces

🧪 Tests

8 sync-specific tests + all 103 existing MCP server tests pass.

python -m pytest tests/test_mcp_server.py -q
111 passed

Depends on: #1343 (content_hash in drawer metadata — without it, tool returns status: unknown)
Relates to #224.

Adds a read-only MCP tool for AI agents to check whether palace memories
are up to date, plus a stop hook that warns when stale files are detected.

MCP tool mempalace_sync_status:
- Scans all drawers in batches of 500
- Compares stored content_hash against current file content
- Returns status: fresh | stale | missing | unknown | empty | error
- Returns stale_files list and ready-to-run remine_commands
- Returns status: unknown (not fresh) when all drawers lack content_hash
- Optional directory param scopes check with path boundary enforcement
- SESSION_ID sanitized to prevent path traversal in stamp file

Hook mempal_freshness_hook.sh:
- Checks freshness once per session (configurable CHECK_INTERVAL, default 3600s)
- Uses sed instead of grep -P for macOS compatibility
- Quotes CHECK_DIR to handle paths with spaces

Docs: adds mempalace_sync_status to website/reference/mcp-tools.md,
updates tool count from 29 to 30.

Depends on: feat/content-hash-foundation (content_hash in drawer metadata)

Relates to MemPalace#224.
@rusel95
rusel95 force-pushed the feat/sync-mcp-tool-v2 branch from 7a3db39 to 9a15986 Compare May 4, 2026 11:54
@rusel95

rusel95 commented May 4, 2026

Copy link
Copy Markdown
Author

✅ End-to-end testing completed

Ran the full freshness detection pipeline against real ChromaDB: mine files → edit/delete → call tool_sync_status() → verify status.

Tests verified (8 in tests/test_mcp_server.py + 4 e2e):

Scenario Expected Result
Mine 3 files, no changes status: fresh, stale: 0
Mine → edit README.md status: stale, stale_files has README, remine_commands present
Mine → delete notes.txt missing >= 1
Filter to /nonexistent/ total_source_files: 0
Empty palace status: empty
No palace Error response
Legacy drawers (no hash) status: unknown (honest, not false-fresh)
Directory filter scoping Only files under filtered path checked
python -m pytest tests/test_mcp_server.py -k sync -v
8 passed in 18s

Full suite (including readme claims test for tool count 29→30): 0 regressions.

@igorls igorls added enhancement New feature or request area/mcp MCP server and tools area/hooks Claude Code hook scripts (Stop, PreCompact, SessionStart) labels May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/hooks Claude Code hook scripts (Stop, PreCompact, SessionStart) area/mcp MCP server and tools enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants