We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/doobidoo/mcp-memory-service'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
import pytest
import os
import sys
import tempfile
import shutil
import uuid
from typing import Callable, Optional, List
# Add src directory to Python path
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'src'))
# Disable semantic deduplication during tests to avoid interference with test expectations
# Tests often use similar content patterns (e.g., "Test memory 1", "Test memory 2")
# which would be caught by semantic dedup and cause unexpected failures
os.environ['MCP_SEMANTIC_DEDUP_ENABLED'] = 'false'
# CRITICAL: Force sqlite_vec backend for tests to prevent accidental Cloudflare operations
# This prevents tests from soft-deleting production memories in Cloudflare D1
#
# To explicitly test Cloudflare/Hybrid backends, set:
# MCP_TEST_ALLOW_CLOUD_BACKEND=true pytest tests/integration/test_cloudflare_*.py
#
_original_backend = os.environ.get('MCP_MEMORY_STORAGE_BACKEND')
_allow_cloud = os.environ.get('MCP_TEST_ALLOW_CLOUD_BACKEND', 'false').lower() == 'true'
if not _allow_cloud:
os.environ['MCP_MEMORY_STORAGE_BACKEND'] = 'sqlite_vec'
if _original_backend and _original_backend != 'sqlite_vec':
print(f"\n[Test Safety] β οΈ Overriding MCP_MEMORY_STORAGE_BACKEND from '{_original_backend}' to 'sqlite_vec'")
print(f"[Test Safety] This prevents tests from modifying production Cloudflare data.")
print(f"[Test Safety] To allow cloud backends: MCP_TEST_ALLOW_CLOUD_BACKEND=true pytest ...")
# CRITICAL: Force test database path to prevent production database access
# This ensures tests NEVER touch production databases even if they use the wrong fixtures
_test_db_dir = tempfile.mkdtemp(prefix='mcp-test-db-')
os.environ['MCP_MEMORY_SQLITE_PATH'] = os.path.join(_test_db_dir, 'test.db')
print(f"\n[Test Safety] π Test database path: {os.environ['MCP_MEMORY_SQLITE_PATH']}")
print(f"[Test Safety] Production databases are isolated and protected.")
# Reserved tag for test memories - enables automatic cleanup
TEST_MEMORY_TAG = "__test__"
@pytest.fixture
def temp_db_path():
'''Create a temporary directory for database testing.'''
temp_dir = tempfile.mkdtemp()
yield temp_dir
# Clean up after test
shutil.rmtree(temp_dir)
@pytest.fixture
def unique_content() -> Callable[[str], str]:
"""
Generate unique test content to avoid duplicate content errors.
Usage:
def test_example(unique_content):
content = unique_content("Test memory about authentication")
hash1 = store(content, tags=["test"])
Returns:
A function that takes a base string and returns a unique version.
"""
def _generator(base: str = "test") -> str:
return f"{base} [{uuid.uuid4()}]"
return _generator
@pytest.fixture
def test_store():
"""
Store function that auto-tags memories with TEST_MEMORY_TAG for cleanup.
All memories created with this fixture will be automatically deleted
at the end of the test session via pytest_sessionfinish hook.
Usage:
def test_example(test_store, unique_content):
hash1 = test_store(unique_content("Test memory"), tags=["auth"])
# Memory will have tags: ["__test__", "auth"]
"""
from mcp_memory_service.api import store
def _store(content: str, tags: Optional[List[str]] = None, **kwargs):
all_tags = [TEST_MEMORY_TAG] + (tags or [])
return store(content, tags=all_tags, **kwargs)
return _store
def pytest_sessionfinish(session, exitstatus):
"""
Cleanup all test memories at end of test session.
SAFETY: Uses TRIPLE verification to prevent production database deletion.
Only cleans test databases, never production.
"""
try:
from mcp_memory_service.config import SQLITE_VEC_PATH, STORAGE_BACKEND
import tempfile
# Get database path based on backend
if STORAGE_BACKEND == 'hybrid':
# Hybrid uses SQLite-vec as primary
db_path = str(SQLITE_VEC_PATH) if SQLITE_VEC_PATH else None
elif STORAGE_BACKEND == 'sqlite_vec':
db_path = str(SQLITE_VEC_PATH) if SQLITE_VEC_PATH else None
else:
# Cloudflare or other backends - skip cleanup (no local DB)
print(f"\n[Test Cleanup] βΉοΈ Backend '{STORAGE_BACKEND}' has no local database to clean")
return
if not db_path:
print(f"\n[Test Cleanup] β οΈ No database path configured, skipping cleanup")
return
# === TRIPLE SAFETY CHECK SYSTEM ===
# SAFETY CHECK 1: Must be in temp directory
temp_prefix = tempfile.gettempdir()
if not db_path.startswith(temp_prefix):
print(f"\n[Test Cleanup] π SAFETY ABORT: Database not in temp directory!")
print(f"[Test Cleanup] Database path: {db_path}")
print(f"[Test Cleanup] Expected prefix: {temp_prefix}")
print(f"[Test Cleanup] This indicates a configuration error - tests must use isolated databases.")
return
# SAFETY CHECK 2: Must NOT contain production indicators
production_indicators = [
"Library/Application Support/mcp-memory",
".mcp-memory",
"mcp-memory-service/data",
"/Users/", # Any user home directory
"/home/", # Linux home directories
"C:\\Users\\", # Windows user directories
]
for indicator in production_indicators:
if indicator in db_path:
print(f"\n[Test Cleanup] π SAFETY ABORT: Production path indicator detected!")
print(f"[Test Cleanup] Database path: {db_path}")
print(f"[Test Cleanup] Detected indicator: '{indicator}'")
print(f"[Test Cleanup] Tests MUST use temp_db_path fixture for isolation.")
return
# SAFETY CHECK 3: Must contain test-specific markers
test_markers = [
'mcp-test-', # Our custom test prefix
'pytest-', # pytest temp directories
'/tmp/', # Unix temp
'/var/tmp/', # Unix alternative temp
'Temp\\', # Windows temp
]
has_test_marker = any(marker in db_path for marker in test_markers)
if not has_test_marker:
print(f"\n[Test Cleanup] π SAFETY ABORT: No test marker found in database path!")
print(f"[Test Cleanup] Database path: {db_path}")
print(f"[Test Cleanup] Expected one of: {test_markers}")
return
# === ALL SAFETY CHECKS PASSED ===
print(f"\n[Test Cleanup] β
Safety checks passed")
print(f"[Test Cleanup] Database path: {db_path}")
print(f"[Test Cleanup] Cleaning test database...")
# Import delete function
from mcp_memory_service.api import delete_by_tag
# Perform cleanup - DO NOT use allow_production flag
# The delete_by_tag function has its own safety checks
# If our checks above passed, the delete_by_tag checks should also pass
result = delete_by_tag([TEST_MEMORY_TAG], allow_production=False)
deleted = result.get('deleted', 0) if isinstance(result, dict) else 0
if deleted > 0:
print(f"[Test Cleanup] β
Deleted {deleted} test memories tagged with '{TEST_MEMORY_TAG}'")
else:
print(f"[Test Cleanup] β
No test memories to clean")
except ValueError as e:
# Safety check from delete_by_tag - this is GOOD, it means safety worked!
if "production database" in str(e).lower():
print(f"\n[Test Cleanup] β
Safety check prevented production deletion!")
print(f"[Test Cleanup] Error: {e}")
print(f"[Test Cleanup] This is the safety system working correctly.")
else:
print(f"\n[Test Cleanup] β Unexpected ValueError: {e}")
except Exception as e:
# Make errors VISIBLE instead of silent
print(f"\n[Test Cleanup] β ERROR during cleanup: {e}")
print(f"[Test Cleanup] This may indicate a configuration problem.")
# Still don't fail the test session
def pytest_sessionstart(session):
"""
Verify test isolation before running any tests.
This hook runs BEFORE any tests execute to ensure proper configuration.
"""
print("\n" + "="*80)
print("π TEST ISOLATION VERIFICATION")
print("="*80)
try:
from mcp_memory_service.config import SQLITE_VEC_PATH, STORAGE_BACKEND
import tempfile
# Check backend
if STORAGE_BACKEND not in ['sqlite_vec', 'cloudflare']:
if not _allow_cloud:
print(f"β οΈ WARNING: Backend '{STORAGE_BACKEND}' may access production!")
print(f"β οΈ Tests should use 'sqlite_vec' backend for isolation.")
print(f"β οΈ Set MCP_TEST_ALLOW_CLOUD_BACKEND=true to explicitly allow this.")
# Check database path
if SQLITE_VEC_PATH:
db_path = str(SQLITE_VEC_PATH)
temp_prefix = tempfile.gettempdir()
# Verify it's in temp directory
if db_path.startswith(temp_prefix):
print(f"β
Database in temp directory: {db_path}")
else:
print(f"β CRITICAL: Database NOT in temp directory!")
print(f" Path: {db_path}")
print(f" Expected prefix: {temp_prefix}")
print(f" Tests may affect production data!")
# Check for production indicators
production_indicators = [
"Library/Application Support/mcp-memory",
".mcp-memory",
"mcp-memory-service/data"
]
for indicator in production_indicators:
if indicator in db_path:
print(f" π PRODUCTION PATH DETECTED: '{indicator}'")
print(f" π ABORTING TEST RUN FOR SAFETY")
pytest.exit("Test configuration would affect production database", returncode=1)
print(f"β
Storage backend: {STORAGE_BACKEND}")
print(f"β
Cloud backends: {'ALLOWED' if _allow_cloud else 'BLOCKED'}")
print("="*80 + "\n")
except Exception as e:
print(f"β Error during isolation verification: {e}")
print("="*80 + "\n")
# Cleanup temp test database directory at session end
def pytest_unconfigure(config):
"""Clean up global test database directory."""
try:
if os.path.exists(_test_db_dir):
shutil.rmtree(_test_db_dir, ignore_errors=True)
print(f"\n[Test Cleanup] ποΈ Removed test database directory: {_test_db_dir}")
except Exception as e:
print(f"\n[Test Cleanup] β οΈ Failed to remove test database directory: {e}")