This is page 3 of 46. Use http://codebase.md/doobidoo/mcp-memory-service?lines=false&page={x} to view the full context.
# Directory Structure
```
├── .claude
│ ├── agents
│ │ ├── amp-bridge.md
│ │ ├── amp-pr-automator.md
│ │ ├── code-quality-guard.md
│ │ ├── gemini-pr-automator.md
│ │ └── github-release-manager.md
│ ├── commands
│ │ ├── README.md
│ │ ├── refactor-function
│ │ ├── refactor-function-prod
│ │ └── refactor-function.md
│ ├── consolidation-fix-handoff.md
│ ├── consolidation-hang-fix-summary.md
│ ├── directives
│ │ ├── agents.md
│ │ ├── code-quality-workflow.md
│ │ ├── consolidation-details.md
│ │ ├── development-setup.md
│ │ ├── hooks-configuration.md
│ │ ├── memory-first.md
│ │ ├── memory-tagging.md
│ │ ├── pr-workflow.md
│ │ ├── quality-system-details.md
│ │ ├── README.md
│ │ ├── refactoring-checklist.md
│ │ ├── storage-backends.md
│ │ └── version-management.md
│ ├── prompts
│ │ └── hybrid-cleanup-integration.md
│ ├── settings.local.json.backup
│ └── settings.local.json.local
├── .commit-message
├── .coveragerc
├── .dockerignore
├── .env.example
├── .env.sqlite.backup
├── .envnn#
├── .gitattributes
├── .github
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ ├── feature_request.yml
│ │ └── performance_issue.yml
│ ├── pull_request_template.md
│ └── workflows
│ ├── bridge-tests.yml
│ ├── CACHE_FIX.md
│ ├── claude-branch-automation.yml
│ ├── claude-code-review.yml
│ ├── claude.yml
│ ├── cleanup-images.yml.disabled
│ ├── dev-setup-validation.yml
│ ├── docker-publish.yml
│ ├── dockerfile-lint.yml
│ ├── LATEST_FIXES.md
│ ├── main-optimized.yml.disabled
│ ├── main.yml
│ ├── publish-and-test.yml
│ ├── publish-dual.yml
│ ├── README_OPTIMIZATION.md
│ ├── release-tag.yml.disabled
│ ├── release.yml
│ ├── roadmap-review-reminder.yml
│ ├── SECRET_CONDITIONAL_FIX.md
│ └── WORKFLOW_FIXES.md
├── .gitignore
├── .mcp.json.backup
├── .mcp.json.template
├── .metrics
│ ├── baseline_cc_install_hooks.txt
│ ├── baseline_mi_install_hooks.txt
│ ├── baseline_nesting_install_hooks.txt
│ ├── BASELINE_REPORT.md
│ ├── COMPLEXITY_COMPARISON.txt
│ ├── QUICK_REFERENCE.txt
│ ├── README.md
│ ├── REFACTORED_BASELINE.md
│ ├── REFACTORING_COMPLETION_REPORT.md
│ └── TRACKING_TABLE.md
├── .pyscn
│ ├── .gitignore
│ └── reports
│ └── analyze_20251123_214224.html
├── AGENTS.md
├── ai-optimized-tool-descriptions.py
├── archive
│ ├── deployment
│ │ ├── deploy_fastmcp_fixed.sh
│ │ ├── deploy_http_with_mcp.sh
│ │ └── deploy_mcp_v4.sh
│ ├── deployment-configs
│ │ ├── empty_config.yml
│ │ └── smithery.yaml
│ ├── development
│ │ └── test_fastmcp.py
│ ├── docs-removed-2025-08-23
│ │ ├── authentication.md
│ │ ├── claude_integration.md
│ │ ├── claude-code-compatibility.md
│ │ ├── claude-code-integration.md
│ │ ├── claude-code-quickstart.md
│ │ ├── claude-desktop-setup.md
│ │ ├── complete-setup-guide.md
│ │ ├── database-synchronization.md
│ │ ├── development
│ │ │ ├── autonomous-memory-consolidation.md
│ │ │ ├── CLEANUP_PLAN.md
│ │ │ ├── CLEANUP_README.md
│ │ │ ├── CLEANUP_SUMMARY.md
│ │ │ ├── dream-inspired-memory-consolidation.md
│ │ │ ├── hybrid-slm-memory-consolidation.md
│ │ │ ├── mcp-milestone.md
│ │ │ ├── multi-client-architecture.md
│ │ │ ├── test-results.md
│ │ │ └── TIMESTAMP_FIX_SUMMARY.md
│ │ ├── distributed-sync.md
│ │ ├── invocation_guide.md
│ │ ├── macos-intel.md
│ │ ├── master-guide.md
│ │ ├── mcp-client-configuration.md
│ │ ├── multi-client-server.md
│ │ ├── service-installation.md
│ │ ├── sessions
│ │ │ └── MCP_ENHANCEMENT_SESSION_MEMORY_v4.1.0.md
│ │ ├── UBUNTU_SETUP.md
│ │ ├── ubuntu.md
│ │ ├── windows-setup.md
│ │ └── windows.md
│ ├── docs-root-cleanup-2025-08-23
│ │ ├── AWESOME_LIST_SUBMISSION.md
│ │ ├── CLOUDFLARE_IMPLEMENTATION.md
│ │ ├── DOCUMENTATION_ANALYSIS.md
│ │ ├── DOCUMENTATION_CLEANUP_PLAN.md
│ │ ├── DOCUMENTATION_CONSOLIDATION_COMPLETE.md
│ │ ├── LITESTREAM_SETUP_GUIDE.md
│ │ ├── lm_studio_system_prompt.md
│ │ ├── PYTORCH_DOWNLOAD_FIX.md
│ │ └── README-ORIGINAL-BACKUP.md
│ ├── investigations
│ │ └── MACOS_HOOKS_INVESTIGATION.md
│ ├── litestream-configs-v6.3.0
│ │ ├── install_service.sh
│ │ ├── litestream_master_config_fixed.yml
│ │ ├── litestream_master_config.yml
│ │ ├── litestream_replica_config_fixed.yml
│ │ ├── litestream_replica_config.yml
│ │ ├── litestream_replica_simple.yml
│ │ ├── litestream-http.service
│ │ ├── litestream.service
│ │ └── requirements-cloudflare.txt
│ ├── release-notes
│ │ └── release-notes-v7.1.4.md
│ └── setup-development
│ ├── README.md
│ ├── setup_consolidation_mdns.sh
│ ├── STARTUP_SETUP_GUIDE.md
│ └── test_service.sh
├── CHANGELOG-HISTORIC.md
├── CHANGELOG.md
├── claude_commands
│ ├── memory-context.md
│ ├── memory-health.md
│ ├── memory-ingest-dir.md
│ ├── memory-ingest.md
│ ├── memory-recall.md
│ ├── memory-search.md
│ ├── memory-store.md
│ ├── README.md
│ └── session-start.md
├── claude-hooks
│ ├── config.json
│ ├── config.template.json
│ ├── CONFIGURATION.md
│ ├── core
│ │ ├── auto-capture-hook.js
│ │ ├── auto-capture-hook.ps1
│ │ ├── memory-retrieval.js
│ │ ├── mid-conversation.js
│ │ ├── permission-request.js
│ │ ├── session-end.js
│ │ ├── session-start.js
│ │ └── topic-change.js
│ ├── debug-pattern-test.js
│ ├── install_claude_hooks_windows.ps1
│ ├── install_hooks.py
│ ├── memory-mode-controller.js
│ ├── MIGRATION.md
│ ├── README-AUTO-CAPTURE.md
│ ├── README-NATURAL-TRIGGERS.md
│ ├── README-PERMISSION-REQUEST.md
│ ├── README-phase2.md
│ ├── README.md
│ ├── simple-test.js
│ ├── statusline.sh
│ ├── test-adaptive-weights.js
│ ├── test-dual-protocol-hook.js
│ ├── test-mcp-hook.js
│ ├── test-natural-triggers.js
│ ├── test-recency-scoring.js
│ ├── tests
│ │ ├── integration-test.js
│ │ ├── phase2-integration-test.js
│ │ ├── test-code-execution.js
│ │ ├── test-cross-session.json
│ │ ├── test-permission-request.js
│ │ ├── test-session-tracking.json
│ │ └── test-threading.json
│ ├── utilities
│ │ ├── adaptive-pattern-detector.js
│ │ ├── auto-capture-patterns.js
│ │ ├── context-formatter.js
│ │ ├── context-shift-detector.js
│ │ ├── conversation-analyzer.js
│ │ ├── dynamic-context-updater.js
│ │ ├── git-analyzer.js
│ │ ├── mcp-client.js
│ │ ├── memory-client.js
│ │ ├── memory-scorer.js
│ │ ├── performance-manager.js
│ │ ├── project-detector.js
│ │ ├── session-cache.json
│ │ ├── session-tracker.js
│ │ ├── tiered-conversation-monitor.js
│ │ ├── user-override-detector.js
│ │ └── version-checker.js
│ └── WINDOWS-SESSIONSTART-BUG.md
├── CLAUDE.md
├── CODE_OF_CONDUCT.md
├── COMMIT_MESSAGE.md
├── CONTRIBUTING.md
├── Development-Sprint-November-2025.md
├── docs
│ ├── amp-cli-bridge.md
│ ├── api
│ │ ├── code-execution-interface.md
│ │ ├── memory-metadata-api.md
│ │ ├── PHASE1_IMPLEMENTATION_SUMMARY.md
│ │ ├── PHASE2_IMPLEMENTATION_SUMMARY.md
│ │ ├── PHASE2_REPORT.md
│ │ └── tag-standardization.md
│ ├── architecture
│ │ ├── graph-database-design.md
│ │ ├── search-enhancement-spec.md
│ │ └── search-examples.md
│ ├── architecture.md
│ ├── archive
│ │ └── obsolete-workflows
│ │ ├── load_memory_context.md
│ │ └── README.md
│ ├── assets
│ │ └── images
│ │ ├── dashboard-v3.3.0-preview.png
│ │ ├── memory-awareness-hooks-example.png
│ │ ├── project-infographic.svg
│ │ └── README.md
│ ├── CLAUDE_CODE_QUICK_REFERENCE.md
│ ├── cloudflare-setup.md
│ ├── demo-recording-script.md
│ ├── deployment
│ │ ├── docker.md
│ │ ├── dual-service.md
│ │ ├── production-guide.md
│ │ └── systemd-service.md
│ ├── development
│ │ ├── ai-agent-instructions.md
│ │ ├── code-quality
│ │ │ ├── phase-2a-completion.md
│ │ │ ├── phase-2a-handle-get-prompt.md
│ │ │ ├── phase-2a-index.md
│ │ │ ├── phase-2a-install-package.md
│ │ │ └── phase-2b-session-summary.md
│ │ ├── code-quality-workflow.md
│ │ ├── dashboard-workflow.md
│ │ ├── issue-management.md
│ │ ├── pr-280-post-mortem.md
│ │ ├── pr-review-guide.md
│ │ ├── refactoring-notes.md
│ │ ├── release-checklist.md
│ │ └── todo-tracker.md
│ ├── docker-optimized-build.md
│ ├── document-ingestion.md
│ ├── DOCUMENTATION_AUDIT.md
│ ├── enhancement-roadmap-issue-14.md
│ ├── examples
│ │ ├── analysis-scripts.js
│ │ ├── maintenance-session-example.md
│ │ ├── memory-distribution-chart.jsx
│ │ ├── quality-system-configs.md
│ │ └── tag-schema.json
│ ├── features
│ │ └── association-quality-boost.md
│ ├── first-time-setup.md
│ ├── glama-deployment.md
│ ├── guides
│ │ ├── advanced-command-examples.md
│ │ ├── chromadb-migration.md
│ │ ├── commands-vs-mcp-server.md
│ │ ├── mcp-enhancements.md
│ │ ├── mdns-service-discovery.md
│ │ ├── memory-consolidation-guide.md
│ │ ├── memory-quality-guide.md
│ │ ├── migration.md
│ │ ├── scripts.md
│ │ └── STORAGE_BACKENDS.md
│ ├── HOOK_IMPROVEMENTS.md
│ ├── hooks
│ │ └── phase2-code-execution-migration.md
│ ├── http-server-management.md
│ ├── ide-compatability.md
│ ├── IMAGE_RETENTION_POLICY.md
│ ├── images
│ │ ├── dashboard-placeholder.md
│ │ └── update-restart-demo.png
│ ├── implementation
│ │ ├── health_checks.md
│ │ └── performance.md
│ ├── IMPLEMENTATION_PLAN_HTTP_SSE.md
│ ├── integration
│ │ ├── homebrew.md
│ │ └── multi-client.md
│ ├── integrations
│ │ ├── gemini.md
│ │ ├── groq-bridge.md
│ │ ├── groq-integration-summary.md
│ │ └── groq-model-comparison.md
│ ├── integrations.md
│ ├── legacy
│ │ └── dual-protocol-hooks.md
│ ├── LIGHTWEIGHT_ONNX_SETUP.md
│ ├── LM_STUDIO_COMPATIBILITY.md
│ ├── maintenance
│ │ └── memory-maintenance.md
│ ├── mastery
│ │ ├── api-reference.md
│ │ ├── architecture-overview.md
│ │ ├── configuration-guide.md
│ │ ├── local-setup-and-run.md
│ │ ├── testing-guide.md
│ │ └── troubleshooting.md
│ ├── migration
│ │ ├── code-execution-api-quick-start.md
│ │ └── graph-migration-guide.md
│ ├── natural-memory-triggers
│ │ ├── cli-reference.md
│ │ ├── installation-guide.md
│ │ └── performance-optimization.md
│ ├── oauth-setup.md
│ ├── pr-graphql-integration.md
│ ├── quality-system-ui-implementation.md
│ ├── quick-setup-cloudflare-dual-environment.md
│ ├── README.md
│ ├── refactoring
│ │ └── phase-3-3-analysis.md
│ ├── releases
│ │ └── v8.72.0-testing.md
│ ├── remote-configuration-wiki-section.md
│ ├── research
│ │ ├── code-execution-interface-implementation.md
│ │ └── code-execution-interface-summary.md
│ ├── ROADMAP.md
│ ├── sqlite-vec-backend.md
│ ├── statistics
│ │ ├── charts
│ │ │ ├── activity_patterns.png
│ │ │ ├── contributors.png
│ │ │ ├── growth_trajectory.png
│ │ │ ├── monthly_activity.png
│ │ │ └── october_sprint.png
│ │ ├── data
│ │ │ ├── activity_by_day.csv
│ │ │ ├── activity_by_hour.csv
│ │ │ ├── contributors.csv
│ │ │ └── monthly_activity.csv
│ │ ├── generate_charts.py
│ │ └── REPOSITORY_STATISTICS.md
│ ├── technical
│ │ ├── development.md
│ │ ├── memory-migration.md
│ │ ├── migration-log.md
│ │ ├── sqlite-vec-embedding-fixes.md
│ │ └── tag-storage.md
│ ├── testing
│ │ └── regression-tests.md
│ ├── testing-cloudflare-backend.md
│ ├── troubleshooting
│ │ ├── cloudflare-api-token-setup.md
│ │ ├── cloudflare-authentication.md
│ │ ├── database-transfer-migration.md
│ │ ├── general.md
│ │ ├── hooks-quick-reference.md
│ │ ├── memory-management.md
│ │ ├── pr162-schema-caching-issue.md
│ │ ├── session-end-hooks.md
│ │ └── sync-issues.md
│ ├── tutorials
│ │ ├── advanced-techniques.md
│ │ ├── data-analysis.md
│ │ └── demo-session-walkthrough.md
│ ├── wiki-documentation-plan.md
│ └── wiki-Graph-Database-Architecture.md
├── examples
│ ├── claude_desktop_config_template.json
│ ├── claude_desktop_config_windows.json
│ ├── claude-desktop-http-config.json
│ ├── config
│ │ └── claude_desktop_config.json
│ ├── http-mcp-bridge.js
│ ├── memory_export_template.json
│ ├── README.md
│ ├── setup
│ │ └── setup_multi_client_complete.py
│ └── start_https_example.sh
├── IMPLEMENTATION_SUMMARY.md
├── install_service.py
├── install.py
├── LICENSE
├── NOTICE
├── PR_DESCRIPTION.md
├── pyproject-lite.toml
├── pyproject.toml
├── pytest.ini
├── README.md
├── release-notes-v8.61.0.md
├── run_server.py
├── scripts
│ ├── .claude
│ │ └── settings.local.json
│ ├── archive
│ │ └── check_missing_timestamps.py
│ ├── backup
│ │ ├── backup_memories.py
│ │ ├── backup_sqlite_vec.sh
│ │ ├── export_distributable_memories.sh
│ │ └── restore_memories.py
│ ├── benchmarks
│ │ ├── benchmark_code_execution_api.py
│ │ ├── benchmark_hybrid_sync.py
│ │ └── benchmark_server_caching.py
│ ├── ci
│ │ ├── check_dockerfile_args.sh
│ │ └── validate_imports.sh
│ ├── database
│ │ ├── analyze_sqlite_vec_db.py
│ │ ├── check_sqlite_vec_status.py
│ │ ├── db_health_check.py
│ │ └── simple_timestamp_check.py
│ ├── development
│ │ ├── debug_server_initialization.py
│ │ ├── find_orphaned_files.py
│ │ ├── fix_mdns.sh
│ │ ├── fix_sitecustomize.py
│ │ ├── remote_ingest.sh
│ │ ├── setup-git-merge-drivers.sh
│ │ ├── uv-lock-merge.sh
│ │ └── verify_hybrid_sync.py
│ ├── hooks
│ │ └── pre-commit
│ ├── installation
│ │ ├── install_linux_service.py
│ │ ├── install_macos_service.py
│ │ ├── install_uv.py
│ │ ├── install_windows_service.py
│ │ ├── install.py
│ │ ├── setup_backup_cron.sh
│ │ ├── setup_claude_mcp.sh
│ │ └── setup_cloudflare_resources.py
│ ├── linux
│ │ ├── service_status.sh
│ │ ├── start_service.sh
│ │ ├── stop_service.sh
│ │ ├── uninstall_service.sh
│ │ └── view_logs.sh
│ ├── maintenance
│ │ ├── add_project_tags.py
│ │ ├── apply_quality_boost_retroactively.py
│ │ ├── assign_memory_types.py
│ │ ├── auto_retag_memory_merge.py
│ │ ├── auto_retag_memory.py
│ │ ├── backfill_graph_table.py
│ │ ├── check_memory_types.py
│ │ ├── cleanup_association_memories_hybrid.py
│ │ ├── cleanup_association_memories.py
│ │ ├── cleanup_corrupted_encoding.py
│ │ ├── cleanup_low_quality.py
│ │ ├── cleanup_memories.py
│ │ ├── cleanup_organize.py
│ │ ├── consolidate_memory_types.py
│ │ ├── consolidation_mappings.json
│ │ ├── delete_orphaned_vectors_fixed.py
│ │ ├── delete_test_memories.py
│ │ ├── fast_cleanup_duplicates_with_tracking.sh
│ │ ├── find_all_duplicates.py
│ │ ├── find_cloudflare_duplicates.py
│ │ ├── find_duplicates.py
│ │ ├── memory-types.md
│ │ ├── README.md
│ │ ├── recover_timestamps_from_cloudflare.py
│ │ ├── regenerate_embeddings.py
│ │ ├── repair_malformed_tags.py
│ │ ├── repair_memories.py
│ │ ├── repair_sqlite_vec_embeddings.py
│ │ ├── repair_zero_embeddings.py
│ │ ├── restore_from_json_export.py
│ │ ├── retag_valuable_memories.py
│ │ ├── scan_todos.sh
│ │ ├── soft_delete_test_memories.py
│ │ └── sync_status.py
│ ├── migration
│ │ ├── cleanup_mcp_timestamps.py
│ │ ├── legacy
│ │ │ └── migrate_chroma_to_sqlite.py
│ │ ├── mcp-migration.py
│ │ ├── migrate_sqlite_vec_embeddings.py
│ │ ├── migrate_storage.py
│ │ ├── migrate_tags.py
│ │ ├── migrate_timestamps.py
│ │ ├── migrate_to_cloudflare.py
│ │ ├── migrate_to_sqlite_vec.py
│ │ ├── migrate_v5_enhanced.py
│ │ ├── TIMESTAMP_CLEANUP_README.md
│ │ └── verify_mcp_timestamps.py
│ ├── pr
│ │ ├── amp_collect_results.sh
│ │ ├── amp_detect_breaking_changes.sh
│ │ ├── amp_generate_tests.sh
│ │ ├── amp_pr_review.sh
│ │ ├── amp_quality_gate.sh
│ │ ├── amp_suggest_fixes.sh
│ │ ├── auto_review.sh
│ │ ├── detect_breaking_changes.sh
│ │ ├── generate_tests.sh
│ │ ├── lib
│ │ │ └── graphql_helpers.sh
│ │ ├── pre_pr_check.sh
│ │ ├── quality_gate.sh
│ │ ├── resolve_threads.sh
│ │ ├── run_pyscn_analysis.sh
│ │ ├── run_quality_checks_on_files.sh
│ │ ├── run_quality_checks.sh
│ │ ├── thread_status.sh
│ │ └── watch_reviews.sh
│ ├── quality
│ │ ├── bulk_evaluate_onnx.py
│ │ ├── check_test_scores.py
│ │ ├── debug_deberta_scoring.py
│ │ ├── export_deberta_onnx.py
│ │ ├── fix_dead_code_install.sh
│ │ ├── migrate_to_deberta.py
│ │ ├── phase1_dead_code_analysis.md
│ │ ├── phase2_complexity_analysis.md
│ │ ├── README_PHASE1.md
│ │ ├── README_PHASE2.md
│ │ ├── rescore_deberta.py
│ │ ├── rescore_fallback.py
│ │ ├── reset_onnx_scores.py
│ │ ├── track_pyscn_metrics.sh
│ │ └── weekly_quality_review.sh
│ ├── README.md
│ ├── run
│ │ ├── memory_wrapper_cleanup.ps1
│ │ ├── memory_wrapper_cleanup.py
│ │ ├── memory_wrapper_cleanup.sh
│ │ ├── README_CLEANUP_WRAPPER.md
│ │ ├── run_mcp_memory.sh
│ │ ├── run-with-uv.sh
│ │ └── start_sqlite_vec.sh
│ ├── run_memory_server.py
│ ├── server
│ │ ├── check_http_server.py
│ │ ├── check_server_health.py
│ │ ├── memory_offline.py
│ │ ├── preload_models.py
│ │ ├── run_http_server.py
│ │ ├── run_memory_server.py
│ │ ├── start_http_server.bat
│ │ └── start_http_server.sh
│ ├── service
│ │ ├── deploy_dual_services.sh
│ │ ├── http_server_manager.sh
│ │ ├── install_http_service.sh
│ │ ├── mcp-memory-http.service
│ │ ├── mcp-memory.service
│ │ ├── memory_service_manager.sh
│ │ ├── service_control.sh
│ │ ├── service_utils.py
│ │ ├── update_service.sh
│ │ └── windows
│ │ ├── add_watchdog_trigger.ps1
│ │ ├── install_scheduled_task.ps1
│ │ ├── manage_service.ps1
│ │ ├── run_http_server_background.ps1
│ │ ├── uninstall_scheduled_task.ps1
│ │ └── update_and_restart.ps1
│ ├── setup-lightweight.sh
│ ├── sync
│ │ ├── check_drift.py
│ │ ├── claude_sync_commands.py
│ │ ├── export_memories.py
│ │ ├── import_memories.py
│ │ ├── litestream
│ │ │ ├── apply_local_changes.sh
│ │ │ ├── enhanced_memory_store.sh
│ │ │ ├── init_staging_db.sh
│ │ │ ├── io.litestream.replication.plist
│ │ │ ├── manual_sync.sh
│ │ │ ├── memory_sync.sh
│ │ │ ├── pull_remote_changes.sh
│ │ │ ├── push_to_remote.sh
│ │ │ ├── README.md
│ │ │ ├── resolve_conflicts.sh
│ │ │ ├── setup_local_litestream.sh
│ │ │ ├── setup_remote_litestream.sh
│ │ │ ├── staging_db_init.sql
│ │ │ ├── stash_local_changes.sh
│ │ │ ├── sync_from_remote_noconfig.sh
│ │ │ └── sync_from_remote.sh
│ │ ├── README.md
│ │ ├── safe_cloudflare_update.sh
│ │ ├── sync_memory_backends.py
│ │ └── sync_now.py
│ ├── testing
│ │ ├── run_complete_test.py
│ │ ├── run_memory_test.sh
│ │ ├── simple_test.py
│ │ ├── test_cleanup_logic.py
│ │ ├── test_cloudflare_backend.py
│ │ ├── test_docker_functionality.py
│ │ ├── test_installation.py
│ │ ├── test_mdns.py
│ │ ├── test_memory_api.py
│ │ ├── test_memory_simple.py
│ │ ├── test_migration.py
│ │ ├── test_search_api.py
│ │ ├── test_sqlite_vec_embeddings.py
│ │ ├── test_sse_events.py
│ │ ├── test-connection.py
│ │ └── test-hook.js
│ ├── update_and_restart.sh
│ ├── utils
│ │ ├── claude_commands_utils.py
│ │ ├── detect_platform.py
│ │ ├── generate_personalized_claude_md.sh
│ │ ├── groq
│ │ ├── groq_agent_bridge.py
│ │ ├── list-collections.py
│ │ ├── memory_wrapper_uv.py
│ │ ├── query_memories.py
│ │ ├── README_detect_platform.md
│ │ ├── smithery_wrapper.py
│ │ ├── test_groq_bridge.sh
│ │ └── uv_wrapper.py
│ └── validation
│ ├── check_dev_setup.py
│ ├── check_documentation_links.py
│ ├── check_handler_coverage.py
│ ├── diagnose_backend_config.py
│ ├── validate_configuration_complete.py
│ ├── validate_graph_tools.py
│ ├── validate_memories.py
│ ├── validate_migration.py
│ ├── validate_timestamp_integrity.py
│ ├── verify_environment.py
│ ├── verify_pytorch_windows.py
│ └── verify_torch.py
├── SECURITY.md
├── selective_timestamp_recovery.py
├── SPONSORS.md
├── src
│ └── mcp_memory_service
│ ├── __init__.py
│ ├── _version.py
│ ├── api
│ │ ├── __init__.py
│ │ ├── client.py
│ │ ├── operations.py
│ │ ├── sync_wrapper.py
│ │ └── types.py
│ ├── backup
│ │ ├── __init__.py
│ │ └── scheduler.py
│ ├── cli
│ │ ├── __init__.py
│ │ ├── ingestion.py
│ │ ├── main.py
│ │ └── utils.py
│ ├── config.py
│ ├── consolidation
│ │ ├── __init__.py
│ │ ├── associations.py
│ │ ├── base.py
│ │ ├── clustering.py
│ │ ├── compression.py
│ │ ├── consolidator.py
│ │ ├── decay.py
│ │ ├── forgetting.py
│ │ ├── health.py
│ │ └── scheduler.py
│ ├── dependency_check.py
│ ├── discovery
│ │ ├── __init__.py
│ │ ├── client.py
│ │ └── mdns_service.py
│ ├── embeddings
│ │ ├── __init__.py
│ │ └── onnx_embeddings.py
│ ├── ingestion
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── chunker.py
│ │ ├── csv_loader.py
│ │ ├── json_loader.py
│ │ ├── pdf_loader.py
│ │ ├── registry.py
│ │ ├── semtools_loader.py
│ │ └── text_loader.py
│ ├── lm_studio_compat.py
│ ├── mcp_server.py
│ ├── models
│ │ ├── __init__.py
│ │ └── memory.py
│ ├── quality
│ │ ├── __init__.py
│ │ ├── ai_evaluator.py
│ │ ├── async_scorer.py
│ │ ├── config.py
│ │ ├── implicit_signals.py
│ │ ├── metadata_codec.py
│ │ ├── onnx_ranker.py
│ │ └── scorer.py
│ ├── server
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── cache_manager.py
│ │ ├── client_detection.py
│ │ ├── environment.py
│ │ ├── handlers
│ │ │ ├── __init__.py
│ │ │ ├── consolidation.py
│ │ │ ├── documents.py
│ │ │ ├── graph.py
│ │ │ ├── memory.py
│ │ │ ├── quality.py
│ │ │ └── utility.py
│ │ └── logging_config.py
│ ├── server_impl.py
│ ├── services
│ │ ├── __init__.py
│ │ └── memory_service.py
│ ├── storage
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── cloudflare.py
│ │ ├── factory.py
│ │ ├── graph.py
│ │ ├── http_client.py
│ │ ├── hybrid.py
│ │ ├── migrations
│ │ │ └── 008_add_graph_table.sql
│ │ └── sqlite_vec.py
│ ├── sync
│ │ ├── __init__.py
│ │ ├── exporter.py
│ │ ├── importer.py
│ │ └── litestream_config.py
│ ├── utils
│ │ ├── __init__.py
│ │ ├── cache_manager.py
│ │ ├── content_splitter.py
│ │ ├── db_utils.py
│ │ ├── debug.py
│ │ ├── directory_ingestion.py
│ │ ├── document_processing.py
│ │ ├── gpu_detection.py
│ │ ├── hashing.py
│ │ ├── health_check.py
│ │ ├── http_server_manager.py
│ │ ├── port_detection.py
│ │ ├── quality_analytics.py
│ │ ├── startup_orchestrator.py
│ │ ├── system_detection.py
│ │ └── time_parser.py
│ └── web
│ ├── __init__.py
│ ├── api
│ │ ├── __init__.py
│ │ ├── analytics.py
│ │ ├── backup.py
│ │ ├── consolidation.py
│ │ ├── documents.py
│ │ ├── events.py
│ │ ├── health.py
│ │ ├── manage.py
│ │ ├── mcp.py
│ │ ├── memories.py
│ │ ├── quality.py
│ │ ├── search.py
│ │ └── sync.py
│ ├── app.py
│ ├── dependencies.py
│ ├── oauth
│ │ ├── __init__.py
│ │ ├── authorization.py
│ │ ├── discovery.py
│ │ ├── middleware.py
│ │ ├── models.py
│ │ ├── registration.py
│ │ └── storage.py
│ ├── sse.py
│ └── static
│ ├── app.js
│ ├── i18n
│ │ ├── de.json
│ │ ├── en.json
│ │ ├── es.json
│ │ ├── fr.json
│ │ ├── ja.json
│ │ ├── ko.json
│ │ └── zh.json
│ ├── index.html
│ ├── README.md
│ ├── sse_test.html
│ └── style.css
├── start_http_debug.bat
├── start_http_server.sh
├── test_document.txt
├── test_version_checker.js
├── TESTING_NOTES.md
├── tests
│ ├── __init__.py
│ ├── api
│ │ ├── __init__.py
│ │ ├── test_compact_types.py
│ │ └── test_operations.py
│ ├── bridge
│ │ ├── mock_responses.js
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ └── test_http_mcp_bridge.js
│ ├── conftest.py
│ ├── consolidation
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_associations.py
│ │ ├── test_clustering.py
│ │ ├── test_compression.py
│ │ ├── test_consolidator.py
│ │ ├── test_decay.py
│ │ ├── test_forgetting.py
│ │ └── test_graph_modes.py
│ ├── contracts
│ │ └── api-specification.yml
│ ├── integration
│ │ ├── conftest.py
│ │ ├── HANDLER_COVERAGE_REPORT.md
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── test_all_memory_handlers.py
│ │ ├── test_api_key_fallback.py
│ │ ├── test_api_memories_chronological.py
│ │ ├── test_api_tag_time_search.py
│ │ ├── test_api_with_memory_service.py
│ │ ├── test_bridge_integration.js
│ │ ├── test_cli_interfaces.py
│ │ ├── test_cloudflare_connection.py
│ │ ├── test_concurrent_clients.py
│ │ ├── test_data_serialization_consistency.py
│ │ ├── test_http_server_startup.py
│ │ ├── test_mcp_memory.py
│ │ ├── test_mdns_integration.py
│ │ ├── test_oauth_basic_auth.py
│ │ ├── test_oauth_flow.py
│ │ ├── test_server_handlers.py
│ │ └── test_store_memory.py
│ ├── performance
│ │ ├── test_background_sync.py
│ │ └── test_hybrid_live.py
│ ├── README.md
│ ├── smithery
│ │ └── test_smithery.py
│ ├── sqlite
│ │ └── simple_sqlite_vec_test.py
│ ├── storage
│ │ ├── conftest.py
│ │ └── test_graph_storage.py
│ ├── test_client.py
│ ├── test_content_splitting.py
│ ├── test_database.py
│ ├── test_deberta_quality.py
│ ├── test_fallback_quality.py
│ ├── test_graph_traversal.py
│ ├── test_hybrid_cloudflare_limits.py
│ ├── test_hybrid_storage.py
│ ├── test_lightweight_onnx.py
│ ├── test_memory_ops.py
│ ├── test_memory_wrapper_cleanup.py
│ ├── test_quality_integration.py
│ ├── test_quality_system.py
│ ├── test_semantic_search.py
│ ├── test_sqlite_vec_storage.py
│ ├── test_time_parser.py
│ ├── test_timestamp_preservation.py
│ ├── timestamp
│ │ ├── test_hook_vs_manual_storage.py
│ │ ├── test_issue99_final_validation.py
│ │ ├── test_search_retrieval_inconsistency.py
│ │ ├── test_timestamp_issue.py
│ │ └── test_timestamp_simple.py
│ └── unit
│ ├── conftest.py
│ ├── test_cloudflare_storage.py
│ ├── test_csv_loader.py
│ ├── test_fastapi_dependencies.py
│ ├── test_import.py
│ ├── test_imports.py
│ ├── test_json_loader.py
│ ├── test_mdns_simple.py
│ ├── test_mdns.py
│ ├── test_memory_service.py
│ ├── test_memory.py
│ ├── test_semtools_loader.py
│ ├── test_storage_interface_compatibility.py
│ ├── test_tag_time_filtering.py
│ └── test_uv_no_pip_installer_fallback.py
├── tools
│ ├── docker
│ │ ├── DEPRECATED.md
│ │ ├── docker-compose.http.yml
│ │ ├── docker-compose.pythonpath.yml
│ │ ├── docker-compose.standalone.yml
│ │ ├── docker-compose.uv.yml
│ │ ├── docker-compose.yml
│ │ ├── docker-entrypoint-persistent.sh
│ │ ├── docker-entrypoint-unified.sh
│ │ ├── docker-entrypoint.sh
│ │ ├── Dockerfile
│ │ ├── Dockerfile.glama
│ │ ├── Dockerfile.slim
│ │ ├── README.md
│ │ └── test-docker-modes.sh
│ └── README.md
├── uv.lock
└── verify_compression.sh
```
# Files
--------------------------------------------------------------------------------
/claude-hooks/test-mcp-hook.js:
--------------------------------------------------------------------------------
```javascript
#!/usr/bin/env node
/**
* Test MCP-based Memory Hook
* Tests the updated session-start hook with MCP protocol
*/
const { onSessionStart } = require('./core/session-start.js');
// Test configuration
const testContext = {
workingDirectory: process.cwd(),
sessionId: 'mcp-test-session',
trigger: 'session-start',
userMessage: 'test memory hook with cloudflare backend',
injectSystemMessage: async (message) => {
console.log('\n' + '='.repeat(60));
console.log('🧠 MCP MEMORY CONTEXT INJECTION TEST');
console.log('='.repeat(60));
console.log(message);
console.log('='.repeat(60) + '\n');
return true;
}
};
async function testMCPHook() {
console.log('🔧 Testing MCP Memory Hook...');
console.log(`📂 Working Directory: ${process.cwd()}`);
console.log(`🔧 Testing with Cloudflare backend configuration\n`);
try {
await testContext.onSessionStart(testContext);
console.log('✅ MCP Hook test completed successfully');
} catch (error) {
console.error('❌ MCP Hook test failed:', error.message);
// Don't show full stack trace in test mode
if (process.env.DEBUG) {
console.error(error.stack);
}
// Test completed - hook should fail gracefully
console.log('✅ Hook failed gracefully as expected when MCP server unavailable');
}
}
// Handle the onSessionStart function correctly
const sessionStartModule = require('./core/session-start.js');
if (sessionStartModule.handler) {
testContext.onSessionStart = sessionStartModule.handler;
} else if (typeof sessionStartModule === 'function') {
testContext.onSessionStart = sessionStartModule;
} else {
// Try direct export
testContext.onSessionStart = sessionStartModule.onSessionStart || sessionStartModule.default;
}
if (!testContext.onSessionStart) {
console.error('❌ Could not find onSessionStart handler');
process.exit(1);
}
// Run the test
testMCPHook();
```
--------------------------------------------------------------------------------
/scripts/installation/install_uv.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
# Copyright 2024 Heinrich Krupp
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Script to install UV package manager
"""
import os
import sys
import subprocess
import platform
def main():
print("Installing UV package manager...")
try:
# Install UV using pip
subprocess.check_call([
sys.executable, '-m', 'pip', 'install', 'uv'
])
print("UV installed successfully!")
print("You can now use UV for faster dependency management:")
print(" uv pip install -r requirements.txt")
# Create shortcut script
system = platform.system().lower()
if system == "windows":
# Create .bat file for Windows
with open("uv-run.bat", "w") as f:
f.write(f"@echo off\n")
f.write(f"python -m uv run memory %*\n")
print("Created uv-run.bat shortcut")
else:
# Create shell script for Unix-like systems
with open("uv-run.sh", "w") as f:
f.write("#!/bin/sh\n")
f.write("python -m uv run memory \"$@\"\n")
# Make it executable
try:
os.chmod("uv-run.sh", 0o755)
except:
pass
print("Created uv-run.sh shortcut")
except subprocess.SubprocessError as e:
print(f"Error installing UV: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
```
--------------------------------------------------------------------------------
/.claude/directives/memory-tagging.md:
--------------------------------------------------------------------------------
```markdown
# Memory Tagging Directive
## CRITICAL: Always Tag Memories with Project Name
When storing memories manually for this project, **ALWAYS** include `mcp-memory-service` as the **first tag**.
### Why This Matters
- Session-end hooks automatically add `projectContext.name` (line 222 in session-end.js)
- Manual storage has NO hook context - you must add the tag explicitly
- Without the tag, memories are excluded from:
- SessionStart hook project context retrieval
- Tag-based searches
- Git-aware context integration
- Cross-PC sync queries
### Correct Usage
```bash
# ✅ CORRECT - Always include project tag first
claude /memory-store "architecture decision..." \
--tags "mcp-memory-service,architecture,graph-database"
# ✅ CORRECT - MCP tool with project tag
store_memory(
content="configuration baseline...",
metadata={"tags": "mcp-memory-service,configuration,hybrid-backend"}
)
# ❌ WRONG - Missing project tag
claude /memory-store "bug fix..." --tags "bug-fix,troubleshooting"
```
### Tag Priority Order (v8.48.2+)
1. **Project identifier** - `mcp-memory-service` (REQUIRED)
2. **Content category** - `architecture`, `configuration`, `bug-fix`, `release`, etc.
3. **Specifics** - `graph-database`, `hybrid-backend`, `v8.51.0`, etc.
### Standard Categories
| Category | Use Case | Example |
|----------|----------|---------|
| `architecture` | Design decisions, system structure | `mcp-memory-service,architecture,graph-database` |
| `configuration` | Setup, environment, settings | `mcp-memory-service,configuration,multi-pc` |
| `performance` | Optimization, benchmarks | `mcp-memory-service,performance,30x-improvement` |
| `bug-fix` | Issue resolution | `mcp-memory-service,bug-fix,database-lock` |
| `release` | Version management | `mcp-memory-service,release,v8.51.0` |
| `documentation` | Guides, references | `mcp-memory-service,documentation,setup-guide` |
## Enforcement
This directive is **mandatory** for all manual memory storage operations in this project.
```
--------------------------------------------------------------------------------
/archive/litestream-configs-v6.3.0/install_service.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# Install MCP Memory Service as a systemd service
echo "Installing MCP Memory Service as a systemd service..."
# Check if running as regular user (not root)
if [ "$EUID" -eq 0 ]; then
echo "Error: Do not run this script as root. Run as your regular user."
exit 1
fi
# Get current user and working directory
CURRENT_USER=$(whoami)
CURRENT_DIR=$(pwd)
SERVICE_FILE="deployment/mcp-memory.service"
echo "User: $CURRENT_USER"
echo "Working directory: $CURRENT_DIR"
# Check if service file exists
if [ ! -f "$SERVICE_FILE" ]; then
echo "Error: Service file $SERVICE_FILE not found!"
exit 1
fi
# Generate a unique API key
API_KEY="mcp-$(openssl rand -hex 16)"
echo "Generated API key: $API_KEY"
# Update the service file with the actual API key
sed -i "s/Environment=MCP_API_KEY=.*/Environment=MCP_API_KEY=$API_KEY/" "$SERVICE_FILE"
# Copy service file to systemd directory
echo "Installing systemd service file..."
sudo cp "$SERVICE_FILE" /etc/systemd/system/
# Set proper permissions
sudo chmod 644 /etc/systemd/system/mcp-memory.service
# Reload systemd daemon
echo "Reloading systemd daemon..."
sudo systemctl daemon-reload
# Enable the service to start on boot
echo "Enabling service for startup..."
sudo systemctl enable mcp-memory.service
echo ""
echo "✅ MCP Memory Service installed successfully!"
echo ""
echo "Commands to manage the service:"
echo " Start: sudo systemctl start mcp-memory"
echo " Stop: sudo systemctl stop mcp-memory"
echo " Status: sudo systemctl status mcp-memory"
echo " Logs: sudo journalctl -u mcp-memory -f"
echo " Disable: sudo systemctl disable mcp-memory"
echo ""
echo "The service will now start automatically on system boot."
echo "API Key: $API_KEY"
echo ""
echo "Service will be available at:"
echo " Dashboard: https://localhost:8000"
echo " API Docs: https://localhost:8000/api/docs"
echo " Health: https://localhost:8000/api/health"
echo ""
echo "To start the service now, run:"
echo " sudo systemctl start mcp-memory"
```
--------------------------------------------------------------------------------
/scripts/run/memory_wrapper_cleanup.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# MCP Memory Service Wrapper with Orphan Cleanup
#
# Cleans up orphaned MCP memory processes before starting the server.
# Orphaned processes cause SQLite "database locked" errors.
#
# Usage in MCP config:
# {
# "memory": {
# "command": "/path/to/mcp-memory-service/scripts/run/memory_wrapper_cleanup.sh",
# "args": [],
# "env": { ... }
# }
# }
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
log() {
echo "[mcp-memory-wrapper] $1" >&2
}
# Find and kill orphaned MCP memory processes
cleanup_orphans() {
local count=0
for pid in $(pgrep -f "mcp-memory-service" 2>/dev/null || true); do
# Skip our own process tree
if [ "$pid" = "$$" ]; then
continue
fi
# Get parent PID
local ppid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ')
# ppid=1 means orphaned (parent is init/launchd)
if [ "$ppid" = "1" ]; then
log "Killing orphaned process: $pid"
kill -9 "$pid" 2>/dev/null || true
((count++)) || true
fi
done
if [ "$count" -gt 0 ]; then
log "Cleaned up $count orphaned process(es)"
else
log "No orphaned processes found"
fi
}
# Find uv executable
find_uv() {
if command -v uv &>/dev/null; then
echo "uv"
elif [ -x "$HOME/.local/bin/uv" ]; then
echo "$HOME/.local/bin/uv"
elif [ -x "$HOME/.cargo/bin/uv" ]; then
echo "$HOME/.cargo/bin/uv"
else
log "ERROR: uv not found. Install with: curl -LsSf https://astral.sh/uv/install.sh | sh"
exit 1
fi
}
main() {
log "Starting ($(uname -s) $(uname -r))"
# Step 1: Cleanup orphans
cleanup_orphans
# Step 2: Start server
cd "$PROJECT_DIR"
UV=$(find_uv)
log "Starting server with: $UV run memory"
# exec replaces this shell - clean signal handling, no subprocess
exec "$UV" run memory "$@"
}
main "$@"
```
--------------------------------------------------------------------------------
/scripts/utils/query_memories.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""Query memories from the SQLite database"""
import sqlite3
import json
import sys
def query_memories(tag_filter=None, query_text=None, limit=5):
"""Query memories from the database"""
conn = sqlite3.connect('/home/hkr/.local/share/mcp-memory/sqlite_vec.db')
cursor = conn.cursor()
if tag_filter:
sql = "SELECT content, tags FROM memories WHERE tags LIKE ? LIMIT ?"
cursor.execute(sql, (f'%{tag_filter}%', limit))
elif query_text:
sql = "SELECT content, tags FROM memories WHERE content LIKE ? LIMIT ?"
cursor.execute(sql, (f'%{query_text}%', limit))
else:
sql = "SELECT content, tags FROM memories ORDER BY created_at DESC LIMIT ?"
cursor.execute(sql, (limit,))
results = []
for row in cursor.fetchall():
content = row[0]
try:
tags = json.loads(row[1]) if row[1] else []
except (json.JSONDecodeError, TypeError):
# Tags might be stored differently
tags = row[1].split(',') if row[1] and isinstance(row[1], str) else []
results.append({
'content': content,
'tags': tags
})
conn.close()
return results
if __name__ == "__main__":
# Get memories with specific tags
print("=== Searching for README sections ===\n")
# Search for readme content
memories = query_memories(tag_filter="readme", limit=10)
for i, memory in enumerate(memories, 1):
print(f"Memory {i}:")
print(f"Content (first 500 chars):\n{memory['content'][:500]}")
print(f"Tags: {', '.join(memory['tags'])}")
print("-" * 80)
print()
# Search for specific content
print("\n=== Searching for Installation content ===\n")
memories = query_memories(query_text="installation", limit=5)
for i, memory in enumerate(memories, 1):
print(f"Memory {i}:")
print(f"Content (first 500 chars):\n{memory['content'][:500]}")
print(f"Tags: {', '.join(memory['tags'])}")
print("-" * 80)
print()
```
--------------------------------------------------------------------------------
/archive/deployment/deploy_http_with_mcp.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# Deploy HTTP Server with MCP endpoints (hybrid approach)
echo "🔄 Switching to HTTP server with MCP protocol support..."
# Create updated service file for hybrid approach
cat > /tmp/mcp-memory-hybrid.service << 'EOF'
[Unit]
Description=MCP Memory Service HTTP+MCP Hybrid v4.0.0-alpha.1
Documentation=https://github.com/doobidoo/mcp-memory-service
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=simple
User=hkr
Group=hkr
WorkingDirectory=/home/hkr/repositories/mcp-memory-service
Environment=PATH=/home/hkr/repositories/mcp-memory-service/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=PYTHONPATH=/home/hkr/repositories/mcp-memory-service/src
Environment=MCP_CONSOLIDATION_ENABLED=true
Environment=MCP_MDNS_ENABLED=true
Environment=MCP_HTTPS_ENABLED=false
Environment=MCP_MDNS_SERVICE_NAME="MCP Memory Service - Hybrid"
Environment=MCP_HTTP_ENABLED=true
Environment=MCP_HTTP_HOST=0.0.0.0
Environment=MCP_HTTP_PORT=8000
Environment=MCP_MEMORY_STORAGE_BACKEND=sqlite_vec
Environment=MCP_API_KEY=test-key-123
ExecStart=/home/hkr/repositories/mcp-memory-service/venv/bin/python /home/hkr/repositories/mcp-memory-service/scripts/run_http_server.py
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=mcp-memory-service
[Install]
WantedBy=multi-user.target
EOF
# Install the hybrid service configuration
echo "📝 Installing hybrid HTTP+MCP service configuration..."
sudo cp /tmp/mcp-memory-hybrid.service /etc/systemd/system/mcp-memory.service
# Reload and start
echo "🔄 Reloading systemd and starting hybrid service..."
sudo systemctl daemon-reload
sudo systemctl start mcp-memory
# Check status
echo "🔍 Checking service status..."
sudo systemctl status mcp-memory --no-pager
echo ""
echo "✅ HTTP server with MCP protocol support is now running!"
echo ""
echo "🌐 Available Services:"
echo " - HTTP API: http://localhost:8000/api/*"
echo " - Dashboard: http://localhost:8000/"
echo " - Health: http://localhost:8000/api/health"
echo ""
echo "🔧 Next: Add MCP protocol endpoints to the HTTP server"
```
--------------------------------------------------------------------------------
/scripts/ci/validate_imports.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# Copyright 2024 Heinrich Krupp
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -euo pipefail
# Validate that all handlers can be imported without errors
# Catches Issue #299 style bugs (ModuleNotFoundError, ImportError)
#
# Exit codes:
# 0 - All imports successful
# 1 - Import validation failed
echo "🔍 Validating handler imports..."
# Test all 17 memory handlers can be imported
python3 -c "
import sys
import traceback
try:
from mcp_memory_service.server.handlers.memory import (
handle_store_memory,
handle_retrieve_memory,
handle_retrieve_with_quality_boost,
handle_search_by_tag,
handle_delete_memory,
handle_delete_by_tag,
handle_delete_by_tags,
handle_delete_by_all_tags,
handle_cleanup_duplicates,
handle_update_memory_metadata,
handle_debug_retrieve,
handle_exact_match_retrieve,
handle_get_raw_embedding,
handle_recall_memory,
handle_recall_by_timeframe,
handle_delete_by_timeframe,
handle_delete_before_date,
)
print('✅ All 17 handler imports successful')
sys.exit(0)
except ImportError as e:
print(f'❌ Import validation failed: {e}', file=sys.stderr)
traceback.print_exc()
sys.exit(1)
except Exception as e:
print(f'❌ Unexpected error during import: {e}', file=sys.stderr)
traceback.print_exc()
sys.exit(1)
"
if [ $? -eq 0 ]; then
echo "✅ Handler import validation passed"
exit 0
else
echo "❌ Handler import validation failed" >&2
echo "💡 This catches bugs like Issue #299 (relative import errors)" >&2
exit 1
fi
```
--------------------------------------------------------------------------------
/tools/docker/docker-compose.http.yml:
--------------------------------------------------------------------------------
```yaml
version: '3.8'
# Docker Compose configuration for HTTP/API mode
# Usage: docker-compose -f docker-compose.http.yml up -d
services:
mcp-memory-service:
build:
context: ../..
dockerfile: tools/docker/Dockerfile
ports:
- "${HTTP_PORT:-8000}:8000" # Map to different port if needed
volumes:
# Single data directory for all storage
- ./data:/app/data
# Model cache (prevents re-downloading models on each restart)
# Uncomment the following line to persist Hugging Face models
# - ${HOME}/.cache/huggingface:/root/.cache/huggingface
# Optional: mount local config
# - ./config:/app/config:ro
environment:
# Mode selection
- MCP_MODE=http
# Storage configuration
- MCP_MEMORY_STORAGE_BACKEND=sqlite_vec
- MCP_MEMORY_SQLITE_PATH=/app/data/sqlite_vec.db
- MCP_MEMORY_BACKUPS_PATH=/app/data/backups
# HTTP configuration
- MCP_HTTP_PORT=8000
- MCP_HTTP_HOST=0.0.0.0
- MCP_API_KEY=${MCP_API_KEY:-your-secure-api-key-here}
# Optional: HTTPS configuration
# - MCP_HTTPS_ENABLED=true
# - MCP_HTTPS_PORT=8443
# - MCP_SSL_CERT_FILE=/app/certs/cert.pem
# - MCP_SSL_KEY_FILE=/app/certs/key.pem
# Performance tuning
- LOG_LEVEL=${LOG_LEVEL:-INFO}
- MAX_RESULTS_PER_QUERY=10
- SIMILARITY_THRESHOLD=0.7
# Python configuration
- PYTHONUNBUFFERED=1
- PYTHONPATH=/app/src
# Offline mode (uncomment if models are pre-cached and network is restricted)
# - HF_HUB_OFFLINE=1
# - TRANSFORMERS_OFFLINE=1
# Use the unified entrypoint
entrypoint: ["/usr/local/bin/docker-entrypoint-unified.sh"]
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# Resource limits (optional, adjust as needed)
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
```
--------------------------------------------------------------------------------
/scripts/testing/test-hook.js:
--------------------------------------------------------------------------------
```javascript
#!/usr/bin/env node
/**
* Test script for the enhanced session-start hook
*/
const path = require('path');
// Import the enhanced hook
const sessionStartHook = require('../../claude-hooks/core/session-start.js');
async function testEnhancedHook() {
console.log('🧪 Testing Enhanced Session Start Hook\n');
// Mock context for testing
const mockContext = {
workingDirectory: process.cwd(),
sessionId: 'test-session-' + Date.now(),
trigger: 'session-start',
userMessage: 'Help me understand the memory service improvements',
injectSystemMessage: async (message) => {
console.log('\n🎯 INJECTED CONTEXT:');
console.log('═'.repeat(60));
console.log(message);
console.log('═'.repeat(60));
return true;
}
};
console.log(`📂 Testing in directory: ${mockContext.workingDirectory}`);
console.log(`🔍 Test query: "${mockContext.userMessage}"`);
console.log(`⚙️ Trigger: ${mockContext.trigger}\n`);
try {
// Execute the enhanced hook
await sessionStartHook.handler(mockContext);
console.log('\n✅ Hook execution completed successfully!');
console.log('\n📊 Expected improvements:');
console.log(' • Multi-phase memory retrieval (recent + important + fallback)');
console.log(' • Enhanced recency indicators (🕒 today, 📅 this week)');
console.log(' • Better semantic queries with git context');
console.log(' • Improved categorization with "Recent Work" section');
console.log(' • Configurable memory ratios and time windows');
} catch (error) {
console.error('❌ Hook execution failed:', error.message);
console.error('Stack trace:', error.stack);
}
}
// Run the test
if (require.main === module) {
testEnhancedHook()
.then(() => {
console.log('\n🎉 Test completed');
process.exit(0);
})
.catch(error => {
console.error('\n💥 Test failed:', error.message);
process.exit(1);
});
}
module.exports = { testEnhancedHook };
```
--------------------------------------------------------------------------------
/tests/integration/conftest.py:
--------------------------------------------------------------------------------
```python
# Copyright 2024 Heinrich Krupp
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Shared fixtures and configuration for integration tests.
This conftest.py sets up test-wide authentication disabling to ensure
all integration tests can access the FastAPI endpoints without authentication.
CRITICAL: Environment variables MUST be set BEFORE any mcp_memory_service
modules are imported. This is because config.py reads env vars at module-level
import time, not at runtime.
Why session-scoped autouse fixture works:
- pytest loads conftest.py BEFORE importing test modules
- autouse=True ensures this runs BEFORE any test collection
- Session scope means it runs once at the very start
- os.environ changes affect subsequent imports of config.py
"""
import os
import pytest
@pytest.fixture(scope="session", autouse=True)
def disable_auth_for_integration_tests():
"""
Disable authentication globally for all integration tests.
Sets environment variables BEFORE any app imports happen.
This must be session-scoped and autouse=True to ensure it runs
before FastAPI app initialization.
Technical note for uvx CI compatibility:
- config.py reads env vars at import time: OAUTH_ENABLED = os.getenv('MCP_OAUTH_ENABLED', True)
- If config.py is imported before this fixture, auth remains enabled
- Session-scope + autouse ensures this runs FIRST
- Works in both local pytest and uvx CI environments
"""
# Set env vars BEFORE any imports
os.environ['MCP_API_KEY'] = ''
os.environ['MCP_OAUTH_ENABLED'] = 'false'
os.environ['MCP_ALLOW_ANONYMOUS_ACCESS'] = 'true'
yield
# Cleanup not needed - test session ends after this
```
--------------------------------------------------------------------------------
/tests/unit/test_imports.py:
--------------------------------------------------------------------------------
```python
# Copyright 2024 Heinrich Krupp
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Regression tests for import issues.
Ensures all required imports are present to prevent issues like the
'import time' bug fixed in v8.57.0 (Issue #295, Phase 1).
"""
import pytest
def test_server_impl_imports():
"""
Regression test for missing 'import time' bug (v8.57.0).
Ensures server_impl.py has all required imports, particularly the
'time' module which was missing and caused NameError in 27+ tests.
Related: PR #294, v8.57.0 Phase 1 fixes
"""
# Read server_impl.py source to verify imports are present
import os
server_impl_path = os.path.join(
os.path.dirname(__file__),
'../../src/mcp_memory_service/server_impl.py'
)
server_impl_path = os.path.abspath(server_impl_path)
with open(server_impl_path, 'r') as f:
source = f.read()
# Verify critical imports are present in source
assert 'import time' in source, "server_impl.py must import 'time' module"
assert 'import asyncio' in source, "server_impl.py must import 'asyncio'"
assert 'import logging' in source, "server_impl.py must import 'logging'"
assert 'import json' in source, "server_impl.py must import 'json'"
def test_memory_service_imports():
"""Ensure memory_service.py has all required imports."""
import mcp_memory_service.services.memory_service as ms
# Verify critical imports
assert hasattr(ms, 'logging'), "memory_service.py must import 'logging'"
# Verify model imports
from mcp_memory_service.models.memory import Memory, MemoryQueryResult
assert Memory is not None
assert MemoryQueryResult is not None
```
--------------------------------------------------------------------------------
/examples/start_https_example.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# Example HTTPS startup script for MCP Memory Service
# Copy and customize this file for your deployment
#
# This example shows how to configure the MCP Memory Service with custom SSL certificates.
# For easy local development with trusted certificates, consider using mkcert:
# https://github.com/FiloSottile/mkcert
# Storage configuration
export MCP_MEMORY_STORAGE_BACKEND=sqlite_vec
# API authentication - CHANGE THIS TO A SECURE KEY!
# Generate a secure key with: openssl rand -base64 32
export MCP_API_KEY="your-secure-api-key-here"
# HTTPS configuration with custom certificates
export MCP_HTTPS_ENABLED=true
export MCP_HTTPS_PORT=8443
# SSL Certificate paths - UPDATE THESE PATHS TO YOUR CERTIFICATES
#
# For mkcert certificates (recommended for development):
# 1. Install mkcert: https://github.com/FiloSottile/mkcert#installation
# 2. Create local CA: mkcert -install
# 3. Generate certificate: mkcert your-domain.local localhost 127.0.0.1
# 4. Update paths below to point to generated certificate files
#
# Example paths:
# export MCP_SSL_CERT_FILE="/path/to/your-domain.local+2.pem"
# export MCP_SSL_KEY_FILE="/path/to/your-domain.local+2-key.pem"
#
# For production, use certificates from your certificate authority:
export MCP_SSL_CERT_FILE="/path/to/your/certificate.pem"
export MCP_SSL_KEY_FILE="/path/to/your/certificate-key.pem"
# Optional: Disable HTTP if only HTTPS is needed
export MCP_HTTP_ENABLED=false
export MCP_HTTP_PORT=8080
# mDNS service discovery
export MCP_MDNS_ENABLED=true
export MCP_MDNS_SERVICE_NAME="MCP Memory Service"
# Optional: Additional configuration
# export MCP_MEMORY_INCLUDE_HOSTNAME=true
# export MCP_CONSOLIDATION_ENABLED=false
echo "Starting MCP Memory Service with HTTPS on port $MCP_HTTPS_PORT"
echo "Certificate: $MCP_SSL_CERT_FILE"
echo "Private Key: $MCP_SSL_KEY_FILE"
# Change to script directory and start server
cd "$(dirname "$0")/.."
# Check if virtual environment exists
if [ ! -f ".venv/bin/python" ]; then
echo "Error: Virtual environment not found at .venv/"
echo "Please run: python -m venv .venv && source .venv/bin/activate && pip install -e ."
exit 1
fi
# Start the server
exec ./.venv/bin/python run_server.py
```
--------------------------------------------------------------------------------
/docs/document-ingestion.md:
--------------------------------------------------------------------------------
```markdown
# Document Ingestion (v7.6.0+)
Enhanced document parsing with optional semtools integration for superior quality extraction.
## Supported Formats
| Format | Native Parser | With Semtools | Quality |
|--------|--------------|---------------|---------|
| PDF | PyPDF2/pdfplumber | LlamaParse | Excellent (OCR, tables) |
| DOCX | Not supported | LlamaParse | Excellent |
| PPTX | Not supported | LlamaParse | Excellent |
| TXT/MD | Built-in | N/A | Perfect |
## Semtools Integration (Optional)
Install [semtools](https://github.com/run-llama/semtools) for enhanced document parsing:
```bash
# Install via npm (recommended)
npm i -g @llamaindex/semtools
# Or via cargo
cargo install semtools
# Optional: Configure LlamaParse API key for best quality
export LLAMAPARSE_API_KEY="your-api-key"
```
## Configuration
```bash
# Document chunking settings
export MCP_DOCUMENT_CHUNK_SIZE=1000 # Characters per chunk
export MCP_DOCUMENT_CHUNK_OVERLAP=200 # Overlap between chunks
# LlamaParse API key (optional, improves quality)
export LLAMAPARSE_API_KEY="llx-..."
```
## Usage Examples
```bash
# Ingest a single document
claude /memory-ingest document.pdf --tags documentation
# Ingest directory
claude /memory-ingest-dir ./docs --tags knowledge-base
# Via Python
from mcp_memory_service.ingestion import get_loader_for_file
loader = get_loader_for_file(Path("document.pdf"))
async for chunk in loader.extract_chunks(Path("document.pdf")):
await store_memory(chunk.content, tags=["doc"])
```
## Features
- **Automatic format detection** - Selects best loader for each file
- **Intelligent chunking** - Respects paragraph/sentence boundaries
- **Metadata enrichment** - Preserves file info, extraction method, page numbers
- **Graceful fallback** - Uses native parsers if semtools unavailable
- **Progress tracking** - Reports chunks processed during ingestion
## Performance Considerations
- LlamaParse provides superior quality but requires API key and internet connection
- Native parsers work offline but may have lower extraction quality for complex documents
- Chunk size affects retrieval granularity vs context completeness
- Larger overlap improves continuity but increases storage
```
--------------------------------------------------------------------------------
/scripts/sync/litestream/manual_sync.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# Manual sync using HTTP downloads (alternative to Litestream restore)
DB_PATH="/Users/hkr/Library/Application Support/mcp-memory/sqlite_vec.db"
REMOTE_BASE="http://narrowbox.local:8080/mcp-memory"
BACKUP_PATH="/Users/hkr/Library/Application Support/mcp-memory/sqlite_vec.db.backup"
TEMP_DIR="/tmp/litestream_manual_$$"
echo "$(date): Starting manual sync from remote master..."
# Create temporary directory
mkdir -p "$TEMP_DIR"
# Get the latest generation ID
GENERATION=$(curl -s "$REMOTE_BASE/generations/" | grep -o 'href="[^"]*/"' | sed 's/href="//;s/\/"//g' | head -1)
if [ -z "$GENERATION" ]; then
echo "$(date): ERROR: Could not determine generation ID"
exit 1
fi
echo "$(date): Found generation: $GENERATION"
# Get the latest snapshot
SNAPSHOT_URL="$REMOTE_BASE/generations/$GENERATION/snapshots/"
SNAPSHOT_FILE=$(curl -s "$SNAPSHOT_URL" | grep -o 'href="[^"]*\.snapshot\.lz4"' | sed 's/href="//;s/"//g' | tail -1)
if [ -z "$SNAPSHOT_FILE" ]; then
echo "$(date): ERROR: Could not find snapshot file"
rm -rf "$TEMP_DIR"
exit 1
fi
echo "$(date): Downloading snapshot: $SNAPSHOT_FILE"
# Download and decompress snapshot
curl -s "$SNAPSHOT_URL$SNAPSHOT_FILE" -o "$TEMP_DIR/snapshot.lz4"
if command -v lz4 >/dev/null 2>&1; then
# Use lz4 if available
lz4 -d "$TEMP_DIR/snapshot.lz4" "$TEMP_DIR/database.db"
else
echo "$(date): ERROR: lz4 command not found. Please install: brew install lz4"
rm -rf "$TEMP_DIR"
exit 1
fi
# Backup current database
if [ -f "$DB_PATH" ]; then
cp "$DB_PATH" "$BACKUP_PATH"
echo "$(date): Created backup at $BACKUP_PATH"
fi
# Replace with new database
cp "$TEMP_DIR/database.db" "$DB_PATH"
if [ $? -eq 0 ]; then
echo "$(date): Successfully synced database from remote master"
# Remove backup on success
rm -f "$BACKUP_PATH"
# Show database info
echo "$(date): Database size: $(du -h "$DB_PATH" | cut -f1)"
echo "$(date): Database modified: $(stat -f "%Sm" "$DB_PATH")"
else
echo "$(date): ERROR: Failed to replace database"
# Restore backup on failure
if [ -f "$BACKUP_PATH" ]; then
mv "$BACKUP_PATH" "$DB_PATH"
echo "$(date): Restored backup"
fi
rm -rf "$TEMP_DIR"
exit 1
fi
# Cleanup
rm -rf "$TEMP_DIR"
echo "$(date): Manual sync completed successfully"
```
--------------------------------------------------------------------------------
/scripts/utils/README_detect_platform.md:
--------------------------------------------------------------------------------
```markdown
# Platform Detection Helper
## Overview
`detect_platform.py` provides unified hardware and OS detection for bash scripts, using the same `gpu_detection.py` module as `install.py` for consistency.
## Usage
```bash
# Run detection
python scripts/utils/detect_platform.py
# Output (JSON):
{
"os": "darwin",
"arch": "arm64",
"is_arm": true,
"is_x86": false,
"accelerator": "mps",
"has_cuda": false,
"has_rocm": false,
"has_mps": true,
"has_directml": false,
"cuda_version": null,
"rocm_version": null,
"directml_version": null,
"pytorch_index_url": "",
"needs_directml": false
}
```
## Supported Platforms
| Platform | Detection | PyTorch Index |
|----------|-----------|---------------|
| **Apple Silicon (M1/M2/M3)** | MPS via system_profiler | Default PyPI (MPS built-in) |
| **NVIDIA GPU (CUDA)** | nvcc version | cu121/cu118/cu102 |
| **AMD GPU (ROCm)** | rocminfo | rocm5.6 |
| **Windows DirectML** | torch-directml import | CPU + directml package |
| **CPU-only** | Fallback | CPU index |
## Integration with update_and_restart.sh
The script automatically:
1. Detects hardware platform (MPS/CUDA/ROCm/DirectML/CPU)
2. Selects optimal PyTorch index URL
3. Installs DirectML package if needed (Windows)
4. Falls back to basic detection if Python helper unavailable
## Benefits vs. Old Logic
**Old (Bash-only):**
- ❌ Only detected macOS vs. Linux with nvidia-smi
- ❌ Treated all macOS as CPU-only (performance loss on M-series)
- ❌ No ROCm, DirectML, or MPS support
**New (Python-based):**
- ✅ Detects MPS, CUDA, ROCm, DirectML, CPU
- ✅ Consistent with install.py logic
- ✅ Optimal PyTorch selection per platform
- ✅ Graceful fallback to old logic if detection fails
## Example Output (macOS M2)
```bash
▶ Installing dependencies (editable mode)...
ℹ Existing venv Python version: 3.13
ℹ Installing with venv pip (this may take 1-2 minutes)...
ℹ Apple Silicon MPS detected - using MPS-optimized PyTorch
```
## Example Output (Linux with NVIDIA)
```bash
▶ Installing dependencies (editable mode)...
ℹ CUDA detected (12.1) - using optimized PyTorch
Installing with: --extra-index-url https://download.pytorch.org/whl/cu121
```
## Maintenance
The detection logic is centralized in `src/mcp_memory_service/utils/gpu_detection.py`. Updates to that module automatically benefit both `install.py` and `update_and_restart.sh`.
```
--------------------------------------------------------------------------------
/claude-hooks/utilities/user-override-detector.js:
--------------------------------------------------------------------------------
```javascript
/**
* User Override Detector
* Shared module for consistent #skip/#remember handling across all hooks
*
* Usage:
* const { detectUserOverrides } = require('./user-override-detector');
* const overrides = detectUserOverrides(userMessage);
* if (overrides.forceSkip) return;
*/
// User override patterns (case-insensitive, word boundary)
const USER_OVERRIDES = {
forceRemember: /#remember\b/i,
forceSkip: /#skip\b/i
};
/**
* Detect user overrides in a message
* @param {string} userMessage - The user's message text
* @returns {Object} Override detection result
*/
function detectUserOverrides(userMessage) {
if (!userMessage || typeof userMessage !== 'string') {
return { forceRemember: false, forceSkip: false };
}
return {
forceRemember: USER_OVERRIDES.forceRemember.test(userMessage),
forceSkip: USER_OVERRIDES.forceSkip.test(userMessage)
};
}
/**
* Extract user message from various context formats
* Handles different hook context structures
* @param {Object} context - Hook context object
* @returns {string|null} Extracted user message or null
*/
function extractUserMessage(context) {
if (!context) return null;
// Direct userMessage property
if (context.userMessage) {
return typeof context.userMessage === 'string'
? context.userMessage
: null;
}
// From transcript (last user message)
if (context.transcript_path) {
// Transcript extraction should be done by caller
return null;
}
// From message property
if (context.message) {
return typeof context.message === 'string'
? context.message
: null;
}
return null;
}
/**
* Console output for override actions
*/
const OVERRIDE_MESSAGES = {
skip: '\x1b[33m\u23ed\ufe0f Memory Hook\x1b[0m \x1b[2m\u2192\x1b[0m Skipped by user override (#skip)',
remember: '\x1b[36m\ud83d\udcbe Memory Hook\x1b[0m \x1b[2m\u2192\x1b[0m Force triggered by user override (#remember)'
};
/**
* Log override action to console
* @param {'skip'|'remember'} action - The override action
*/
function logOverride(action) {
if (OVERRIDE_MESSAGES[action]) {
console.log(OVERRIDE_MESSAGES[action]);
}
}
module.exports = {
detectUserOverrides,
extractUserMessage,
logOverride,
USER_OVERRIDES,
OVERRIDE_MESSAGES
};
```
--------------------------------------------------------------------------------
/scripts/service/windows/add_watchdog_trigger.ps1:
--------------------------------------------------------------------------------
```
#Requires -Version 5.1
<#
.SYNOPSIS
Adds a repeating watchdog trigger to the MCP Memory HTTP Server task.
.DESCRIPTION
Modifies the scheduled task to run every N minutes, ensuring the server
automatically restarts if it crashes between logins.
.PARAMETER IntervalMinutes
How often to check (default: 5 minutes).
.EXAMPLE
.\add_watchdog_trigger.ps1
Adds a 5-minute watchdog trigger.
.EXAMPLE
.\add_watchdog_trigger.ps1 -IntervalMinutes 10
Adds a 10-minute watchdog trigger.
#>
param(
[int]$IntervalMinutes = 5
)
$ErrorActionPreference = "Stop"
$TaskName = "MCPMemoryHTTPServer"
Write-Host ""
Write-Host "Adding Watchdog Trigger to $TaskName" -ForegroundColor Cyan
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host ""
# Check if task exists
$Task = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
if (-not $Task) {
Write-Host "[ERROR] Task '$TaskName' not found. Run install_scheduled_task.ps1 first." -ForegroundColor Red
exit 1
}
Write-Host "[INFO] Current triggers:"
$Task.Triggers | ForEach-Object {
Write-Host " - $($_.CimClass.CimClassName)"
}
# Create new repeating trigger
Write-Host ""
Write-Host "[INFO] Adding repeating trigger (every $IntervalMinutes minutes)..." -ForegroundColor Yellow
# Note: RepetitionDuration must be finite but long (9999 days = ~27 years)
$RepetitionTrigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `
-RepetitionInterval (New-TimeSpan -Minutes $IntervalMinutes) `
-RepetitionDuration (New-TimeSpan -Days 9999)
# Get existing triggers and add new one
$ExistingTriggers = @($Task.Triggers)
$AllTriggers = $ExistingTriggers + @($RepetitionTrigger)
# Update task
Set-ScheduledTask -TaskName $TaskName -Trigger $AllTriggers | Out-Null
Write-Host "[SUCCESS] Watchdog trigger added!" -ForegroundColor Green
Write-Host ""
Write-Host "Configuration:" -ForegroundColor Cyan
Write-Host " - Check interval: Every $IntervalMinutes minutes"
Write-Host " - Behavior: If server already running, exits immediately"
Write-Host " - Behavior: If server not running, starts it"
Write-Host ""
# Show updated triggers
$UpdatedTask = Get-ScheduledTask -TaskName $TaskName
Write-Host "Updated triggers:" -ForegroundColor Cyan
$UpdatedTask.Triggers | ForEach-Object {
$Type = $_.CimClass.CimClassName -replace 'MSFT_Task', '' -replace 'Trigger', ''
Write-Host " - $Type"
}
Write-Host ""
```
--------------------------------------------------------------------------------
/docs/archive/obsolete-workflows/load_memory_context.md:
--------------------------------------------------------------------------------
```markdown
# Memory Context Loading Prompt
Use this prompt at the start of Claude Code sessions on machines in your local network:
---
## Prompt for Claude Code
```
Load MCP Memory Service context for this project. Before we begin working, please retrieve and incorporate all stored knowledge about this codebase from my local memory service:
**Memory Service Endpoint**: https://your-server-ip:8443/mcp
**Authorization**: Bearer your-api-key
Execute this command to load context:
```bash
curl -k -s -X POST https://your-server-ip:8443/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-api-key" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "retrieve_memory", "arguments": {"query": "claude-code-reference distributable-reference", "limit": 20}}}' \
| jq -r '.result.content[0].text'
```
This memory contains:
- Complete project structure and architecture
- All key development, testing, and deployment commands
- Environment variables and configuration patterns
- Recent changes including v5.0.2 ONNX implementation details
- Issue management approaches and current project status
- Testing practices and platform-specific optimizations
- Remote service deployment and health monitoring
After loading this context, you'll have comprehensive knowledge of the MCP Memory Service project equivalent to extensive codebase exploration, which will significantly reduce token usage and improve response accuracy.
Please confirm successful context loading and summarize the key project information you've retrieved.
```
---
## Alternative Short Prompt
For quick context loading:
```
Load project context from memory service: curl -k -s -X POST https://your-server-ip:8443/mcp -H "Content-Type: application/json" -H "Authorization: Bearer your-api-key" -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "retrieve_memory", "arguments": {"query": "claude-code-reference", "limit": 20}}}' | jq -r '.result.content[0].text'
Incorporate this MCP Memory Service project knowledge before proceeding.
```
---
## Network Distribution
1. **Copy this prompt file** to other machines in your network
2. **Update IP address** if memory service moves
3. **Test connectivity** with: `curl -k -s https://your-server-ip:8443/api/health`
4. **Use at session start** for instant project context
This eliminates repetitive codebase discovery across all your development machines.
```
--------------------------------------------------------------------------------
/scripts/service/service_control.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# MCP Memory Service Control Script
SERVICE_NAME="mcp-memory"
case "$1" in
start)
echo "Starting MCP Memory Service..."
sudo systemctl start $SERVICE_NAME
sleep 2
sudo systemctl status $SERVICE_NAME --no-pager
;;
stop)
echo "Stopping MCP Memory Service..."
sudo systemctl stop $SERVICE_NAME
sudo systemctl status $SERVICE_NAME --no-pager
;;
restart)
echo "Restarting MCP Memory Service..."
sudo systemctl restart $SERVICE_NAME
sleep 2
sudo systemctl status $SERVICE_NAME --no-pager
;;
status)
sudo systemctl status $SERVICE_NAME --no-pager
;;
logs)
echo "Showing recent logs (Ctrl+C to exit)..."
sudo journalctl -u $SERVICE_NAME -f
;;
health)
echo "Checking service health..."
curl -k -s https://localhost:8000/api/health | jq '.' 2>/dev/null || curl -k -s https://localhost:8000/api/health
;;
enable)
echo "Enabling service for startup..."
sudo systemctl enable $SERVICE_NAME
echo "Service will start automatically on boot"
;;
disable)
echo "Disabling service from startup..."
sudo systemctl disable $SERVICE_NAME
echo "Service will not start automatically on boot"
;;
install)
echo "Installing service..."
./install_service.sh
;;
uninstall)
echo "Uninstalling service..."
sudo systemctl stop $SERVICE_NAME 2>/dev/null
sudo systemctl disable $SERVICE_NAME 2>/dev/null
sudo rm -f /etc/systemd/system/$SERVICE_NAME.service
sudo systemctl daemon-reload
echo "Service uninstalled"
;;
*)
echo "Usage: $0 {start|stop|restart|status|logs|health|enable|disable|install|uninstall}"
echo ""
echo "Commands:"
echo " start - Start the service"
echo " stop - Stop the service"
echo " restart - Restart the service"
echo " status - Show service status"
echo " logs - Show live service logs"
echo " health - Check API health endpoint"
echo " enable - Enable service for startup"
echo " disable - Disable service from startup"
echo " install - Install the systemd service"
echo " uninstall - Remove the systemd service"
exit 1
;;
esac
```
--------------------------------------------------------------------------------
/tests/smithery/test_smithery.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""
Test script to verify Smithery configuration works correctly.
This simulates how Smithery would invoke the service.
"""
import os
import sys
import subprocess
import tempfile
import json
def test_smithery_config():
"""Test the Smithery configuration by simulating the expected command."""
print("Testing Smithery configuration...")
# Create temporary paths for testing
with tempfile.TemporaryDirectory() as temp_dir:
chroma_path = os.path.join(temp_dir, "chroma_db")
backups_path = os.path.join(temp_dir, "backups")
# Create directories
os.makedirs(chroma_path, exist_ok=True)
os.makedirs(backups_path, exist_ok=True)
# Set environment variables as Smithery would
test_env = os.environ.copy()
test_env.update({
'MCP_MEMORY_CHROMA_PATH': chroma_path,
'MCP_MEMORY_BACKUPS_PATH': backups_path,
'PYTHONUNBUFFERED': '1',
'PYTORCH_ENABLE_MPS_FALLBACK': '1'
})
# Command that Smithery would run
cmd = [sys.executable, 'smithery_wrapper.py', '--version']
print(f"Running command: {' '.join(cmd)}")
print(f"Environment: {json.dumps({k: v for k, v in test_env.items() if k.startswith('MCP_') or k in ['PYTHONUNBUFFERED', 'PYTORCH_ENABLE_MPS_FALLBACK']}, indent=2)}")
try:
result = subprocess.run(
cmd,
env=test_env,
capture_output=True,
text=True,
timeout=30
)
print(f"Return code: {result.returncode}")
if result.stdout:
print(f"STDOUT:\n{result.stdout}")
if result.stderr:
print(f"STDERR:\n{result.stderr}")
if result.returncode == 0:
print("✅ SUCCESS: Smithery configuration test passed!")
return True
else:
print("❌ FAILED: Smithery configuration test failed!")
return False
except subprocess.TimeoutExpired:
print("❌ FAILED: Command timed out")
return False
except Exception as e:
print(f"❌ FAILED: Exception occurred: {e}")
return False
if __name__ == "__main__":
success = test_smithery_config()
sys.exit(0 if success else 1)
```
--------------------------------------------------------------------------------
/docs/integrations/groq-bridge.md:
--------------------------------------------------------------------------------
```markdown
# Groq Agent Bridge - Requirements
Install the required package:
```bash
pip install groq
# or
uv pip install groq
```
Set up your environment:
```bash
export GROQ_API_KEY="your-api-key-here"
```
## Available Models
The Groq bridge supports multiple high-performance models:
| Model | Context | Best For | Speed |
|-------|---------|----------|-------|
| **llama-3.3-70b-versatile** | 128K | General purpose (default) | ~300ms |
| **moonshotai/kimi-k2-instruct** | 256K | Agentic coding, tool calling | ~200ms |
| **llama-3.1-8b-instant** | 128K | Fast, simple tasks | ~100ms |
**Kimi K2 Features:**
- 256K context window (largest on GroqCloud)
- 1 trillion parameters (32B activated)
- Excellent for front-end development and complex coding
- Superior agentic intelligence and tool calling
- 185 tokens/second throughput
## Usage Examples
### As a library from another AI agent:
```python
from groq_agent_bridge import GroqAgentBridge
# Initialize the bridge
bridge = GroqAgentBridge()
# Simple call
response = bridge.call_model_raw("Explain quantum computing in simple terms")
print(response)
# Advanced call with options
result = bridge.call_model(
prompt="Generate Python code for a binary search tree",
model="llama-3.3-70b-versatile",
max_tokens=500,
temperature=0.3,
system_message="You are an expert Python programmer"
)
print(result)
```
### Command-line usage:
```bash
# Simple usage (uses default llama-3.3-70b-versatile)
./scripts/utils/groq "What is machine learning?"
# Use Kimi K2 for complex coding tasks
./scripts/utils/groq "Generate a React component with hooks" \
--model "moonshotai/kimi-k2-instruct"
# Fast simple queries with llama-3.1-8b-instant
./scripts/utils/groq "Rate complexity 1-10: def add(a,b): return a+b" \
--model "llama-3.1-8b-instant"
# Full options with default model
./scripts/utils/groq "Generate a SQL query" \
--model "llama-3.3-70b-versatile" \
--max-tokens 200 \
--temperature 0.5 \
--system "You are a database expert" \
--json
```
### Integration with bash scripts:
```bash
#!/bin/bash
export GROQ_API_KEY="your-key"
# Get response and save to file
python groq_agent_bridge.py "Write a haiku about code" --temperature 0.9 > response.txt
# JSON output for parsing
json_response=$(python groq_agent_bridge.py "Explain REST APIs" --json)
# Parse with jq or other tools
```
This provides a completely non-interactive way for other AI agents to call Groq's models!
```
--------------------------------------------------------------------------------
/src/mcp_memory_service/server/__init__.py:
--------------------------------------------------------------------------------
```python
# Copyright 2024 Heinrich Krupp
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Server package for MCP Memory Service.
Modular server components for better maintainability:
- client_detection: MCP client detection (Claude Desktop, LM Studio, etc.)
- logging_config: Client-aware logging configuration
- environment: Python path setup, version checks, performance config
- cache_manager: Global caching for storage and service instances
"""
# Client Detection
from .client_detection import MCP_CLIENT, detect_mcp_client
# Logging Configuration
from .logging_config import DualStreamHandler, configure_logging, logger
# Environment Configuration
from .environment import (
setup_python_paths,
check_uv_environment,
check_version_consistency,
configure_environment,
configure_performance_environment
)
# Cache Management
from .cache_manager import (
_STORAGE_CACHE,
_MEMORY_SERVICE_CACHE,
_CACHE_LOCK,
_CACHE_STATS,
_get_cache_lock,
_get_or_create_memory_service,
_log_cache_performance
)
# Backward compatibility: Import main functions from server_impl.py
# server_impl.py (formerly server.py) contains main() and async_main()
# We re-export them for backward compatibility: from mcp_memory_service.server import main
from ..server_impl import main, async_main, MemoryServer
__all__ = [
# Client Detection
'MCP_CLIENT',
'detect_mcp_client',
# Logging
'DualStreamHandler',
'configure_logging',
'logger',
# Environment
'setup_python_paths',
'check_uv_environment',
'check_version_consistency',
'configure_environment',
'configure_performance_environment',
# Cache
'_STORAGE_CACHE',
'_MEMORY_SERVICE_CACHE',
'_CACHE_LOCK',
'_CACHE_STATS',
'_get_cache_lock',
'_get_or_create_memory_service',
'_log_cache_performance',
# Entry points and core classes (for backward compatibility)
'main',
'async_main',
'MemoryServer',
]
```
--------------------------------------------------------------------------------
/src/mcp_memory_service/cli/utils.py:
--------------------------------------------------------------------------------
```python
# Copyright 2024 Heinrich Krupp
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
CLI utilities for MCP Memory Service.
"""
import os
from typing import Optional
from ..storage.base import MemoryStorage
async def get_storage(backend: Optional[str] = None) -> MemoryStorage:
"""
Get storage backend for CLI operations.
Args:
backend: Storage backend name ('sqlite_vec', 'cloudflare', or 'hybrid')
Returns:
Initialized storage backend
"""
# Determine backend
if backend is None:
backend = os.getenv('MCP_MEMORY_STORAGE_BACKEND', 'sqlite_vec').lower()
backend = backend.lower()
if backend in ('sqlite_vec', 'sqlite-vec'):
from ..storage.sqlite_vec import SqliteVecMemoryStorage
from ..config import SQLITE_VEC_PATH
storage = SqliteVecMemoryStorage(SQLITE_VEC_PATH)
await storage.initialize()
return storage
elif backend == 'cloudflare':
from ..storage.cloudflare import CloudflareStorage
from ..config import (
CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID,
CLOUDFLARE_VECTORIZE_INDEX, CLOUDFLARE_D1_DATABASE_ID,
CLOUDFLARE_R2_BUCKET, CLOUDFLARE_EMBEDDING_MODEL,
CLOUDFLARE_LARGE_CONTENT_THRESHOLD, CLOUDFLARE_MAX_RETRIES,
CLOUDFLARE_BASE_DELAY
)
storage = CloudflareStorage(
api_token=CLOUDFLARE_API_TOKEN,
account_id=CLOUDFLARE_ACCOUNT_ID,
vectorize_index=CLOUDFLARE_VECTORIZE_INDEX,
d1_database_id=CLOUDFLARE_D1_DATABASE_ID,
r2_bucket=CLOUDFLARE_R2_BUCKET,
embedding_model=CLOUDFLARE_EMBEDDING_MODEL,
large_content_threshold=CLOUDFLARE_LARGE_CONTENT_THRESHOLD,
max_retries=CLOUDFLARE_MAX_RETRIES,
base_delay=CLOUDFLARE_BASE_DELAY
)
await storage.initialize()
return storage
else:
raise ValueError(f"Unsupported storage backend: {backend}")
```
--------------------------------------------------------------------------------
/scripts/migration/TIMESTAMP_CLEANUP_README.md:
--------------------------------------------------------------------------------
```markdown
# MCP Memory Timestamp Cleanup Scripts
## Overview
These scripts help clean up the timestamp mess in your MCP Memory ChromaDB database where multiple timestamp formats and fields have accumulated over time.
## Files
1. **`verify_mcp_timestamps.py`** - Verification script to check current timestamp state
2. **`cleanup_mcp_timestamps.py`** - Migration script to fix timestamp issues
## The Problem
Your database has accumulated 8 different timestamp-related fields:
- `timestamp` (integer) - Original design
- `created_at` (float) - Duplicate data
- `created_at_iso` (string) - ISO format duplicate
- `timestamp_float` (float) - Another duplicate
- `timestamp_str` (string) - String format duplicate
- `updated_at` (float) - Update tracking
- `updated_at_iso` (string) - Update tracking in ISO
- `date` (generic) - Generic date field
This causes:
- 3x storage overhead for the same timestamp
- Confusion about which field to use
- Inconsistent data retrieval
## Usage
### Step 1: Verify Current State
```bash
python3 scripts/migrations/verify_mcp_timestamps.py
```
This will show:
- Total memories in database
- Distribution of timestamp fields
- Memories missing timestamps
- Sample values showing the redundancy
- Date ranges for each timestamp type
### Step 2: Run Migration
```bash
python3 scripts/migrations/cleanup_mcp_timestamps.py
```
The migration will:
1. **Create a backup** of your database
2. **Standardize** all timestamps to integer format in the `timestamp` field
3. **Remove** all redundant timestamp fields
4. **Ensure** all memories have valid timestamps
5. **Optimize** the database with VACUUM
### Step 3: Verify Results
```bash
python3 scripts/migrations/verify_mcp_timestamps.py
```
After migration, you should see:
- Only one timestamp field (`timestamp`)
- All memories have timestamps
- Clean data structure
## Safety
- The migration script **always creates a backup** before making changes
- Backup location: `/Users/hkr/Library/Application Support/mcp-memory/chroma_db/chroma.sqlite3.backup_YYYYMMDD_HHMMSS`
- If anything goes wrong, you can restore the backup
## Restoration (if needed)
If you need to restore from backup:
```bash
# Stop Claude Desktop first
cp "/path/to/backup" "/Users/hkr/Library/Application Support/mcp-memory/chroma_db/chroma.sqlite3"
```
## After Migration
Update your MCP Memory Service code to only use the `timestamp` field (integer format) for all timestamp operations. This prevents the issue from recurring.
```
--------------------------------------------------------------------------------
/src/mcp_memory_service/utils/http_server_manager.py:
--------------------------------------------------------------------------------
```python
"""HTTP Server Manager for MCP Memory Service multi-client coordination."""
import asyncio
import logging
import os
import subprocess
import sys
from pathlib import Path
from typing import Optional
logger = logging.getLogger(__name__)
async def auto_start_http_server_if_needed() -> bool:
"""
Auto-start HTTP server if needed for multi-client coordination.
Returns:
bool: True if server was started or already running, False if failed
"""
try:
# Check if HTTP auto-start is enabled
if not os.getenv("MCP_MEMORY_HTTP_AUTO_START", "").lower() in ("true", "1"):
logger.debug("HTTP auto-start not enabled")
return False
# Check if server is already running
from ..utils.port_detection import is_port_in_use
port = int(os.getenv("MCP_HTTP_PORT", "8000"))
if await is_port_in_use("localhost", port):
logger.info(f"HTTP server already running on port {port}")
return True
# Try to start the HTTP server
logger.info(f"Starting HTTP server on port {port}")
# Get the repository root
repo_root = Path(__file__).parent.parent.parent.parent
# Start the HTTP server as a background process
cmd = [
sys.executable, "-m", "src.mcp_memory_service.app",
"--port", str(port),
"--host", "localhost"
]
process = subprocess.Popen(
cmd,
cwd=repo_root,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True
)
# Wait a moment and check if the process started successfully
await asyncio.sleep(1)
if process.poll() is None: # Process is still running
# Wait a bit more and check if port is now in use
await asyncio.sleep(2)
if await is_port_in_use("localhost", port):
logger.info(f"Successfully started HTTP server on port {port}")
return True
else:
logger.warning("HTTP server process started but port not in use")
return False
else:
logger.warning(f"HTTP server process exited with code {process.returncode}")
return False
except Exception as e:
logger.error(f"Failed to auto-start HTTP server: {e}")
return False
```
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
```python
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'))
# 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.
Deletes all memories tagged with TEST_MEMORY_TAG to prevent
test data from polluting the production database.
"""
try:
from mcp_memory_service.api import delete_by_tag
result = delete_by_tag([TEST_MEMORY_TAG])
deleted = result.get('deleted', 0) if isinstance(result, dict) else 0
if deleted > 0:
print(f"\n[Test Cleanup] Deleted {deleted} test memories tagged with '{TEST_MEMORY_TAG}'")
except Exception as e:
# Don't fail the test session if cleanup fails
print(f"\n[Test Cleanup] Warning: Could not cleanup test memories: {e}")
```
--------------------------------------------------------------------------------
/archive/docs-removed-2025-08-23/claude_integration.md:
--------------------------------------------------------------------------------
```markdown
# MCP Memory Service - Development Guidelines
## Commands
- Run memory server: `python scripts/run_memory_server.py`
- Run tests: `pytest tests/`
- Run specific test: `pytest tests/test_memory_ops.py::test_store_memory -v`
- Check environment: `python scripts/verify_environment_enhanced.py`
- Windows installation: `python scripts/install_windows.py`
- Build package: `python -m build`
## Installation Guidelines
- Always install in a virtual environment: `python -m venv venv`
- Use `install.py` for cross-platform installation
- Windows requires special PyTorch installation with correct index URL:
```bash
pip install torch==2.1.0 torchvision==2.1.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cu118
```
- For recursion errors, run: `python scripts/fix_sitecustomize.py`
## Memory Service Invocation
- See the comprehensive [Invocation Guide](invocation_guide.md) for full details
- Key trigger phrases:
- **Storage**: "remember that", "remember this", "save to memory", "store in memory"
- **Retrieval**: "do you remember", "recall", "retrieve from memory", "search your memory for"
- **Tag-based**: "find memories with tag", "search for tag", "retrieve memories tagged"
- **Deletion**: "forget", "delete from memory", "remove from memory"
## Code Style
- Python 3.10+ with type hints
- Use dataclasses for models (see `models/memory.py`)
- Triple-quoted docstrings for modules and functions
- Async/await pattern for all I/O operations
- Error handling with specific exception types and informative messages
- Logging with appropriate levels for different severity
- Commit messages follow semantic release format: `type(scope): message`
## Project Structure
- `src/mcp_memory_service/` - Core package code
- `models/` - Data models
- `storage/` - Database abstraction
- `utils/` - Helper functions
- `server.py` - MCP protocol implementation
- `scripts/` - Utility scripts
- `memory_wrapper.py` - Windows wrapper script
- `install.py` - Cross-platform installation script
## Dependencies
- ChromaDB (0.5.23) for vector database
- sentence-transformers (>=2.2.2) for embeddings
- PyTorch (platform-specific installation)
- MCP protocol (>=1.0.0, <2.0.0) for client-server communication
## Troubleshooting
- For Windows installation issues, use `scripts/install_windows.py`
- Apple Silicon requires Python 3.10+ built for ARM64
- CUDA issues: verify with `torch.cuda.is_available()`
- For MCP protocol issues, check `server.py` for required methods
```
--------------------------------------------------------------------------------
/.claude/directives/quality-system-details.md:
--------------------------------------------------------------------------------
```markdown
# Memory Quality System - Detailed Reference
**Quick Summary for CLAUDE.md**: See main file for architecture overview. This file contains implementation details, configuration options, and troubleshooting.
## Complete Configuration Options
```bash
# Quality System (Local-First Defaults)
MCP_QUALITY_SYSTEM_ENABLED=true # Default: enabled
MCP_QUALITY_AI_PROVIDER=local # local|groq|gemini|auto|none
MCP_QUALITY_LOCAL_MODEL=nvidia-quality-classifier-deberta # Default v8.49.0+
MCP_QUALITY_LOCAL_DEVICE=auto # auto|cpu|cuda|mps|directml
# Legacy model (backward compatible, not recommended)
# MCP_QUALITY_LOCAL_MODEL=ms-marco-MiniLM-L-6-v2
# Quality-Boosted Search (Recommended with DeBERTa)
MCP_QUALITY_BOOST_ENABLED=true # More accurate with DeBERTa
MCP_QUALITY_BOOST_WEIGHT=0.3 # 0.3 = 30% quality, 70% semantic
# Quality-Based Retention
MCP_QUALITY_RETENTION_HIGH=365 # Days for quality ≥0.7
MCP_QUALITY_RETENTION_MEDIUM=180 # Days for 0.5-0.7
MCP_QUALITY_RETENTION_LOW_MIN=30 # Min days for <0.5
```
## MCP Tools
- `rate_memory(content_hash, rating, feedback)` - Manual quality rating (-1/0/1)
- `get_memory_quality(content_hash)` - Retrieve quality metrics
- `analyze_quality_distribution(min_quality, max_quality)` - System-wide analytics
- `retrieve_with_quality_boost(query, n_results, quality_weight)` - Quality-boosted search
## Migration from MS-MARCO to DeBERTa
**Why Migrate:**
- ✅ Eliminates self-matching bias (no query needed)
- ✅ Uniform distribution (mean 0.60-0.70 vs 0.469)
- ✅ Fewer false positives (<5% perfect scores vs 20%)
- ✅ Absolute quality assessment vs relative ranking
**Migration Guide**: See [docs/guides/memory-quality-guide.md](../../docs/guides/memory-quality-guide.md#migration-from-ms-marco-to-deberta)
## Success Metrics (Phase 1 - v8.48.3)
**Achieved:**
- ✅ <100ms search latency with quality boost (45ms avg, +17% overhead)
- ✅ $0 monthly cost (local SLM default)
- ✅ 75% local SLM usage (3,570 of 4,762 memories)
- ✅ 95% quality score coverage
**Challenges:**
- ⚠️ Average score 0.469 (target: 0.6+)
- ⚠️ Self-matching bias ~25%
- ⚠️ Quality boost minimal ranking improvement (0-3%)
**Next Phase**: See [Issue #268](https://github.com/doobidoo/mcp-memory-service/issues/268)
## Troubleshooting
See [docs/guides/memory-quality-guide.md](../../docs/guides/memory-quality-guide.md) for:
- Model download issues
- Performance tuning
- Quality score interpretation
- User feedback integration
```
--------------------------------------------------------------------------------
/src/mcp_memory_service/server/client_detection.py:
--------------------------------------------------------------------------------
```python
# Copyright 2024 Heinrich Krupp
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Client detection module for MCP Memory Service.
Detects which MCP client is running the server (Claude Desktop, LM Studio, etc.)
and provides environment-aware behavior adjustments.
"""
import os
import logging
import psutil
logger = logging.getLogger(__name__)
def detect_mcp_client():
"""Detect which MCP client is running this server."""
try:
# Get the parent process (the MCP client)
current_process = psutil.Process()
parent = current_process.parent()
if parent:
parent_name = parent.name().lower()
parent_exe = parent.exe() if hasattr(parent, 'exe') else ""
# Check for Claude Desktop
if 'claude' in parent_name or 'claude' in parent_exe.lower():
return 'claude_desktop'
# Check for LM Studio
if 'lmstudio' in parent_name or 'lm-studio' in parent_name or 'lmstudio' in parent_exe.lower():
return 'lm_studio'
# Check command line for additional clues
try:
cmdline = parent.cmdline()
cmdline_str = ' '.join(cmdline).lower()
if 'claude' in cmdline_str:
return 'claude_desktop'
if 'lmstudio' in cmdline_str or 'lm-studio' in cmdline_str:
return 'lm_studio'
except (OSError, IndexError, AttributeError) as e:
logger.debug(f"Could not detect client from process: {e}")
pass
# Fallback: check environment variables
if os.getenv('CLAUDE_DESKTOP'):
return 'claude_desktop'
if os.getenv('LM_STUDIO'):
return 'lm_studio'
# Default to Claude Desktop for strict JSON compliance
return 'claude_desktop'
except Exception:
# If detection fails, default to Claude Desktop (strict mode)
return 'claude_desktop'
# Detect the current MCP client
MCP_CLIENT = detect_mcp_client()
```
--------------------------------------------------------------------------------
/archive/investigations/MACOS_HOOKS_INVESTIGATION.md:
--------------------------------------------------------------------------------
```markdown
# macOS Memory Hooks Investigation
## Issue
Memory awareness hooks may work differently on macOS vs Linux when using MCP protocol.
## Current Linux Behavior (Manjaro)
- **Problem**: Hooks try to spawn duplicate MCP server via `MCPClient(serverCommand)`
- **Symptom**: Connection timeout when hooks execute
- **Root Cause**: Claude Code already has MCP server on stdio, can't have two servers on same streams
- **Current Workaround**: HTTP fallback (requires separate HTTP server on port 8443)
## Hypothesis: macOS May Work Differently
User reports hooks work on macOS without HTTP fallback. Possible reasons:
1. macOS Claude Code may provide hooks access to existing MCP connection
2. Different process/stdio handling on macOS vs Linux
3. `useExistingServer: true` config may actually work on macOS
## Investigation Needed (On MacBook)
### Test 1: MCP-Only Configuration
```json
{
"memoryService": {
"protocol": "mcp",
"preferredProtocol": "mcp",
"mcp": {
"useExistingServer": true,
"serverName": "memory"
}
}
}
```
**Expected on macOS (if hypothesis correct):**
- ✅ Hooks connect successfully
- ✅ No duplicate server spawned
- ✅ Memory context injected on session start
**Expected on Linux (current behavior):**
- ❌ Connection timeout
- ❌ Multiple server processes spawn
- ❌ Fallback to HTTP needed
### Test 2: Check Memory Client Behavior
1. Run hook manually: `node ~/.claude/hooks/core/session-start.js`
2. Check process list: Does it spawn new `memory server` process?
3. Monitor connection: Does it timeout or succeed?
### Test 3: Platform Comparison
```bash
# On macOS
ps aux | grep "memory server" # How many instances?
node ~/.claude/hooks/core/session-start.js # Does it work?
# On Linux (current)
ps aux | grep "memory server" # Multiple instances!
node ~/.claude/hooks/core/session-start.js # Times out!
```
## Files to Check
- `claude-hooks/utilities/memory-client.js` - MCP connection logic
- `claude-hooks/utilities/mcp-client.js` - Server spawning code
- `claude-hooks/install_hooks.py` - Config generation (line 268-273: useExistingServer)
## Next Steps
1. Test on MacBook with MCP-only config
2. If works on macOS: investigate platform-specific differences
3. Document proper cross-platform solution
4. Update hooks to work consistently on both platforms
## Current Status
- **Linux**: Requires HTTP fallback (confirmed working)
- **macOS**: TBD - needs verification
- **Goal**: Understand why different, achieve consistent behavior
---
Created: 2025-09-30
Platform: Linux (Manjaro)
Issue: Hooks/MCP connection conflict
```
--------------------------------------------------------------------------------
/scripts/service/deploy_dual_services.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
echo "🚀 Deploying Dual MCP Services with mDNS..."
echo " - FastMCP Server (port 8000) for Claude Code MCP clients"
echo " - HTTP Dashboard (port 8080) for web interface"
echo " - mDNS enabled for both services"
echo ""
# Stop existing services
echo "⏹️ Stopping existing services..."
sudo systemctl stop mcp-memory 2>/dev/null || true
sudo systemctl stop mcp-http-dashboard 2>/dev/null || true
# Install FastMCP service with mDNS
echo "📝 Installing FastMCP service (port 8000)..."
sudo cp /tmp/fastmcp-server-with-mdns.service /etc/systemd/system/mcp-memory.service
# Install HTTP Dashboard service
echo "📝 Installing HTTP Dashboard service (port 8080)..."
sudo cp /tmp/mcp-http-dashboard.service /etc/systemd/system/mcp-http-dashboard.service
# Reload systemd
echo "🔄 Reloading systemd daemon..."
sudo systemctl daemon-reload
# Enable both services
echo "🔛 Enabling both services for startup..."
sudo systemctl enable mcp-memory
sudo systemctl enable mcp-http-dashboard
# Start FastMCP service first
echo "▶️ Starting FastMCP server (port 8000)..."
sudo systemctl start mcp-memory
sleep 2
# Start HTTP Dashboard service
echo "▶️ Starting HTTP Dashboard (port 8080)..."
sudo systemctl start mcp-http-dashboard
sleep 2
# Check status of both services
echo ""
echo "🔍 Checking service status..."
echo ""
echo "=== FastMCP Server (port 8000) ==="
sudo systemctl status mcp-memory --no-pager
echo ""
echo "=== HTTP Dashboard (port 8080) ==="
sudo systemctl status mcp-http-dashboard --no-pager
echo ""
echo "📊 Port status:"
ss -tlnp | grep -E ":800[08]"
echo ""
echo "🌐 mDNS Services (if avahi is installed):"
avahi-browse -t _http._tcp 2>/dev/null | grep -E "(MCP|Memory)" || echo "No mDNS services found (avahi may not be installed)"
avahi-browse -t _mcp._tcp 2>/dev/null | grep -E "(MCP|Memory)" || echo "No MCP mDNS services found"
echo ""
echo "✅ Dual service deployment complete!"
echo ""
echo "🔗 Available Services:"
echo " - FastMCP Protocol: http://memory.local:8000/mcp (for Claude Code)"
echo " - HTTP Dashboard: http://memory.local:8080/ (for web access)"
echo " - API Endpoints: http://memory.local:8080/api/* (for curl/scripts)"
echo ""
echo "📋 Service Management:"
echo " - FastMCP logs: sudo journalctl -u mcp-memory -f"
echo " - Dashboard logs: sudo journalctl -u mcp-http-dashboard -f"
echo " - Stop FastMCP: sudo systemctl stop mcp-memory"
echo " - Stop Dashboard: sudo systemctl stop mcp-http-dashboard"
echo ""
echo "🔍 mDNS Discovery:"
echo " - Browse services: avahi-browse -t _http._tcp"
echo " - Browse MCP: avahi-browse -t _mcp._tcp"
```
--------------------------------------------------------------------------------
/archive/docs-root-cleanup-2025-08-23/PYTORCH_DOWNLOAD_FIX.md:
--------------------------------------------------------------------------------
```markdown
# PyTorch Download Issue - FIXED! 🎉
## Problem
Claude Desktop was downloading PyTorch models (230MB+) on every startup, even with offline environment variables set in the config.
## Root Cause
The issue was that **UV package manager isolation** prevented environment variables from being properly inherited, and model downloads happened before our offline configuration could take effect.
## Solution Applied
### 1. Created Offline Launcher Script
**File**: `scripts/memory_offline.py`
- Sets offline environment variables **before any imports**
- Configures cache paths for Windows
- Bypasses UV isolation by running Python directly
### 2. Updated Claude Desktop Config
**Your config now uses**:
```json
{
"command": "python",
"args": ["C:/REPOSITORIES/mcp-memory-service/scripts/memory_offline.py"]
}
```
**Instead of**:
```json
{
"command": "uv",
"args": ["--directory", "...", "run", "memory"]
}
```
### 3. Added Code-Level Offline Setup
**File**: `src/mcp_memory_service/__init__.py`
- Added `setup_offline_mode()` function
- Runs immediately when module is imported
- Provides fallback offline configuration
## Test Results ✅
**Before Fix**:
```
2025-08-11T19:04:48.249Z [memory] [info] Message from client: {...}
Downloading torch (230.2MiB) ← PROBLEM
2025-08-11T19:05:48.151Z [memory] [info] Request timed out
```
**After Fix**:
```
Setting up offline mode...
HF_HUB_OFFLINE: 1
HF_HOME: C:\Users\heinrich.krupp\.cache\huggingface
Starting MCP Memory Service in offline mode...
[No download messages] ← FIXED!
```
## Files Modified
1. **Your Claude Desktop Config**: `%APPDATA%\Claude\claude_desktop_config.json`
- Changed from UV to direct Python execution
- Uses new offline launcher script
2. **New Offline Launcher**: `scripts/memory_offline.py`
- Forces offline mode before any ML library imports
- Configures Windows cache paths automatically
3. **Core Module Init**: `src/mcp_memory_service/__init__.py`
- Added offline mode setup as backup
- Runs on module import
4. **Sample Config**: `examples/claude_desktop_config_windows.json`
- Updated for other users
- Uses new launcher approach
## Impact
✅ **No more 230MB PyTorch downloads on startup**
✅ **Faster Claude Desktop initialization**
✅ **Uses existing cached models (434 memories preserved)**
✅ **SQLite-vec backend still working**
## For Other Users
Use the updated `examples/claude_desktop_config_windows.json` template and:
1. Replace `C:/REPOSITORIES/mcp-memory-service` with your path
2. Replace `YOUR_USERNAME` with your Windows username
3. Use `python` command with `scripts/memory_offline.py`
The stubborn PyTorch download issue is now **completely resolved**! 🎉
```
--------------------------------------------------------------------------------
/.github/workflows/CACHE_FIX.md:
--------------------------------------------------------------------------------
```markdown
# Python Cache Configuration Fix
## Issue Identified
**Date**: 2024-08-24
**Problem**: GitHub Actions workflows failing at Python setup step
### Root Cause
The `setup-python` action was configured with `cache: 'pip'` but couldn't find a `requirements.txt` file. The project uses `pyproject.toml` for dependency management instead.
### Error Message
```
Error: No file in /home/runner/work/mcp-memory-service/mcp-memory-service matched to [**/requirements.txt], make sure you have checked out the target repository
```
## Solution Applied
Added `cache-dependency-path: '**/pyproject.toml'` to all Python setup steps that use pip caching.
### Files Modified
#### 1. `.github/workflows/main-optimized.yml`
Fixed 2 instances:
- Line 34-39: Release job Python setup
- Line 112-117: Test job Python setup
#### 2. `.github/workflows/cleanup-images.yml`
Fixed 1 instance:
- Line 95-100: Docker Hub cleanup job Python setup
### Before
```yaml
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
cache: 'pip'
# ❌ Missing cache-dependency-path causes failure
```
### After
```yaml
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
cache: 'pip'
cache-dependency-path: '**/pyproject.toml'
# ✅ Explicitly tells setup-python where to find dependencies
```
## Benefits
1. **Immediate Fix**: Workflows will no longer fail at Python setup step
2. **Performance**: Dependencies are properly cached, reducing workflow execution time
3. **Compatibility**: Works with modern Python projects using `pyproject.toml` (PEP 621)
## Testing
All modified workflows have been validated:
- ✅ `main-optimized.yml` - Valid YAML syntax
- ✅ `cleanup-images.yml` - Valid YAML syntax
## Background
The `setup-python` action defaults to looking for `requirements.txt` when using pip cache. Since this project uses `pyproject.toml` for dependency management (following modern Python packaging standards), we need to explicitly specify the dependency file path.
This is a known issue in the setup-python action:
- Issue #502: Cache pip dependencies from pyproject.toml file
- Issue #529: Change pip default cache path to include pyproject.toml
## Next Steps
After pushing these changes:
1. Workflows should complete successfully
2. Monitor the Python setup steps to confirm caching works
3. Check workflow execution time improvements from proper caching
## Alternative Solutions (Not Applied)
1. **Remove caching**: Simply remove `cache: 'pip'` line (would work but slower)
2. **Create requirements.txt**: Generate from pyproject.toml (adds maintenance burden)
3. **Use uv directly**: Since project uses uv for package management (more complex change)
Date: 2024-08-24
Status: Fixed and ready for deployment
```
--------------------------------------------------------------------------------
/scripts/pr/amp_suggest_fixes.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# scripts/pr/amp_suggest_fixes.sh - Generate fix suggestions using Amp CLI
#
# Usage: bash scripts/pr/amp_suggest_fixes.sh <PR_NUMBER>
# Example: bash scripts/pr/amp_suggest_fixes.sh 215
set -e
PR_NUMBER=$1
if [ -z "$PR_NUMBER" ]; then
echo "Usage: $0 <PR_NUMBER>"
exit 1
fi
if ! command -v gh &> /dev/null; then
echo "Error: GitHub CLI (gh) is not installed"
exit 1
fi
echo "=== Amp CLI Fix Suggestions for PR #$PR_NUMBER ==="
echo ""
# Ensure Amp directories exist
mkdir -p .claude/amp/prompts/pending
mkdir -p .claude/amp/responses/ready
# Get repository
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || echo "doobidoo/mcp-memory-service")
# Fetch review comments
echo "Fetching review comments from PR #$PR_NUMBER..."
review_comments=$(gh api "repos/$REPO/pulls/$PR_NUMBER/comments" | \
jq -r '[.[] | select(.user.login | test("bot|gemini|claude"))] | .[] | "- \(.path):\(.line) - \(.body[0:200])"' | \
head -50)
if [ -z "$review_comments" ]; then
echo "No review comments found."
exit 0
fi
echo "Review Comments:"
echo "$review_comments"
echo ""
# Get PR diff
echo "Fetching PR diff..."
pr_diff=$(gh pr diff $PR_NUMBER | head -500) # Limit to 500 lines to avoid token overflow
# Generate UUID for fix suggestions task
fixes_uuid=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid)
echo "Creating Amp prompt for fix suggestions..."
# Create fix suggestions prompt
cat > .claude/amp/prompts/pending/fixes-${fixes_uuid}.json << EOF
{
"id": "${fixes_uuid}",
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")",
"prompt": "Analyze these code review comments and suggest specific fixes. DO NOT auto-apply changes. Output format: For each issue, provide: 1) File path, 2) Issue description, 3) Suggested fix (code snippet or explanation), 4) Rationale. Focus on safe, non-breaking changes (formatting, type hints, error handling, variable naming, import organization).\n\nReview comments:\n${review_comments}\n\nPR diff (current code):\n${pr_diff}\n\nProvide actionable fix suggestions in markdown format.",
"context": {
"project": "mcp-memory-service",
"task": "fix-suggestions",
"pr_number": "${PR_NUMBER}"
},
"options": {
"timeout": 180000,
"format": "markdown"
}
}
EOF
echo "✅ Created Amp prompt for fix suggestions"
echo ""
echo "=== Run this Amp command ==="
echo "amp @.claude/amp/prompts/pending/fixes-${fixes_uuid}.json"
echo ""
echo "=== Then collect the suggestions ==="
echo "bash scripts/pr/amp_collect_results.sh --timeout 180 --uuids '${fixes_uuid}'"
echo ""
# Save UUID for later collection
echo "${fixes_uuid}" > /tmp/amp_fix_suggestions_uuid_${PR_NUMBER}.txt
echo "UUID saved to /tmp/amp_fix_suggestions_uuid_${PR_NUMBER}.txt for result collection"
```
--------------------------------------------------------------------------------
/docs/mastery/troubleshooting.md:
--------------------------------------------------------------------------------
```markdown
# MCP Memory Service — Troubleshooting Guide
Common issues and proven fixes when running locally or in CI.
## sqlite-vec Extension Loading Fails
Symptoms:
- Errors like: `SQLite extension loading not supported` or `enable_load_extension not available`.
- `Failed to load sqlite-vec extension`.
Causes:
- Python’s `sqlite3` not compiled with loadable extensions (macOS system Python is common culprit).
Fixes:
- macOS:
- `brew install python` and use Homebrew Python.
- Or install via pyenv with extensions: `PYTHON_CONFIGURE_OPTS='--enable-loadable-sqlite-extensions' pyenv install 3.12.x`.
- Linux:
- Install dev headers: `apt install python3-dev sqlite3` and ensure Python was built with `--enable-loadable-sqlite-extensions`.
- Windows:
- Prefer official python.org installer or conda distribution.
- Alternative: switch backend: `export MCP_MEMORY_STORAGE_BACKEND=chromadb` (see migration notes).
## `sentence-transformers`/`torch` Not Available
Symptoms:
- Warnings about no embedding model; semantic search returns empty.
Fixes:
- Install ML deps: `pip install sentence-transformers torch` (or `uv add` equivalents).
- For constrained environments, semantic search can still run once deps are installed; tag-based and metadata operations work without embeddings.
## First-Run Model Downloads
Symptoms:
- Warnings like: `Using TRANSFORMERS_CACHE is deprecated` or `No snapshots directory`.
Status:
- Expected on first run while downloading `all-MiniLM-L6-v2` (~25MB). Subsequent runs use cache.
## Cloudflare Backend Fails on Boot
Symptoms:
- Immediate exit with `Missing required environment variables for Cloudflare backend`.
Fixes:
- Set all required envs: `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_VECTORIZE_INDEX`, `CLOUDFLARE_D1_DATABASE_ID`. Optional: `CLOUDFLARE_R2_BUCKET`.
- Validate resources via Wrangler or dashboard; see `docs/cloudflare-setup.md`.
## Port/Coordination Conflicts
Symptoms:
- Multi-client mode cannot start HTTP server, or falls back to direct mode.
Status/Fixes:
- The server auto-detects: `http_client` (connect), `http_server` (start), else `direct` (WAL). If the coordination port is in use by another service, expect direct fallback; adjust port or stop the conflicting service.
## File Permission or Path Errors
Symptoms:
- Path write tests failing under `BASE_DIR` or backup directories.
Fixes:
- Ensure `MCP_MEMORY_BASE_DIR` points to a writable location; the service validates and creates directories and test-writes `.write_test` files with retries.
## Slow Queries or High CPU
Checklist:
- Ensure embeddings are available and model loaded once (warmup).
- For low RAM or Windows CUDA:
- `PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:128`
- Reduce model cache sizes; see `configure_environment()` in `server.py`.
- Tune SQLite pragmas via `MCP_MEMORY_SQLITE_PRAGMAS`.
```
--------------------------------------------------------------------------------
/scripts/server/check_http_server.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""
Check if the MCP Memory Service HTTP server is running.
This script checks if the HTTP server is accessible and provides
helpful feedback to users about how to start it if it's not running.
"""
import sys
import os
from urllib.request import urlopen, Request
from urllib.error import URLError, HTTPError
import json
import ssl
def check_http_server(verbose: bool = False) -> bool:
"""
Check if the HTTP server is running.
Args:
verbose: If True, print detailed status messages
Returns:
bool: True if server is running, False otherwise
"""
# Determine the endpoint from environment
https_enabled = os.getenv('MCP_HTTPS_ENABLED', 'false').lower() == 'true'
http_port = int(os.getenv('MCP_HTTP_PORT', '8000'))
https_port = int(os.getenv('MCP_HTTPS_PORT', '8443'))
if https_enabled:
endpoint = f"https://localhost:{https_port}/api/health"
else:
endpoint = f"http://localhost:{http_port}/api/health"
try:
# Create SSL context that doesn't verify certificates (for self-signed certs)
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
req = Request(endpoint)
with urlopen(req, timeout=3, context=ctx) as response:
if response.status == 200:
data = json.loads(response.read().decode('utf-8'))
if verbose:
print("[OK] HTTP server is running")
print(f" Version: {data.get('version', 'unknown')}")
print(f" Endpoint: {endpoint}")
print(f" Status: {data.get('status', 'unknown')}")
return True
else:
if verbose:
print(f"[WARN] HTTP server responded with status {response.status}")
return False
except (URLError, HTTPError, json.JSONDecodeError) as e:
if verbose:
print("[ERROR] HTTP server is NOT running")
print(f"\nTo start the HTTP server, run:")
print(f" uv run python scripts/server/run_http_server.py")
print(f"\n Or for HTTPS:")
print(f" MCP_HTTPS_ENABLED=true uv run python scripts/server/run_http_server.py")
print(f"\nError: {str(e)}")
return False
def main():
"""Main entry point for CLI usage."""
import argparse
parser = argparse.ArgumentParser(
description="Check if MCP Memory Service HTTP server is running"
)
parser.add_argument(
"-q", "--quiet",
action="store_true",
help="Only return exit code (0=running, 1=not running), no output."
)
args = parser.parse_args()
is_running = check_http_server(verbose=not args.quiet)
sys.exit(0 if is_running else 1)
if __name__ == "__main__":
main()
```
--------------------------------------------------------------------------------
/claude_commands/memory-ingest.md:
--------------------------------------------------------------------------------
```markdown
# memory-ingest
Ingest a document file into the MCP Memory Service database.
## Usage
```
claude /memory-ingest <file_path> [--tags TAG1,TAG2] [--chunk-size SIZE] [--chunk-overlap OVERLAP] [--memory-type TYPE]
```
## Parameters
- `file_path`: Path to the document file to ingest (required)
- `--tags`: Comma-separated list of tags to apply to all memories created from this document
- `--chunk-size`: Target size for text chunks in characters (default: 1000)
- `--chunk-overlap`: Characters to overlap between chunks (default: 200)
- `--memory-type`: Type label for created memories (default: "document")
## Supported Formats
- PDF files (.pdf)
- Text files (.txt, .md, .markdown, .rst)
- JSON files (.json)
## Implementation
I need to upload the document to the MCP Memory Service HTTP API endpoint and monitor the progress.
First, let me check if the service is running and get the correct endpoint:
```bash
# Check if the service is running on default port
curl -s http://localhost:8080/api/health || echo "Service not running on 8080"
# Or check common alternative ports
curl -s http://localhost:8443/api/health || echo "Service not running on 8443"
```
Assuming the service is running (adjust the URL as needed), I'll upload the document:
```bash
# Upload the document with specified parameters
curl -X POST "http://localhost:8080/api/documents/upload" \\
-F "file=@$FILE_PATH" \\
-F "tags=$TAGS" \\
-F "chunk_size=$CHUNK_SIZE" \\
-F "chunk_overlap=$CHUNK_OVERLAP" \\
-F "memory_type=$MEMORY_TYPE" \\
```
Then I'll monitor the upload progress:
```bash
# Monitor progress (replace UPLOAD_ID with the ID from the upload response)
curl -s "http://localhost:8080/api/documents/status/UPLOAD_ID"
```
## Examples
```
# Ingest a PDF with tags
claude /memory-ingest manual.pdf --tags documentation,reference
# Ingest a markdown file with custom chunking
claude /memory-ingest README.md --chunk-size 1500 --chunk-overlap 300 --tags project,readme
# Ingest a document as reference material
claude /memory-ingest api-docs.json --tags api,reference --memory-type reference
```
## Actual Execution Steps
When you run this command, I will:
1. **Validate the file exists** and check if it's a supported format
2. **Determine the service endpoint** (try localhost:8080, then 8443)
3. **Upload the file** using the documents API endpoint with your specified parameters
4. **Monitor progress** and show real-time updates
5. **Report results** including chunks created and any errors
The document will be automatically parsed, chunked, and stored as searchable memories in your MCP Memory Service database.
## Notes
- The document will be automatically parsed and chunked for optimal retrieval
- Each chunk becomes a separate memory entry with semantic embeddings
- Progress will be displayed during ingestion
- Failed chunks will be reported but won't stop the overall process
```
--------------------------------------------------------------------------------
/archive/docs-removed-2025-08-23/development/mcp-milestone.md:
--------------------------------------------------------------------------------
```markdown
# MCP Memory Service v4.0.0-beta.1 - Major Milestone Achievement
**Date**: August 4, 2025
**Status**: 🚀 **Mission Accomplished**
## Project Evolution Complete
Successfully transitioned MCP Memory Service from experimental local-only service to **production-ready remote memory infrastructure** with native MCP protocol support.
## Technical Achievements
### 1. Release Management ✅
- **v4.0.0-beta.1** beta release completed
- Fixed Docker CI/CD workflows (main.yml and publish-and-test.yml)
- GitHub Release created with comprehensive notes
- Repository cleanup (3 obsolete branches removed)
### 2. GitHub Issues Resolved ✅
- **Issue #71**: Remote Memory Service access - **FULLY RESOLVED** via FastAPI MCP integration
- **Issue #72**: Node.js Bridge SSL issues - **SUPERSEDED** (bridge deprecated in favor of native protocol)
### 3. MCP Protocol Compliance ✅
Applied critical refactorings from fellow AI Coder:
- **Flexible ID Validation**: `Optional[Union[str, int]]` supporting both string and integer IDs
- **Dual Route Handling**: Both `/mcp` and `/mcp/` endpoints to prevent 307 redirects
- **Content Hash Generation**: Proper `generate_content_hash()` implementation
### 4. Infrastructure Deployment ✅
- **Remote Server**: Successfully deployed at `your-server-ip:8000`
- **Backend**: SQLite-vec (1.7MB database, 384-dimensional embeddings)
- **Model**: all-MiniLM-L6-v2 loaded and operational
- **Existing Data**: 65 memories already stored
- **API Coverage**: Full MCP protocol + REST API + Dashboard
## Strategic Impact
This represents the **successful completion of architectural evolution** from:
- ❌ Local-only experimental service
- ✅ Production-ready remote memory infrastructure
**Key Benefits Achieved**:
1. **Cross-Device Access**: Claude Code can connect from any device
2. **Protocol Compliance**: Standard MCP JSON-RPC 2.0 implementation
3. **Scalable Architecture**: Dual-service design (HTTP + MCP)
4. **Robust CI/CD**: Automated testing and deployment pipeline
## Verification
**MCP Protocol Test Results**:
```bash
# Health check successful
curl -X POST http://your-server-ip:8000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"check_database_health"}}'
# Response: {"status":"healthy","statistics":{"total_memories":65,"embedding_model":"all-MiniLM-L6-v2"}}
```
**Available Endpoints**:
- 🔧 **MCP Protocol**: `http://your-server-ip:8000/mcp`
- 📊 **Dashboard**: `http://your-server-ip:8000/`
- 📚 **API Docs**: `http://your-server-ip:8000/api/docs`
## Next Steps
- Monitor beta feedback for v4.0.0 stable release
- Continue remote memory service operation
- Support Claude Code integrations across devices
---
**This milestone marks the successful transformation of MCP Memory Service into a fully operational, remotely accessible, protocol-compliant memory infrastructure ready for production use.** 🎉
```
--------------------------------------------------------------------------------
/pyproject-lite.toml:
--------------------------------------------------------------------------------
```toml
[build-system]
requires = ["hatchling", "python-semantic-release", "build"]
build-backend = "hatchling.build"
[project]
name = "mcp-memory-service-lite"
version = "8.76.0"
description = "Lightweight MCP memory service with ONNX embeddings - no PyTorch required. 80% smaller install size."
readme = "README.md"
requires-python = ">=3.10"
keywords = [
"mcp", "model-context-protocol", "claude-desktop", "semantic-memory",
"vector-database", "ai-assistant", "sqlite-vec", "multi-client",
"semantic-search", "memory-consolidation", "ai-productivity", "vs-code",
"cursor", "continue", "fastapi", "developer-tools", "cross-platform",
"lightweight", "onnx"
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Topic :: Database :: Database Engines/Servers",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Operating System :: OS Independent",
"Environment :: Console",
"Framework :: FastAPI"
]
authors = [
{ name = "Heinrich Krupp", email = "[email protected]" }
]
maintainers = [
{ name = "Sundeep G", email = "[email protected]" }
]
license = { text = "Apache-2.0" }
dependencies = [
"tokenizers==0.20.3",
"mcp>=1.8.0,<2.0.0",
"python-dotenv>=1.0.0",
"sqlite-vec>=0.1.0",
"build>=0.10.0",
"aiohttp>=3.8.0",
"fastapi>=0.115.0",
"uvicorn>=0.30.0",
"python-multipart>=0.0.9",
"sse-starlette>=2.1.0",
"aiofiles>=23.2.1",
"psutil>=5.9.0",
"zeroconf>=0.130.0",
"pypdf2>=3.0.0",
"chardet>=5.0.0",
"click>=8.0.0",
"httpx>=0.24.0",
"authlib>=1.2.0",
"python-jose[cryptography]>=3.3.0",
"onnxruntime>=1.14.1",
"typing-extensions>=4.0.0; python_version < '3.11'",
"apscheduler>=3.11.0",
]
[project.optional-dependencies]
# Machine learning dependencies for full torch-based embeddings
ml = [
"sentence-transformers>=2.2.2",
"torch>=2.0.0"
]
# Full installation (lite + ml)
full = [
"mcp-memory-service-lite[ml]"
]
[project.scripts]
memory = "mcp_memory_service.cli.main:main"
memory-server = "mcp_memory_service.cli.main:memory_server_main"
mcp-memory-server = "mcp_memory_service.mcp_server:main"
[project.urls]
Homepage = "https://github.com/doobidoo/mcp-memory-service"
Documentation = "https://github.com/doobidoo/mcp-memory-service#readme"
Repository = "https://github.com/doobidoo/mcp-memory-service"
Issues = "https://github.com/doobidoo/mcp-memory-service/issues"
[tool.hatch.build.targets.wheel]
packages = ["src/mcp_memory_service"]
[tool.hatch.version]
path = "src/mcp_memory_service/__init__.py"
```
--------------------------------------------------------------------------------
/scripts/maintenance/memory-types.md:
--------------------------------------------------------------------------------
```markdown
# Memory Type Taxonomy (Updated Nov 2025)
Database consolidated from 342 fragmented types to 128 organized types. Use these **24 core types** for all new memories.
## Content Types
- `note` - General notes, observations, summaries
- `reference` - Reference materials, knowledge base entries
- `document` - Formal documents, code snippets
- `guide` - How-to guides, tutorials, troubleshooting guides
## Activity Types
- `session` - Work sessions, development sessions
- `implementation` - Implementation work, integrations
- `analysis` - Analysis, reports, investigations
- `troubleshooting` - Problem-solving, debugging
- `test` - Testing activities, validation
## Artifact Types
- `fix` - Bug fixes, corrections
- `feature` - New features, enhancements
- `release` - Releases, release notes
- `deployment` - Deployments, deployment records
## Progress Types
- `milestone` - Milestones, completions, achievements
- `status` - Status updates, progress reports
## Infrastructure Types
- `configuration` - Configurations, setups, settings
- `infrastructure` - Infrastructure changes, system updates
- `process` - Processes, workflows, procedures
- `security` - Security-related memories
- `architecture` - Architecture decisions, design patterns
## Other Types
- `documentation` - Documentation artifacts
- `solution` - Solutions, resolutions
- `achievement` - Accomplishments, successes
## Usage Guidelines
### Avoid Creating New Type Variations
**DON'T** create variations like:
- `bug-fix`, `bugfix`, `technical-fix` → Use `fix`
- `technical-solution`, `project-solution` → Use `solution`
- `project-implementation` → Use `implementation`
- `technical-note` → Use `note`
### Avoid Redundant Prefixes
Remove unnecessary qualifiers:
- `project-*` → Use base type
- `technical-*` → Use base type
- `development-*` → Use base type
### Cleanup Commands
```bash
# Preview type consolidation
python scripts/maintenance/consolidate_memory_types.py --dry-run
# Execute type consolidation
python scripts/maintenance/consolidate_memory_types.py
# Check type distribution
python scripts/maintenance/check_memory_types.py
# Assign types to untyped memories
python scripts/maintenance/assign_memory_types.py --dry-run
python scripts/maintenance/assign_memory_types.py
```
## Consolidation Rules
The consolidation script applies these transformations:
1. **Fix variants** → `fix`: bug-fix, bugfix, technical-fix, etc.
2. **Implementation variants** → `implementation`: integrations, project-implementation, etc.
3. **Solution variants** → `solution`: technical-solution, project-solution, etc.
4. **Note variants** → `note`: technical-note, development-note, etc.
5. **Remove redundant prefixes**: project-, technical-, development-
## Benefits of Standardization
- Improved search and retrieval accuracy
- Better tag-based filtering
- Reduced database fragmentation
- Easier memory type analytics
- Consistent memory organization
```
--------------------------------------------------------------------------------
/tests/test_semantic_search.py:
--------------------------------------------------------------------------------
```python
"""
MCP Memory Service
Copyright (c) 2024 Heinrich Krupp
Licensed under the MIT License. See LICENSE file in the project root for full license text.
"""
"""
Test semantic search functionality of the MCP Memory Service.
"""
import pytest
import pytest_asyncio
import asyncio
from mcp_memory_service.server import MemoryServer
@pytest_asyncio.fixture
async def memory_server():
"""Create a test instance of the memory server."""
server = MemoryServer()
# MemoryServer initializes itself, no initialize() call needed
yield server
# No cleanup needed
@pytest.mark.asyncio
async def test_semantic_similarity(memory_server):
"""Test semantic similarity scoring."""
# Store related memories
memories = [
"The quick brown fox jumps over the lazy dog",
"A fast auburn fox leaps above a sleepy canine",
"A cat chases a mouse"
]
for memory in memories:
await memory_server.store_memory(content=memory)
# Test semantic retrieval
query = "swift red fox jumping over sleeping dog"
results = await memory_server.debug_retrieve(
query=query,
n_results=2,
similarity_threshold=0.0 # Get all results with scores
)
# First two results should be the fox-related memories
assert len(results) >= 2
assert all("fox" in result for result in results[:2])
@pytest.mark.asyncio
async def test_similarity_threshold(memory_server):
"""Test similarity threshold filtering."""
await memory_server.store_memory(
content="Python is a programming language"
)
# This query is semantically unrelated
results = await memory_server.debug_retrieve(
query="Recipe for chocolate cake",
similarity_threshold=0.8
)
assert len(results) == 0 # No results above threshold
@pytest.mark.asyncio
async def test_exact_match(memory_server):
"""Test exact match retrieval."""
test_content = "This is an exact match test"
await memory_server.store_memory(content=test_content)
results = await memory_server.exact_match_retrieve(
content=test_content
)
assert len(results) == 1
assert results[0] == test_content
@pytest.mark.asyncio
async def test_semantic_ordering(memory_server):
"""Test that results are ordered by semantic similarity."""
# Store memories with varying relevance
memories = [
"Machine learning is a subset of artificial intelligence",
"Deep learning uses neural networks",
"A bicycle has two wheels"
]
for memory in memories:
await memory_server.store_memory(content=memory)
query = "What is AI and machine learning?"
results = await memory_server.debug_retrieve(
query=query,
n_results=3,
similarity_threshold=0.0
)
# Check ordering
assert "machine learning" in results[0].lower()
assert "bicycle" not in results[0].lower()
```
--------------------------------------------------------------------------------
/tools/docker/test-docker-modes.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# Test script to verify both Docker modes work correctly
set -e
echo "==================================="
echo "Docker Setup Test Script"
echo "==================================="
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
if [ $1 -eq 0 ]; then
echo -e "${GREEN}✓${NC} $2"
else
echo -e "${RED}✗${NC} $2"
return 1
fi
}
# Change to docker directory
cd "$(dirname "$0")"
echo ""
echo "1. Building Docker image..."
docker-compose build --quiet
print_status $? "Docker image built successfully"
echo ""
echo "2. Testing MCP Protocol Mode..."
echo " Starting container in MCP mode..."
docker-compose up -d
sleep 5
# Check if container is running
docker-compose ps | grep -q "Up"
print_status $? "MCP mode container is running"
# Check logs for correct mode
docker-compose logs 2>&1 | grep -q "Running in mcp mode"
print_status $? "Container started in MCP mode"
# Stop MCP mode
docker-compose down
echo ""
echo "3. Testing HTTP API Mode..."
echo " Starting container in HTTP mode..."
docker-compose -f docker-compose.http.yml up -d
sleep 10
# Check if container is running
docker-compose -f docker-compose.http.yml ps | grep -q "Up"
print_status $? "HTTP mode container is running"
# Check logs for Uvicorn
docker-compose -f docker-compose.http.yml logs 2>&1 | grep -q "Uvicorn\|FastAPI\|HTTP"
print_status $? "HTTP server started (Uvicorn/FastAPI)"
# Test health endpoint
HTTP_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/api/health 2>/dev/null || echo "000")
if [ "$HTTP_RESPONSE" = "200" ]; then
print_status 0 "Health endpoint responding (HTTP $HTTP_RESPONSE)"
else
print_status 1 "Health endpoint not responding (HTTP $HTTP_RESPONSE)"
fi
# Test with API key
API_TEST=$(curl -s -X POST http://localhost:8000/api/memories \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-secure-api-key-here" \
-d '{"content": "Docker test memory", "tags": ["test"]}' 2>/dev/null | grep -q "success\|unauthorized" && echo "ok" || echo "fail")
if [ "$API_TEST" = "ok" ]; then
print_status 0 "API endpoint accessible"
else
print_status 1 "API endpoint not accessible"
fi
# Stop HTTP mode
docker-compose -f docker-compose.http.yml down
echo ""
echo "==================================="
echo "Test Summary:"
echo "==================================="
echo -e "${GREEN}✓${NC} All critical fixes from Joe applied:"
echo " - PYTHONPATH=/app/src"
echo " - run_server.py copied"
echo " - Embedding models pre-downloaded"
echo ""
echo -e "${GREEN}✓${NC} Simplified Docker structure:"
echo " - Unified entrypoint for both modes"
echo " - Clear MCP vs HTTP separation"
echo " - Single Dockerfile for all modes"
echo ""
echo -e "${YELLOW}Note:${NC} Deprecated files marked in DEPRECATED.md"
echo ""
echo "Docker setup is ready for use!"
```
--------------------------------------------------------------------------------
/scripts/server/preload_models.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""
Pre-load sentence-transformers models to avoid startup delays.
This script downloads and caches the default embedding models used by
MCP Memory Service so they don't need to be downloaded during server startup,
which can cause timeout errors in Claude Desktop.
"""
import sys
import os
def preload_sentence_transformers():
"""Pre-load the default sentence-transformers model."""
try:
print("[INFO] Pre-loading sentence-transformers models...")
from sentence_transformers import SentenceTransformer
# Default model used by the memory service
model_name = "all-MiniLM-L6-v2"
print(f"[INFO] Downloading and caching model: {model_name}")
model = SentenceTransformer(model_name)
print(f"[OK] Model loaded successfully on device: {model.device}")
# Test the model to ensure it works
print("[INFO] Testing model functionality...")
test_text = "This is a test sentence for embedding."
embedding = model.encode(test_text)
print(f"[OK] Model test successful - embedding shape: {embedding.shape}")
return True
except ImportError:
print("[WARNING] sentence-transformers not available - skipping model preload")
return False
except Exception as e:
print(f"[ERROR] Error preloading model: {e}")
return False
def check_cache_status():
"""Check if models are already cached."""
cache_locations = [
os.path.expanduser("~/.cache/huggingface/hub"),
os.path.expanduser("~/.cache/torch/sentence_transformers"),
]
for cache_dir in cache_locations:
if os.path.exists(cache_dir):
try:
contents = os.listdir(cache_dir)
for item in contents:
if 'sentence-transformers' in item.lower() or 'minilm' in item.lower():
print(f"[OK] Found cached model: {item}")
return True
except (OSError, PermissionError):
continue
print("[INFO] No cached models found")
return False
def main():
print("MCP Memory Service - Model Preloader")
print("=" * 50)
# Check current cache status
print("\n[1] Checking cache status...")
models_cached = check_cache_status()
if models_cached:
print("[OK] Models are already cached - no download needed")
return True
# Preload models
print("\n[2] Preloading models...")
success = preload_sentence_transformers()
if success:
print("\n[OK] Model preloading complete!")
print("[INFO] MCP Memory Service should now start without downloading models")
else:
print("\n[WARNING] Model preloading failed - server may need to download during startup")
return success
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)
```
--------------------------------------------------------------------------------
/docs/mastery/testing-guide.md:
--------------------------------------------------------------------------------
```markdown
# MCP Memory Service — Testing Guide
This guide explains how to run, understand, and extend the test suites.
## Prerequisites
- Python ≥ 3.10 (3.12 recommended; 3.13 may lack prebuilt `sqlite-vec` wheels).
- Install dependencies (uv recommended):
- `uv sync` (respects `pyproject.toml` and `uv.lock`), or
- `pip install -e .` plus extras as needed.
- For SQLite-vec tests:
- `sqlite-vec` and `sentence-transformers`/`torch` should be installed.
- On some OS/Python combinations, sqlite extension loading must be supported (see Troubleshooting).
## Test Layout
- `tests/README.md`: overview.
- Categories:
- Unit: `tests/unit/` (e.g., tags, mdns, cloudflare stubs).
- Integration: `tests/integration/` (cross-component flows).
- Performance: `tests/performance/`.
- Backend-specific: top-level tests like `test_sqlite_vec_storage.py`, `test_time_parser.py`, `test_memory_ops.py`.
## Running Tests
Run all:
```
pytest
```
Category:
```
pytest tests/unit/
pytest tests/integration/
pytest tests/performance/
```
Single file or test:
```
pytest tests/test_sqlite_vec_storage.py::TestSqliteVecStorage::test_store_memory -q
```
With uv:
```
uv run pytest -q
```
## Important Behaviors and Skips
- SQLite-vec tests are marked to skip when `sqlite-vec` is unavailable:
- See `pytestmark = pytest.mark.skipif(not SQLITE_VEC_AVAILABLE, ...)` in `tests/test_sqlite_vec_storage.py`.
- Some tests simulate no-embedding scenarios by patching `SENTENCE_TRANSFORMERS_AVAILABLE=False` to validate fallback code paths.
- Temp directories isolate database files; connections are closed in teardown.
## Coverage of Key Areas
- Storage CRUD and vector search (`test_sqlite_vec_storage.py`).
- Time parsing and timestamp recall (`test_time_parser.py`, `test_timestamp_recall.py`).
- Tag and metadata semantics (`test_tag_storage.py`, `unit/test_tags.py`).
- Health checks and database init (`test_database.py`).
- Cloudflare adapters have unit-level coverage stubbing network (`unit/test_cloudflare_storage.py`).
## Writing New Tests
- Prefer async `pytest.mark.asyncio` for storage APIs.
- Use `tempfile.mkdtemp()` for per-test DB paths.
- Use `src.mcp_memory_service.models.memory.Memory` and `generate_content_hash` helpers.
- For backend-specific behavior, keep tests colocated with backend tests and gate with availability flags.
- For MCP tool surface tests, prefer FastMCP server (`mcp_server.py`) in isolated processes or with `lifespan` context.
## Local MCP/Service Tests
Run stdio server:
```
uv run memory server
```
Run FastMCP HTTP server:
```
uv run mcp-memory-server
```
Use any MCP client (Claude Desktop/Code) and exercise tools: store, retrieve, search_by_tag, delete, health.
## Debugging and Logs
- Set `LOG_LEVEL=INFO` for more verbosity.
- For Claude Desktop: stdout is suppressed to preserve JSON; inspect stderr/warnings. LM Studio prints diagnostics to stdout.
- Common sqlite-vec errors print actionable remediation (see Troubleshooting).
```
--------------------------------------------------------------------------------
/scripts/service/install_http_service.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# Install MCP Memory HTTP Service for systemd
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
SERVICE_FILE="$SCRIPT_DIR/mcp-memory-http.service"
SERVICE_NAME="mcp-memory-http.service"
echo "MCP Memory HTTP Service Installation"
echo "===================================="
echo ""
# Check if service file exists
if [ ! -f "$SERVICE_FILE" ]; then
echo "❌ Service file not found: $SERVICE_FILE"
exit 1
fi
# Check if .env exists
if [ ! -f "$PROJECT_DIR/.env" ]; then
echo "❌ .env file not found: $PROJECT_DIR/.env"
echo "Please create .env file with your configuration"
exit 1
fi
# Check if venv exists
if [ ! -d "$PROJECT_DIR/venv" ]; then
echo "❌ Virtual environment not found: $PROJECT_DIR/venv"
echo "Please run: python -m venv venv && source venv/bin/activate && pip install -e ."
exit 1
fi
# Install as user service (recommended) or system service
echo "Installation Options:"
echo "1. User service (recommended) - runs as your user, no sudo needed"
echo "2. System service - runs at boot, requires sudo"
read -p "Select [1/2]: " choice
case $choice in
1)
# User service
SERVICE_DIR="$HOME/.config/systemd/user"
mkdir -p "$SERVICE_DIR"
echo "Installing user service to: $SERVICE_DIR/$SERVICE_NAME"
cp "$SERVICE_FILE" "$SERVICE_DIR/$SERVICE_NAME"
# Reload systemd
systemctl --user daemon-reload
echo ""
echo "✅ Service installed successfully!"
echo ""
echo "To start the service:"
echo " systemctl --user start $SERVICE_NAME"
echo ""
echo "To enable auto-start on login:"
echo " systemctl --user enable $SERVICE_NAME"
echo " loginctl enable-linger $USER # Required for auto-start"
echo ""
echo "To check status:"
echo " systemctl --user status $SERVICE_NAME"
echo ""
echo "To view logs:"
echo " journalctl --user -u $SERVICE_NAME -f"
;;
2)
# System service
if [ "$EUID" -ne 0 ]; then
echo "❌ System service installation requires sudo"
echo "Please run: sudo $0"
exit 1
fi
SERVICE_DIR="/etc/systemd/system"
echo "Installing system service to: $SERVICE_DIR/$SERVICE_NAME"
cp "$SERVICE_FILE" "$SERVICE_DIR/$SERVICE_NAME"
# Reload systemd
systemctl daemon-reload
echo ""
echo "✅ Service installed successfully!"
echo ""
echo "To start the service:"
echo " sudo systemctl start $SERVICE_NAME"
echo ""
echo "To enable auto-start on boot:"
echo " sudo systemctl enable $SERVICE_NAME"
echo ""
echo "To check status:"
echo " sudo systemctl status $SERVICE_NAME"
echo ""
echo "To view logs:"
echo " sudo journalctl -u $SERVICE_NAME -f"
;;
*)
echo "❌ Invalid choice"
exit 1
;;
esac
```
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
```markdown
# Pull Request
## Description
<!-- Provide a clear and concise description of the changes -->
## Motivation
<!-- Explain why these changes are needed and what problem they solve -->
## Type of Change
<!-- Check all that apply -->
- [ ] 🐛 Bug fix (non-breaking change that fixes an issue)
- [ ] ✨ New feature (non-breaking change that adds functionality)
- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] 📝 Documentation update
- [ ] 🧪 Test improvement
- [ ] ♻️ Code refactoring (no functional changes)
- [ ] ⚡ Performance improvement
- [ ] 🔧 Configuration change
- [ ] 🎨 UI/UX improvement
## Changes
<!-- List the specific changes made in this PR -->
-
-
-
**Breaking Changes** (if any):
<!-- Describe any breaking changes and migration steps -->
-
## Testing
### How Has This Been Tested?
<!-- Describe the tests you ran to verify your changes -->
- [ ] Unit tests
- [ ] Integration tests
- [ ] Manual testing
- [ ] MCP Inspector validation
**Test Configuration**:
- Python version:
- OS:
- Storage backend:
- Installation method:
### Test Coverage
<!-- Describe the test coverage added or modified -->
- [ ] Added new tests
- [ ] Updated existing tests
- [ ] Test coverage maintained/improved
## Related Issues
<!-- Link related issues using keywords: Fixes #123, Closes #456, Relates to #789 -->
Fixes #
Closes #
Relates to #
## Screenshots
<!-- If applicable, add screenshots to help explain your changes -->
## Documentation
<!-- Check all that apply -->
- [ ] Updated README.md
- [ ] Updated CLAUDE.md
- [ ] Updated AGENTS.md
- [ ] Updated CHANGELOG.md
- [ ] Updated Wiki pages
- [ ] Updated code comments/docstrings
- [ ] Added API documentation
- [ ] No documentation needed
## Pre-submission Checklist
<!-- Check all boxes before submitting -->
- [ ] ✅ My code follows the project's coding standards (PEP 8, type hints)
- [ ] ✅ I have performed a self-review of my code
- [ ] ✅ I have commented my code, particularly in hard-to-understand areas
- [ ] ✅ I have made corresponding changes to the documentation
- [ ] ✅ My changes generate no new warnings
- [ ] ✅ I have added tests that prove my fix is effective or that my feature works
- [ ] ✅ New and existing unit tests pass locally with my changes
- [ ] ✅ Any dependent changes have been merged and published
- [ ] ✅ I have updated CHANGELOG.md following [Keep a Changelog](https://keepachangelog.com/) format
- [ ] ✅ I have checked that no sensitive data is exposed (API keys, tokens, passwords)
- [ ] ✅ I have verified this works with all supported storage backends (if applicable)
## Additional Notes
<!-- Any additional information, context, or notes for reviewers -->
---
**For Reviewers**:
- Review checklist: See [PR Review Guide](https://github.com/doobidoo/mcp-memory-service/wiki/PR-Review-Guide)
- Consider testing with Gemini Code Assist for comprehensive review
- Verify CHANGELOG.md entry is present and correctly formatted
- Check documentation accuracy and completeness
```
--------------------------------------------------------------------------------
/.github/workflows/WORKFLOW_FIXES.md:
--------------------------------------------------------------------------------
```markdown
# Workflow Fixes Applied
## Issues Identified and Fixed
### 1. Cleanup Images Workflow (`cleanup-images.yml`)
**Issues:**
- Referenced non-existent workflows in `workflow_run` trigger
- Used incorrect action versions (`@v5` instead of `@v4`)
- Incorrect account type (`org` instead of `personal`)
- Missing error handling for optional steps
- No validation for Docker Hub credentials
**Fixes Applied:**
- Updated workflow references to match actual workflow names
- Downgraded action versions to stable versions (`@v4`, `@v1`)
- Changed account type to `personal` for personal GitHub account
- Added `continue-on-error: true` for optional cleanup steps
- Added credential validation and conditional Docker Hub cleanup
- Added informative messages when cleanup is skipped
### 2. Main Optimized Workflow (`main-optimized.yml`)
**Issues:**
- Complex matrix strategy with indirect secret access
- No handling for missing Docker Hub credentials
- Potential authentication failures for Docker registries
**Fixes Applied:**
- Simplified login steps with explicit registry conditions
- Added conditional Docker Hub login based on credential availability
- Added skip message when Docker Hub credentials are missing
- Improved error handling for registry authentication
## Changes Made
### cleanup-images.yml
```yaml
# Before
workflow_run:
workflows: ["Release (Tags) - Optimized", "Main CI/CD Pipeline - Optimized"]
uses: actions/delete-package-versions@v5
account-type: org
# After
workflow_run:
workflows: ["Main CI/CD Pipeline", "Docker Publish (Tags)", "Publish and Test (Tags)"]
uses: actions/delete-package-versions@v4
account-type: personal
continue-on-error: true
```
### main-optimized.yml
```yaml
# Before
username: ${{ matrix.username_secret == '_github_actor' && github.actor || secrets[matrix.username_secret] }}
# After
- name: Log in to Docker Hub
if: matrix.registry == 'docker.io' && secrets.DOCKER_USERNAME && secrets.DOCKER_PASSWORD
- name: Log in to GitHub Container Registry
if: matrix.registry == 'ghcr.io'
```
## Safety Improvements
1. **Graceful Degradation**: Workflows now continue even if optional steps fail
2. **Credential Validation**: Proper checking for required secrets before use
3. **Clear Messaging**: Users are informed when steps are skipped
4. **Error Isolation**: Failures in one cleanup job don't affect others
## Testing Recommendations
1. **Manual Trigger Test**: Test cleanup workflow with dry-run mode
2. **Credential Scenarios**: Test with and without Docker Hub credentials
3. **Registry Cleanup**: Verify GHCR cleanup works independently
4. **Workflow Dependencies**: Ensure workflow triggers work correctly
## Expected Behavior
- **With Full Credentials**: Both GHCR and Docker Hub cleanup run
- **Without Docker Credentials**: Only GHCR cleanup runs, Docker Hub skipped
- **Action Failures**: Individual cleanup steps may fail but workflow continues
- **No Images to Clean**: Workflows complete successfully with no actions
Date: 2024-08-24
Status: Applied and ready for testing
```
--------------------------------------------------------------------------------
/scripts/sync/claude_sync_commands.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
# Copyright 2024 Heinrich Krupp
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Claude command wrapper for memory sync operations.
Provides convenient commands for managing dual memory backends.
"""
import sys
import asyncio
import subprocess
from pathlib import Path
SYNC_SCRIPT = Path(__file__).parent / "sync_memory_backends.py"
def run_sync_command(args):
"""Run the sync script with given arguments."""
cmd = [sys.executable, str(SYNC_SCRIPT)] + args
result = subprocess.run(cmd, capture_output=True, text=True)
if result.stdout:
print(result.stdout.strip())
if result.stderr:
print(result.stderr.strip(), file=sys.stderr)
return result.returncode
def memory_sync_status():
"""Show memory sync status."""
return run_sync_command(['--status'])
def memory_sync_backup():
"""Backup Cloudflare memories to SQLite-vec."""
print("Backing up Cloudflare memories to SQLite-vec...")
return run_sync_command(['--direction', 'cf-to-sqlite'])
def memory_sync_restore():
"""Restore SQLite-vec memories to Cloudflare."""
print("Restoring SQLite-vec memories to Cloudflare...")
return run_sync_command(['--direction', 'sqlite-to-cf'])
def memory_sync_bidirectional():
"""Perform bidirectional sync."""
print("Performing bidirectional sync...")
return run_sync_command(['--direction', 'bidirectional'])
def memory_sync_dry_run():
"""Show what would be synced without making changes."""
print("Dry run - showing what would be synced:")
return run_sync_command(['--dry-run'])
def show_usage():
"""Show usage information."""
print("Usage: python claude_sync_commands.py <command>")
print("Commands:")
print(" status - Show sync status")
print(" backup - Backup Cloudflare → SQLite-vec")
print(" restore - Restore SQLite-vec → Cloudflare")
print(" sync - Bidirectional sync")
print(" dry-run - Show what would be synced")
if __name__ == "__main__":
# Dictionary-based command dispatch for better scalability
commands = {
"status": memory_sync_status,
"backup": memory_sync_backup,
"restore": memory_sync_restore,
"sync": memory_sync_bidirectional,
"dry-run": memory_sync_dry_run,
}
if len(sys.argv) < 2:
show_usage()
sys.exit(1)
command = sys.argv[1]
if command in commands:
sys.exit(commands[command]())
else:
print(f"Unknown command: {command}")
show_usage()
sys.exit(1)
```
--------------------------------------------------------------------------------
/scripts/utils/memory_wrapper_uv.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""
UV-specific memory wrapper for MCP Memory Service
This wrapper is specifically designed for UV-based installations.
"""
import os
import sys
import subprocess
import traceback
# Set environment variables for better cross-platform compatibility
os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"
def print_info(text):
"""Print formatted info text."""
print(f"[INFO] {text}", file=sys.stderr, flush=True)
def print_error(text):
"""Print formatted error text."""
print(f"[ERROR] {text}", file=sys.stderr, flush=True)
def print_success(text):
"""Print formatted success text."""
print(f"[SUCCESS] {text}", file=sys.stderr, flush=True)
def main():
"""Main entry point for UV-based memory service."""
print_info("Starting MCP Memory Service with UV...")
# Set ChromaDB path if provided via environment variables
if "MCP_MEMORY_CHROMA_PATH" in os.environ:
print_info(f"Using ChromaDB path: {os.environ['MCP_MEMORY_CHROMA_PATH']}")
# Set backups path if provided via environment variables
if "MCP_MEMORY_BACKUPS_PATH" in os.environ:
print_info(f"Using backups path: {os.environ['MCP_MEMORY_BACKUPS_PATH']}")
try:
# Use UV to run the memory service
cmd = [sys.executable, '-m', 'uv', 'run', 'memory']
cmd.extend(sys.argv[1:]) # Pass through any additional arguments
print_info(f"Running command: {' '.join(cmd)}")
# Execute the command
result = subprocess.run(cmd, check=True)
sys.exit(result.returncode)
except subprocess.SubprocessError as e:
print_error(f"UV run failed: {e}")
print_info("Falling back to direct module execution...")
# Fallback to direct execution
try:
# Add the source directory to path
script_dir = os.path.dirname(os.path.abspath(__file__))
src_dir = os.path.join(script_dir, "src")
if os.path.exists(src_dir):
sys.path.insert(0, src_dir)
# Import and run the server
from mcp_memory_service.server import main as server_main
server_main()
except ImportError as import_error:
print_error(f"Failed to import memory service: {import_error}")
sys.exit(1)
except Exception as fallback_error:
print_error(f"Fallback execution failed: {fallback_error}")
traceback.print_exc(file=sys.stderr)
sys.exit(1)
except Exception as e:
print_error(f"Error running memory service: {e}")
traceback.print_exc(file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print_info("Shutting down gracefully...")
sys.exit(0)
except Exception as e:
print_error(f"Unhandled exception: {e}")
traceback.print_exc(file=sys.stderr)
sys.exit(1)
```
--------------------------------------------------------------------------------
/scripts/maintenance/find_all_duplicates.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""Find all near-duplicate memories across the database."""
import sqlite3
from pathlib import Path
from collections import defaultdict
import hashlib
import platform
# Platform-specific database path
if platform.system() == "Darwin": # macOS
DB_PATH = Path.home() / "Library/Application Support/mcp-memory/sqlite_vec.db"
else: # Linux/Windows
DB_PATH = Path.home() / ".local/share/mcp-memory/sqlite_vec.db"
def normalize_content(content):
"""Normalize content by removing timestamps and session-specific data."""
# Remove common timestamp patterns
import re
normalized = content
normalized = re.sub(r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z', 'TIMESTAMP', normalized)
normalized = re.sub(r'\*\*Date\*\*: \d{2,4}[./]\d{2}[./]\d{2,4}', '**Date**: DATE', normalized)
normalized = re.sub(r'Timestamp: \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}', 'Timestamp: TIMESTAMP', normalized)
return normalized.strip()
def content_hash(content):
"""Create a hash of normalized content."""
normalized = normalize_content(content)
return hashlib.md5(normalized.encode()).hexdigest()
def main():
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
print("Analyzing memories for duplicates...")
cursor.execute("SELECT content_hash, content, tags, created_at FROM memories ORDER BY created_at DESC")
memories = cursor.fetchall()
print(f"Total memories: {len(memories)}")
# Group by normalized content
content_groups = defaultdict(list)
for mem_hash, content, tags, created_at in memories:
norm_hash = content_hash(content)
content_groups[norm_hash].append({
'hash': mem_hash,
'content': content[:200], # First 200 chars
'tags': tags,
'created_at': created_at
})
# Find duplicates (groups with >1 memory)
duplicates = {k: v for k, v in content_groups.items() if len(v) > 1}
if not duplicates:
print("✅ No duplicates found!")
conn.close()
return
print(f"\n❌ Found {len(duplicates)} groups of duplicates:")
total_duplicate_count = 0
for i, (norm_hash, group) in enumerate(duplicates.items(), 1):
count = len(group)
total_duplicate_count += count - 1 # Keep one, delete rest
print(f"\n{i}. Group with {count} duplicates:")
print(f" Content preview: {group[0]['content'][:100]}...")
print(f" Tags: {group[0]['tags'][:80]}...")
print(f" Hashes to keep: {group[0]['hash'][:16]}... (newest)")
print(f" Hashes to delete: {count-1} older duplicates")
if i >= 10: # Show only first 10 groups
remaining = len(duplicates) - 10
print(f"\n... and {remaining} more duplicate groups")
break
print(f"\n📊 Summary:")
print(f" Total duplicate groups: {len(duplicates)}")
print(f" Total memories to delete: {total_duplicate_count}")
print(f" Total memories after cleanup: {len(memories) - total_duplicate_count}")
conn.close()
if __name__ == "__main__":
main()
```
--------------------------------------------------------------------------------
/.claude/directives/refactoring-checklist.md:
--------------------------------------------------------------------------------
```markdown
# Refactoring Safety Checklist
## ⚠️ MANDATORY for All Code Moves/Extractions
When extracting, moving, or refactoring code, follow this checklist to avoid production issues.
**Learned from**: Issues #299 (import errors), #300 (response format mismatch)
---
## 1. ✅ Import Path Validation
**Problem**: Relative imports break when code moves (`..services` → `...services`)
**Checklist**:
- [ ] Validate relative imports from new location
- [ ] Run `bash scripts/ci/validate_imports.sh` before commit
- [ ] Test actual imports (no mocks allowed for validation)
**Why**: 82% of import errors are undetected until production
---
## 2. ✅ Response Format Compatibility
**Problem**: Handler expects `result["message"]` but service returns `result["success"]`
**Checklist**:
- [ ] Handler matches service response keys (`success`/`error`, not `message`)
- [ ] Test both success AND error paths
- [ ] Check for KeyError risks in all code paths
**Why**: Response format mismatches cause runtime crashes
---
## 3. ✅ Integration Tests for ALL Extracted Functions
**Problem**: 82% of handlers had zero integration tests (3/17 tested)
**Checklist**:
- [ ] Create integration tests BEFORE committing refactoring
- [ ] 100% handler coverage required (17/17 handlers)
- [ ] Run `python scripts/validation/check_handler_coverage.py`
**Why**: Unit tests alone don't catch integration issues
---
## 4. ✅ Coverage Validation
**Problem**: Refactoring can inadvertently reduce test coverage
**Checklist**:
- [ ] Run `pytest --cov=src/mcp_memory_service --cov-fail-under=80`
- [ ] Coverage must not decrease (delta ≥ 0%)
- [ ] Add tests for new code before committing
**Why**: Coverage gate prevents untested code from merging
---
## 5. ✅ Pre-Commit Validation
**Run these commands before EVERY refactoring commit:**
```bash
# 1. Import validation
bash scripts/ci/validate_imports.sh
# 2. Handler coverage check
python scripts/validation/check_handler_coverage.py
# 3. Coverage gate
pytest tests/ --cov=src --cov-fail-under=80
```
**All must pass** before git commit.
---
## 6. ✅ Commit Strategy
**Problem**: Batching multiple extractions makes errors hard to trace
**Checklist**:
- [ ] Commit incrementally (one extraction per commit)
- [ ] Each commit has passing tests + coverage ≥80%
- [ ] Never batch multiple extractions in one commit
**Why**: Incremental commits = easy rollback if issues found
---
## Quick Command Reference
```bash
# Full pre-refactoring validation
bash scripts/ci/validate_imports.sh && \
python scripts/validation/check_handler_coverage.py && \
pytest tests/ --cov=src --cov-fail-under=80
# If all pass → safe to commit
git commit -m "refactor: extracted X function"
```
---
## Historical Context
**Issue #299**: Import error `..services` → `...services` undetected until production
**Issue #300**: Response format mismatch `result["message"]` vs `result["success"]`
**Root Cause**: 82% of handlers had zero integration tests (3/17 tested)
**Solution**: 9-check pre-PR validation + 100% handler coverage requirement
**Prevention is better than debugging in production.**
```
--------------------------------------------------------------------------------
/.github/workflows/publish-dual.yml:
--------------------------------------------------------------------------------
```yaml
name: Publish Dual Distribution (Main + Lite)
# This workflow publishes both mcp-memory-service (full) and mcp-memory-service-lite (lightweight)
# Both packages share the same codebase but have different dependencies
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version to publish (e.g., 8.75.1)'
required: true
type: string
jobs:
publish-main:
name: Publish Main Package (with PyTorch)
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build hatchling twine
- name: Build main package
run: |
echo "Building mcp-memory-service (full version with PyTorch)"
python -m build
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
run: |
python -m twine upload dist/* --skip-existing
publish-lite:
name: Publish Lite Package (ONNX only)
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build hatchling twine
- name: Prepare lite package
run: |
echo "Preparing mcp-memory-service-lite (lightweight ONNX version)"
cp pyproject.toml pyproject-main.toml
cp pyproject-lite.toml pyproject.toml
- name: Build lite package
run: |
python -m build
- name: Publish lite to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
run: |
python -m twine upload dist/* --skip-existing
- name: Clean build artifacts
run: rm -rf dist/ build/ *.egg-info
- name: Restore original pyproject.toml
run: |
mv pyproject-main.toml pyproject.toml
verify-packages:
name: Verify Both Packages
runs-on: ubuntu-latest
needs: [publish-main, publish-lite]
steps:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Wait for PyPI to update
run: sleep 60
- name: Test main package install
run: |
python -m venv /tmp/test-main
/tmp/test-main/bin/pip install mcp-memory-service
/tmp/test-main/bin/python -c "import mcp_memory_service; print('Main package OK')"
- name: Test lite package install
run: |
python -m venv /tmp/test-lite
/tmp/test-lite/bin/pip install mcp-memory-service-lite
/tmp/test-lite/bin/python -c "import mcp_memory_service; print('Lite package OK')"
```
--------------------------------------------------------------------------------
/docs/integrations/gemini.md:
--------------------------------------------------------------------------------
```markdown
# Gemini Context: MCP Memory Service
## Project Overview
This project is a sophisticated and feature-rich MCP (Memory Component Protocol) server designed to provide a persistent, semantic memory layer for AI assistants, particularly "Claude Desktop". It's built with Python and leverages a variety of technologies to deliver a robust and performant memory service.
The core of the project is the `MemoryServer` class, which handles all MCP tool calls. It features a "dream-inspired" memory consolidation system that autonomously organizes and compresses memories over time. The server is built on top of FastAPI, providing a modern and asynchronous API.
The project offers two distinct storage backends, allowing users to choose the best fit for their needs:
* **ChromaDB:** A feature-rich vector database that provides advanced search capabilities and is well-suited for large memory collections.
* **SQLite-vec:** A lightweight, file-based backend that uses the `sqlite-vec` extension for vector similarity search. This is a great option for resource-constrained environments.
The project also includes a comprehensive suite of scripts for installation, testing, and maintenance, as well as detailed documentation.
## Building and Running
### Installation
The project uses a custom installer that intelligently detects the user's hardware and selects the optimal configuration. To install the project, run the following commands:
```bash
# Clone the repository
git clone https://github.com/doobidoo/mcp-memory-service.git
cd mcp-memory-service
# Create and activate a virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Run the intelligent installer
python install.py
```
### Running the Server
The server can be run in several ways, depending on the desired configuration. The primary entry point is the `mcp_memory_service.server:main` script, which can be executed as a Python module:
```bash
python -m mcp_memory_service.server
```
Alternatively, the `pyproject.toml` file defines a `memory` script that can be used to run the server:
```bash
memory
```
The server can also be run as a FastAPI application using `uvicorn`:
```bash
uvicorn mcp_memory_service.server:app --host 0.0.0.0 --port 8000
```
### Testing
The project includes a comprehensive test suite that can be run using `pytest`:
```bash
pytest tests/
```
## Development Conventions
* **Python 3.10+:** The project requires Python 3.10 or higher.
* **Type Hinting:** The codebase uses type hints extensively to improve code clarity and maintainability.
* **Async/Await:** The project uses the `async/await` pattern for all I/O operations to ensure high performance and scalability.
* **PEP 8:** The code follows the PEP 8 style guide.
* **Dataclasses:** The project uses dataclasses for data models to reduce boilerplate code.
* **Docstrings:** All modules and functions have triple-quoted docstrings that explain their purpose, arguments, and return values.
* **Testing:** All new features should be accompanied by tests to ensure they work as expected and don't introduce regressions.
```
--------------------------------------------------------------------------------
/scripts/quality/check_test_scores.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""Check actual scores for test cases to calibrate expectations."""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))
from mcp_memory_service.quality.onnx_ranker import ONNXRankerModel
def main():
print("Initializing DeBERTa model...")
model = ONNXRankerModel(model_name="nvidia-quality-classifier-deberta", device="cpu")
# Test cases from test_deberta_absolute_quality_scoring
print("\n" + "="*80)
print("TEST 1: test_deberta_absolute_quality_scoring")
print("="*80)
high_quality_1 = "Implement caching layer for API responses with Redis backend. Use TTL of 1 hour for user data."
high_quality_2 = "Fix bug in user authentication flow. Added proper session validation and error handling."
low_quality = "TODO: check this"
score1 = model.score_quality("", high_quality_1)
score2 = model.score_quality("", high_quality_2)
score3 = model.score_quality("", low_quality)
print(f"High quality 1: {score1:.4f} (expected ≥0.6)")
print(f"High quality 2: {score2:.4f} (expected ≥0.6)")
print(f"Low quality: {score3:.4f} (expected <0.4)")
# Test cases from test_deberta_3class_output_mapping
print("\n" + "="*80)
print("TEST 2: test_deberta_3class_output_mapping")
print("="*80)
excellent = "The implementation uses a sophisticated multi-tier architecture with semantic analysis, pattern matching, and adaptive learning algorithms to optimize retrieval accuracy."
average = "The code does some processing and returns a result."
poor = "stuff things maybe later TODO"
score_excellent = model.score_quality("", excellent)
score_average = model.score_quality("", average)
score_poor = model.score_quality("", poor)
print(f"Excellent: {score_excellent:.4f}")
print(f"Average: {score_average:.4f}")
print(f"Poor: {score_poor:.4f}")
print(f"Range: {max(score_excellent, score_average, score_poor) - min(score_excellent, score_average, score_poor):.4f} (expected >0.2)")
print(f"Ordered correctly: {score_excellent > score_average > score_poor}")
# Additional realistic test cases
print("\n" + "="*80)
print("ADDITIONAL TESTS: Realistic memory content")
print("="*80)
tests = [
("Configured CI/CD pipeline with GitHub Actions. Set up automated testing, linting, and deployment to production on merge to main branch. Added branch protection rules.", "DevOps implementation"),
("Refactored authentication module to use JWT tokens instead of session cookies. Implemented refresh token rotation and secure token storage in httpOnly cookies.", "Security improvement"),
("Updated README with installation instructions", "Documentation update"),
("Meeting notes: discussed project timeline", "Generic notes"),
("TODO", "Minimal content"),
("test", "Single word"),
]
for content, label in tests:
score = model.score_quality("", content)
print(f"{score:.4f} - {label}")
print(f" Content: {content[:60]}...")
if __name__ == "__main__":
main()
```
--------------------------------------------------------------------------------
/src/mcp_memory_service/server/logging_config.py:
--------------------------------------------------------------------------------
```python
# Copyright 2024 Heinrich Krupp
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Logging configuration module for MCP Memory Service.
Provides client-aware logging that adjusts output behavior based on MCP client type.
Claude Desktop requires strict JSON mode (stderr only), while LM Studio supports
dual-stream output (stdout for INFO/DEBUG, stderr for WARNING+).
"""
import sys
import os
import logging
from .client_detection import MCP_CLIENT
# Custom logging handler that routes INFO/DEBUG to stdout, WARNING/ERROR to stderr
class DualStreamHandler(logging.Handler):
"""Client-aware handler that adjusts logging behavior based on MCP client."""
def __init__(self, client_type='claude_desktop'):
super().__init__()
self.client_type = client_type
self.stdout_handler = logging.StreamHandler(sys.stdout)
self.stderr_handler = logging.StreamHandler(sys.stderr)
# Set the same formatter for both handlers
formatter = logging.Formatter('%(levelname)s:%(name)s:%(message)s')
self.stdout_handler.setFormatter(formatter)
self.stderr_handler.setFormatter(formatter)
def emit(self, record):
"""Route log records based on client type and level."""
# For Claude Desktop: strict JSON mode - suppress most output, route everything to stderr
if self.client_type == 'claude_desktop':
# Only emit WARNING and above to stderr to maintain JSON protocol
if record.levelno >= logging.WARNING:
self.stderr_handler.emit(record)
# Suppress INFO/DEBUG for Claude Desktop to prevent JSON parsing errors
return
# For LM Studio: enhanced mode with dual-stream
if record.levelno >= logging.WARNING: # WARNING, ERROR, CRITICAL
self.stderr_handler.emit(record)
else: # DEBUG, INFO
self.stdout_handler.emit(record)
def configure_logging():
"""Configure root logger with client-aware handler."""
# Configure logging with client-aware handler BEFORE any imports that use logging
log_level = os.getenv('LOG_LEVEL', 'WARNING').upper() # Default to WARNING for performance
root_logger = logging.getLogger()
root_logger.setLevel(getattr(logging, log_level, logging.WARNING))
# Remove any existing handlers to avoid duplicates
for handler in root_logger.handlers[:]:
root_logger.removeHandler(handler)
# Add our custom client-aware handler
client_aware_handler = DualStreamHandler(client_type=MCP_CLIENT)
root_logger.addHandler(client_aware_handler)
return logging.getLogger(__name__)
# Auto-configure on import
logger = configure_logging()
```
--------------------------------------------------------------------------------
/src/mcp_memory_service/web/api/events.py:
--------------------------------------------------------------------------------
```python
"""
Server-Sent Events endpoints for real-time updates.
"""
from fastapi import APIRouter, Request, Depends
from pydantic import BaseModel
from typing import Dict, Any, List, TYPE_CHECKING
from ...config import OAUTH_ENABLED
from ..sse import create_event_stream, sse_manager
from ..dependencies import get_storage
# OAuth authentication imports (conditional)
if OAUTH_ENABLED or TYPE_CHECKING:
from ..oauth.middleware import require_read_access, AuthenticationResult
else:
# Provide type stubs when OAuth is disabled
AuthenticationResult = None
require_read_access = None
router = APIRouter()
class ConnectionInfo(BaseModel):
"""Individual connection information."""
connection_id: str
client_ip: str
user_agent: str
connected_duration_seconds: float
last_heartbeat_seconds_ago: float
class SSEStatsResponse(BaseModel):
"""Response model for SSE connection statistics."""
total_connections: int
heartbeat_interval: int
connections: List[ConnectionInfo]
@router.get("/events")
async def events_endpoint(
request: Request,
user: AuthenticationResult = Depends(require_read_access) if OAUTH_ENABLED else None
):
"""
Server-Sent Events endpoint for real-time updates.
Provides a continuous stream of events including:
- memory_stored: When new memories are added
- memory_deleted: When memories are removed
- search_completed: When searches finish
- health_update: System status changes
- heartbeat: Periodic keep-alive signals
- connection_established: Welcome message
"""
return await create_event_stream(request)
@router.get("/events/stats")
async def get_sse_stats(
user: AuthenticationResult = Depends(require_read_access) if OAUTH_ENABLED else None
):
"""
Get statistics about current SSE connections.
Returns information about active connections, connection duration,
and heartbeat status.
"""
try:
# Get raw stats first to debug the structure
stats = sse_manager.get_connection_stats()
# Validate structure and transform if needed
connections = []
for conn_data in stats.get('connections', []):
connections.append({
"connection_id": conn_data.get("connection_id", "unknown"),
"client_ip": conn_data.get("client_ip", "unknown"),
"user_agent": conn_data.get("user_agent", "unknown"),
"connected_duration_seconds": conn_data.get("connected_duration_seconds", 0.0),
"last_heartbeat_seconds_ago": conn_data.get("last_heartbeat_seconds_ago", 0.0)
})
return {
"total_connections": stats.get("total_connections", 0),
"heartbeat_interval": stats.get("heartbeat_interval", 30),
"connections": connections
}
except Exception as e:
import logging
logging.getLogger(__name__).error(f"Error getting SSE stats: {str(e)}")
# Return safe default stats if there's an error
return {
"total_connections": 0,
"heartbeat_interval": 30,
"connections": []
}
```
--------------------------------------------------------------------------------
/start_http_debug.bat:
--------------------------------------------------------------------------------
```
@echo off
REM MCP Memory Service HTTP Debug Mode Startup Script
REM This script starts the MCP Memory Service in HTTP mode for debugging and testing
echo ========================================
echo MCP Memory Service HTTP Debug Mode
echo Using uv for dependency management
echo ========================================
REM Check if uv is available
uv --version >nul 2>&1
if %errorlevel% neq 0 (
echo ERROR: uv is not installed or not in PATH
echo Please install uv: https://docs.astral.sh/uv/getting-started/installation/
pause
exit /b 1
)
echo uv version:
uv --version
REM Install dependencies using uv sync (recommended)
echo.
echo Installing dependencies...
echo This may take a few minutes on first run...
echo Installing core dependencies...
uv sync
REM Check if installation was successful
if %errorlevel% neq 0 (
echo ERROR: Failed to install dependencies
echo Please check the error messages above
pause
exit /b 1
)
echo Dependencies installed successfully!
REM Verify Python can import the service
echo.
echo Verifying installation...
python -c "import sys; sys.path.insert(0, 'src'); import mcp_memory_service; print('✓ MCP Memory Service imported successfully')"
if %errorlevel% neq 0 (
echo ERROR: Failed to import MCP Memory Service
echo Please check the error messages above
pause
exit /b 1
)
REM Set environment variables for HTTP mode
set MCP_MEMORY_STORAGE_BACKEND=sqlite_vec
set MCP_HTTP_ENABLED=true
set MCP_HTTP_PORT=8000
set MCP_HTTPS_ENABLED=false
set MCP_MDNS_ENABLED=true
set MCP_MDNS_SERVICE_NAME=MCP-Memory-Service-Debug
REM Fix Transformers cache warning
set HF_HOME=%USERPROFILE%\.cache\huggingface
set TRANSFORMERS_CACHE=%USERPROFILE%\.cache\huggingface\transformers
REM Optional: Set API key for security
REM To use authentication, set your own API key in the environment variable:
REM set MCP_API_KEY=your-secure-api-key-here
REM Or pass it when running this script: set MCP_API_KEY=mykey && start_http_debug.bat
if "%MCP_API_KEY%"=="" (
echo WARNING: No API key set. Running without authentication.
echo To enable auth, set MCP_API_KEY environment variable.
)
REM Optional: Enable debug logging
set MCP_DEBUG=true
echo Configuration:
echo Storage Backend: %MCP_MEMORY_STORAGE_BACKEND%
echo HTTP Port: %MCP_HTTP_PORT%
echo HTTPS Enabled: %MCP_HTTPS_ENABLED%
echo mDNS Enabled: %MCP_MDNS_ENABLED%
echo Service Name: %MCP_MDNS_SERVICE_NAME%
if "%MCP_API_KEY%"=="" (
echo API Key Set: No ^(WARNING: No authentication^)
) else (
echo API Key Set: Yes
)
echo Debug Mode: %MCP_DEBUG%
echo.
echo Service will be available at:
echo HTTP: http://localhost:%MCP_HTTP_PORT%
echo API: http://localhost:%MCP_HTTP_PORT%/api
echo Health: http://localhost:%MCP_HTTP_PORT%/api/health
echo Dashboard: http://localhost:%MCP_HTTP_PORT%/dashboard
echo.
echo Press Ctrl+C to stop the service
echo.
echo ========================================
echo Starting MCP Memory Service...
echo ========================================
REM Start the service using Python directly (required for HTTP mode)
echo Starting service with Python...
echo Note: Using Python directly for HTTP server mode
uv run python run_server.py
```
--------------------------------------------------------------------------------
/scripts/pr/amp_detect_breaking_changes.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# scripts/pr/amp_detect_breaking_changes.sh - Detect breaking API changes using Amp CLI
#
# Usage: bash scripts/pr/amp_detect_breaking_changes.sh <BASE_BRANCH> <HEAD_BRANCH>
# Example: bash scripts/pr/amp_detect_breaking_changes.sh main feature/new-api
set -e
BASE_BRANCH=${1:-main}
HEAD_BRANCH=${2:-$(git branch --show-current)}
echo "=== Amp CLI Breaking Change Detection ==="
echo "Base Branch: $BASE_BRANCH"
echo "Head Branch: $HEAD_BRANCH"
echo ""
# Ensure Amp directories exist
mkdir -p .claude/amp/prompts/pending
mkdir -p .claude/amp/responses/ready
# Get API-related file changes
echo "Analyzing API changes..."
api_changes=$(git diff origin/$BASE_BRANCH...origin/$HEAD_BRANCH -- \
src/mcp_memory_service/tools.py \
src/mcp_memory_service/web/api/ \
2>/dev/null || echo "")
if [ -z "$api_changes" ]; then
echo "✅ No API changes detected"
exit 0
fi
echo "API changes detected ($(echo "$api_changes" | wc -l) lines)"
echo ""
# Generate UUID for breaking change analysis
breaking_uuid=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid)
echo "Creating Amp prompt for breaking change analysis..."
# Truncate large diffs to avoid token overflow
api_changes_truncated=$(echo "$api_changes" | head -300)
# Create breaking change analysis prompt
cat > .claude/amp/prompts/pending/breaking-${breaking_uuid}.json << EOF
{
"id": "${breaking_uuid}",
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")",
"prompt": "Analyze these API changes for breaking changes. A breaking change is:\n- Removed function/method/endpoint\n- Changed function signature (parameters removed/reordered)\n- Changed return type in incompatible way\n- Renamed public API\n- Changed HTTP endpoint path/method\n- Changed MCP tool schema (added required parameters, removed optional parameters, changed parameter types)\n\nReport ONLY breaking changes with severity (CRITICAL/HIGH/MEDIUM). If no breaking changes, respond: 'BREAKING_CHANGES_NONE'.\n\nOutput format:\nSeverity: [CRITICAL|HIGH|MEDIUM]\nType: [removal|signature-change|rename|schema-change]\nLocation: [file:function/endpoint]\nDetails: [explanation]\nMigration: [suggested migration path]\n\nAPI Changes:\n${api_changes_truncated}",
"context": {
"project": "mcp-memory-service",
"task": "breaking-change-detection",
"base_branch": "${BASE_BRANCH}",
"head_branch": "${HEAD_BRANCH}"
},
"options": {
"timeout": 120000,
"format": "text"
}
}
EOF
echo "✅ Created Amp prompt for breaking change analysis"
echo ""
echo "=== Run this Amp command ==="
echo "amp @.claude/amp/prompts/pending/breaking-${breaking_uuid}.json"
echo ""
echo "=== Then collect the analysis ==="
echo "bash scripts/pr/amp_collect_results.sh --timeout 120 --uuids '${breaking_uuid}'"
echo ""
# Alternative: Direct analysis with custom result handler
echo "=== Or use this one-liner for immediate analysis ==="
echo "(amp @.claude/amp/prompts/pending/breaking-${breaking_uuid}.json > /tmp/amp-breaking.log 2>&1); sleep 5 && bash scripts/pr/amp_analyze_breaking_changes.sh '${breaking_uuid}'"
echo ""
# Save UUID for later collection
echo "${breaking_uuid}" > /tmp/amp_breaking_changes_uuid.txt
echo "UUID saved to /tmp/amp_breaking_changes_uuid.txt"
```
--------------------------------------------------------------------------------
/docs/HOOK_IMPROVEMENTS.md:
--------------------------------------------------------------------------------
```markdown
# Claude Code Session Hook Improvements
## Overview
Enhanced the session start hook to prioritize recent memories and provide better context awareness for Claude Code sessions.
## Key Improvements Made
### 1. Multi-Phase Memory Retrieval
- **Phase 1**: Recent memories (last week) - 60% of available slots
- **Phase 2**: Important tagged memories (architecture, decisions) - remaining slots
- **Phase 3**: Fallback to general project context if needed
### 2. Enhanced Recency Prioritization
- Recent memories get higher priority in initial search
- Time-based indicators: 🕒 today, 📅 this week, regular dates for older
- Configurable time windows (`last-week`, `last-2-weeks`, `last-month`)
### 3. Better Memory Categorization
- New "Recent Work" category for memories from last 7 days
- Improved categorization: Recent → Decisions → Architecture → Insights → Features → Context
- Visual indicators for recency in CLI output
### 4. Enhanced Semantic Queries
- Git context integration (branch, recent commits)
- Framework and language context in queries
- User message context when available
### 5. Improved Configuration
```json
{
"memoryService": {
"recentFirstMode": true, // Enable multi-phase retrieval
"recentMemoryRatio": 0.6, // 60% for recent memories
"recentTimeWindow": "last-week", // Time window for recent search
"fallbackTimeWindow": "last-month" // Fallback time window
},
"output": {
"showMemoryDetails": true, // Show detailed memory info
"showRecencyInfo": true, // Show recency indicators
"showPhaseDetails": true // Show search phase details
}
}
```
### 6. Better Visual Feedback
- Phase-by-phase search reporting
- Recency indicators in memory display
- Enhanced scoring display with time flags
- Better deduplication reporting
## Expected Impact
### Before
- Single query for all memories
- No recency prioritization
- Limited context in queries
- Basic categorization
- Truncated output
### After
- Multi-phase approach prioritizing recent memories
- Smart time-based retrieval
- Git and framework-aware queries
- Enhanced categorization with "Recent Work"
- Full context display with recency indicators
## Usage
The improvements are **backward compatible** - existing installations will automatically use the enhanced system. To disable, set:
```json
{
"memoryService": {
"recentFirstMode": false
}
}
```
## Files Modified
1. `claude-hooks/core/session-start.js` - Multi-phase retrieval logic
2. `claude-hooks/utilities/context-formatter.js` - Enhanced display and categorization
3. `claude-hooks/config.json` - New configuration options
4. `test-hook.js` - Test script for validation
## Testing
Run `node test-hook.js` to test the enhanced hook with mock context. The test demonstrates:
- Project detection and context building
- Multi-phase memory retrieval
- Enhanced categorization and display
- Git context integration
- Configurable time windows
## Result
Session hooks now provide more relevant, recent context while maintaining access to important historical decisions and architecture information. Users get better continuity with their recent work while preserving long-term project memory.
```
--------------------------------------------------------------------------------
/docs/LIGHTWEIGHT_ONNX_SETUP.md:
--------------------------------------------------------------------------------
```markdown
# MCP Memory Service - Portable Multi-Machine Setup
**Author:** Sundeepg98
**Purpose:** Quickly replicate optimized MCP memory setup on any machine
---
## Quick Setup (One Command)
```bash
# Install from YOUR fork with ONNX patches
pipx install "git+https://github.com/Sundeepg98/mcp-memory-service.git"
```
---
## Step-by-Step Setup
### 1. Install from Fork
```bash
# Install the patched version from your fork
pipx install "git+https://github.com/Sundeepg98/mcp-memory-service.git"
# Verify installation
pipx list | grep mcp-memory
```
### 2. Add to Claude Code Settings
Add to `~/.claude/settings.json` in the `mcpServers` section:
```json
{
"mcpServers": {
"memory": {
"type": "stdio",
"command": "~/.local/share/pipx/venvs/mcp-memory-service/bin/python",
"args": ["-m", "mcp_memory_service.server"],
"env": {
"MCP_MEMORY_STORAGE_BACKEND": "sqlite_vec",
"MCP_QUALITY_BOOST_ENABLED": "true"
}
}
}
}
```
### 3. Add Environment Variables
Add to `~/.claude/settings.json` in the `env` section:
```json
{
"env": {
"MCP_MEMORY_STORAGE_BACKEND": "sqlite_vec",
"MCP_MEMORY_USE_ONNX": "true",
"MCP_QUALITY_BOOST_ENABLED": "true",
"MCP_CONSOLIDATION_ENABLED": "true",
"MCP_DECAY_ENABLED": "true",
"MCP_CLUSTERING_ENABLED": "true"
}
}
```
---
## Automated Setup Script
Save this as `setup-mcp-memory.sh`:
```bash
#!/bin/bash
# MCP Memory Service - Automated Setup
# Installs from Sundeepg98's fork with ONNX patches
set -e
echo "🔧 Installing MCP Memory Service from fork..."
pipx install "git+https://github.com/Sundeepg98/mcp-memory-service.git" --force
echo "📁 Creating data directory..."
mkdir -p ~/.local/share/mcp-memory
echo "✅ Installation complete!"
echo ""
echo "Next steps:"
echo "1. Add MCP server config to ~/.claude/settings.json (see mcp-memory-portable-setup.md)"
echo "2. Restart Claude Code"
echo ""
echo "ONNX models will auto-download on first use (~255MB)"
```
---
## What Gets Created
| Location | Content | Per-Machine? |
|----------|---------|--------------|
| `~/.local/share/pipx/venvs/mcp-memory-service/` | Patched code | Same across machines |
| `~/.local/share/mcp-memory/sqlite_vec.db` | Your memories | Different per machine |
| `~/.cache/mcp_memory/onnx_models/` | AI models (255MB) | Auto-downloaded |
---
## Benefits of This Setup
- **90% smaller** than transformers+PyTorch install (805MB vs 7.7GB)
- **Quality scoring** works with ONNX Runtime only
- **Your patches** included (no waiting for upstream merge)
- **One command** to replicate on any machine
---
## Updating
```bash
# Update to latest from your fork
pipx upgrade mcp-memory-service --pip-args="--upgrade"
# Or reinstall fresh
pipx uninstall mcp-memory-service
pipx install "git+https://github.com/Sundeepg98/mcp-memory-service.git"
```
---
## Syncing Memories Between Machines
Your memories (`sqlite_vec.db`) are per-machine. To sync:
```bash
# Option 1: Copy database file
scp ~/.local/share/mcp-memory/sqlite_vec.db user@other-machine:~/.local/share/mcp-memory/
# Option 2: Use hybrid backend with Cloudflare (cloud sync)
# Set MCP_MEMORY_STORAGE_BACKEND=hybrid and configure Cloudflare
```
---
*Last updated: 2026-01-09*
```
--------------------------------------------------------------------------------
/claude_commands/session-start.md:
--------------------------------------------------------------------------------
```markdown
# Display Session Memory Context
Run the session-start memory awareness hook manually to display relevant memories, project context, and git analysis.
## What this does:
Executes the session-start.js hook to:
1. **Load Project Context**: Detect current project and framework
2. **Analyze Git History**: Review recent commits and changes
3. **Retrieve Relevant Memories**: Find memories related to current project
4. **Display Memory Context**: Show categorized memories:
- 🔥 Recent Work
- ⚠️ Current Problems
- 📋 Additional Context
## Usage:
```bash
claude /session-start
```
## Windows Compatibility:
This command is specifically designed as a **Windows workaround** for the SessionStart hook bug (#160).
On Windows, SessionStart hooks cause Claude Code to hang indefinitely. This slash command provides the same functionality but can be triggered manually when you start a new session.
**Works on all platforms**: Windows, macOS, Linux
## When to use:
- At the start of each coding session
- When switching projects or contexts
- After compacting conversations to refresh memory context
- When you need to see what memories are available
## What you'll see:
```
🧠 Memory Hook → Initializing session awareness...
📂 Project: mcp-memory-service
💾 Storage: sqlite-vec (Connected) • 1968 memories • 15.37MB
📊 Git Context → 10 commits, 3 changelog entries
📚 Memory Search → Found 4 relevant memories (2 recent)
┌─ 🧠 Injected Memory Context → mcp-memory-service, FastAPI, Python
│
├─ 🔥 Recent Work:
│ ├─ MCP Memory Service v8.6... 📅 6d ago
│ └─ Session Summary - mcp-memory-service... 📅 6d ago
│
├─ ⚠️ Current Problems:
│ └─ Dream-Inspired Memory Consolidation... 📅 Oct 22
│
└─ 📋 Additional Context:
└─ MCP Memory Service v8.5... 📅 Oct 22
```
## Alternative: Automatic Mid-Conversation Hook
Your UserPromptSubmit hook already runs automatically and retrieves memories when appropriate patterns are detected. This command is for when you want to **explicitly see** the memory context at session start.
## Technical Details:
- Runs: `node ~/.claude/hooks/core/session-start.js`
- HTTP endpoint: http://127.0.0.1:8000
- Protocol: HTTP (MCP fallback if HTTP unavailable)
- Performance: <2 seconds typical execution time
## Troubleshooting:
### Command not found
- Ensure hooks are installed: `ls ~/.claude/hooks/core/session-start.js`
- Reinstall: `cd claude-hooks && python install_hooks.py --basic`
### No memories displayed
- Check HTTP server is running: `curl http://127.0.0.1:8000/api/health`
- Verify hooks config: `cat ~/.claude/hooks/config.json`
- Check endpoint matches: Should be `http://127.0.0.1:8000`
### Error: Cannot find module
- **Windows**: Ensure path is quoted properly in hooks config
- Check Node.js installed: `node --version`
- Verify hook file exists at expected location
## Related:
- **GitHub Issue**: [#160 - Windows SessionStart hook bug](https://github.com/doobidoo/mcp-memory-service/issues/160)
- **Technical Analysis**: `claude-hooks/WINDOWS-SESSIONSTART-BUG.md`
- **Hook Documentation**: `claude-hooks/README.md`
---
**For Windows Users**: This is the **recommended workaround** for session initialization until the SessionStart hook bug is fixed in Claude Code core.
```