How to Debug Memory Storage Issues Using Health Check Endpoints in MCP Memory Service
Query the /api/health/detailed endpoint to inspect storage backend statistics, memory counts, and database size, or use /api/health/sync-status for hybrid backend synchronization progress to quickly identify the root cause of memory storage failures.
The MCP Memory Service (doobidoo/mcp-memory-service) exposes HTTP health check endpoints that surface real-time storage backend statistics and system metrics. By analyzing these JSON payloads, you can debug memory storage issues without accessing the database directly or parsing application logs.
Health Check Endpoint Overview
Three endpoints in src/mcp_memory_service/web/api/health.py provide progressive levels of diagnostic detail:
/api/health— Returns minimal liveness status, version, and uptime/api/health/detailed— Returns full storage statistics, system metrics, and performance data/api/health/sync-status— Returns hybrid backend synchronization progress
Both basic and detailed endpoints delegate storage health checks to MemoryService.health_check(), implemented in src/mcp_memory_service/services/memory_service.py at lines 690-707, which calls storage.get_stats() on the configured backend.
Decoding the Detailed Health Payload
The /api/health/detailed endpoint returns a comprehensive JSON object containing storage metadata critical for debugging.
Storage Backend Statistics
The storage object reveals the backend type and data integrity:
{
"backend": "sqlite-vec",
"total_memories": 1247,
"unique_tags": 87,
"memories_this_week": 23,
"database_size_mb": 12.34,
"embedding_model": "all-MiniLM-L6-v2",
"embedding_dimension": 384
}
backend: Identifies the implementation (sqlite-vec,hybrid,cloudflare) fromstorage.get_stats()insrc/mcp_memory_service/storage/sqlite_vec.py(lines 2581-2619)total_memories: Count of non-soft-deleted rows viaSELECT COUNT(*) ... WHERE deleted_at IS NULLunique_tags: Distinct tag count; low values indicatenormalize_tagsissues insrc/mcp_memory_service/services/memory_service.py(lines 55-75)database_size_mb: Physical SQLite file size fromos.path.getsize(self.db_path); sudden drops indicate corruption or resets
Hybrid Sync Status
For hybrid backends, the /api/health/sync-status endpoint (lines 95-110 in health.py) queries get_initial_sync_status() implemented in src/mcp_memory_service/storage/hybrid.py (lines 1516-1525). This reveals whether background synchronization is stuck:
{
"sync_supported": true,
"status": {
"in_progress": true,
"pending_operations": 42,
"progress_percentage": 65
}
}
Step-by-Step Debugging Workflow
Follow this sequence to isolate memory storage issues using the health endpoints:
-
Verify Service Liveness
curl -s http://localhost:8000/api/health | jq .If
statusis not"healthy", check the service logs for startup failures in dependency injection (src/mcp_memory_service/web/dependencies.py). -
Inspect Storage Metrics
curl -s http://localhost:8000/api/health/detailed | jq .storageConfirm the
backendmatches your configuration andtotal_memoriesreflects expected data volume. -
Validate Database Growth
Monitor
database_size_mbacross requests. Static values during active writes indicate permission failures or storage backend disconnections. -
Check Tag Integrity
If
unique_tagsis zero despite memories existing, inspect thenormalize_tagsfunction inmemory_service.pyfor comma-handling bugs. -
Monitor Hybrid Synchronization
curl -s http://localhost:8000/api/health/sync-status | jq .Persistent
"in_progress": truewith highpending_operationsindicates network latency or authentication failures in the hybrid sync worker.
Diagnosing Common Storage Issues
Map symptoms to health payload indicators:
Service Startup Failures
If /api/health returns 500 or missing status field, the MemoryService failed to initialize. Check that the storage backend implements the get_stats() method declared in src/mcp_memory_service/storage/base.py (lines 763-770).
Silent Write Failures
When total_memories remains unchanged after API writes, verify database_size_mb growth. If both are static, the SQLite file lacks write permissions or the storage.store() method is failing silently.
Tag Search Anomalies
Low unique_tags with high total_memories signals that the tag normalization logic is stripping delimiters incorrectly. Compare the health output against direct storage queries:
from mcp_memory_service.storage.sqlite_vec import SqliteVectorStore
store = SqliteVectorStore(db_path="data/memory.db")
await store.initialize()
print(await store.get_stats())
Disk Space Exhaustion
When system.disk_percent exceeds 90% or database_size_mb approaches system.disk_free_gb, the host cannot allocate new pages. Enable database rotation or clean old memory segments.
Backend Mismatch
An backend value of "unknown" indicates the storage class does not properly implement get_stats(). Verify your configuration points to a valid MemoryStorage implementation.
Programmatic Health Check Examples
cURL Diagnostics for Storage Backend
Check storage statistics directly:
curl -s http://localhost:8000/api/health/detailed | jq .storage
Python Async Health Monitor
import httpx
import asyncio
async def check_storage_health():
async with httpx.AsyncClient() as client:
resp = await client.get("http://localhost:8000/api/health/detailed")
data = resp.json()
storage = data["storage"]
assert storage["backend"] == "sqlite-vec"
assert storage["total_memories"] > 0
assert storage["database_size_mb"] > 0
print(f"Backend: {storage['backend']}")
print(f"Memories: {storage['total_memories']}")
print(f"DB Size: {storage['database_size_mb']} MB")
asyncio.run(check_storage_health())
Direct Storage Inspection
Bypass HTTP to verify endpoint accuracy:
import asyncio
from mcp_memory_service.storage.sqlite_vec import SqliteVectorStore
async def verify_stats():
store = SqliteVectorStore(db_path="data/memory.db")
await store.initialize()
stats = await store.get_stats()
print(f"Direct storage query: {stats}")
asyncio.run(verify_stats())
Summary
/api/healthconfirms service process liveness and basic uptime/api/health/detailedexposes storage backend type, memory counts, database file size, and embedding configuration fromsqlite_vec.pyandhybrid.py/api/health/sync-statustracks background synchronization progress for hybrid deployments- Correlate
total_memories,unique_tags, anddatabase_size_mbagainst expected values to detect write failures or tag processing errors - Use
system.disk_percentandmemory_percentto identify resource exhaustion causing storage timeouts - Validate health endpoint output against direct
storage.get_stats()calls to ensure the HTTP layer accurately reflects backend state
Frequently Asked Questions
Why does /api/health return healthy but my memories are missing?
The basic endpoint only checks process liveness. Query /api/health/detailed and inspect storage.total_memories. If the count is zero despite previous writes, the service may be pointing to a different database file path or the storage backend failed to initialize properly. Check storage.backend matches your configured implementation.
How do I detect if the hybrid storage sync is stuck?
Poll /api/health/sync-status and examine status.in_progress. If this remains true for more than 30 minutes with non-zero pending_operations, the background sync worker in src/mcp_memory_service/storage/hybrid.py is likely blocked by network latency or authentication failures. Review logs for sync-related exceptions.
What does a low unique_tags count indicate?
When unique_tags is unexpectedly low compared to total_memories, the normalize_tags function in src/mcp_memory_service/services/memory_service.py (lines 55-75) may be incorrectly stripping tag delimiters or converting tags to empty strings. Compare the health payload against a direct query of storage.get_stats() to confirm the discrepancy.
Why is database_size_mb not increasing when I add memories?
Static database size during write operations indicates the SQLite file is not being modified. Verify file permissions on the database path and ensure the disk has free space (system.disk_free_gb). If permissions and space are adequate, check for transaction rollbacks or silent failures in storage.store() implementations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →