#
tokens: 48930/50000 17/625 files (page 11/47)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 11 of 47. Use http://codebase.md/doobidoo/mcp-memory-service?lines=true&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
│   ├── settings.local.json.backup
│   └── settings.local.json.local
├── .commit-message
├── .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-code-review.yml
│       ├── claude.yml
│       ├── cleanup-images.yml.disabled
│       ├── dev-setup-validation.yml
│       ├── docker-publish.yml
│       ├── LATEST_FIXES.md
│       ├── main-optimized.yml.disabled
│       ├── main.yml
│       ├── publish-and-test.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
├── .pyscn
│   ├── .gitignore
│   └── reports
│       └── analyze_20251123_214224.html
├── AGENTS.md
├── 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
│   │   ├── memory-retrieval.js
│   │   ├── mid-conversation.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-NATURAL-TRIGGERS.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-session-tracking.json
│   │   └── test-threading.json
│   ├── utilities
│   │   ├── adaptive-pattern-detector.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-tracker.js
│   │   ├── tiered-conversation-monitor.js
│   │   └── version-checker.js
│   └── WINDOWS-SESSIONSTART-BUG.md
├── CLAUDE.md
├── CODE_OF_CONDUCT.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
│   │   ├── 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
│   ├── 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-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
│   │   └── tag-schema.json
│   ├── 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
│   │   ├── 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
│   ├── 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
│   ├── 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
│   ├── natural-memory-triggers
│   │   ├── cli-reference.md
│   │   ├── installation-guide.md
│   │   └── performance-optimization.md
│   ├── oauth-setup.md
│   ├── pr-graphql-integration.md
│   ├── quick-setup-cloudflare-dual-environment.md
│   ├── README.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
│   │   ├── general.md
│   │   ├── hooks-quick-reference.md
│   │   ├── pr162-schema-caching-issue.md
│   │   ├── session-end-hooks.md
│   │   └── sync-issues.md
│   └── tutorials
│       ├── advanced-techniques.md
│       ├── data-analysis.md
│       └── demo-session-walkthrough.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
├── install_service.py
├── install.py
├── LICENSE
├── NOTICE
├── pyproject.toml
├── pytest.ini
├── README.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
│   ├── 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
│   │   ├── assign_memory_types.py
│   │   ├── check_memory_types.py
│   │   ├── cleanup_corrupted_encoding.py
│   │   ├── cleanup_memories.py
│   │   ├── cleanup_organize.py
│   │   ├── consolidate_memory_types.py
│   │   ├── consolidation_mappings.json
│   │   ├── delete_orphaned_vectors_fixed.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
│   │   └── scan_todos.sh
│   ├── 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
│   │   ├── quality_gate.sh
│   │   ├── resolve_threads.sh
│   │   ├── run_pyscn_analysis.sh
│   │   ├── run_quality_checks.sh
│   │   ├── thread_status.sh
│   │   └── watch_reviews.sh
│   ├── quality
│   │   ├── fix_dead_code_install.sh
│   │   ├── phase1_dead_code_analysis.md
│   │   ├── phase2_complexity_analysis.md
│   │   ├── README_PHASE1.md
│   │   ├── README_PHASE2.md
│   │   ├── track_pyscn_metrics.sh
│   │   └── weekly_quality_review.sh
│   ├── README.md
│   ├── run
│   │   ├── 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
│   │   ├── install_http_service.sh
│   │   ├── mcp-memory-http.service
│   │   ├── mcp-memory.service
│   │   ├── memory_service_manager.sh
│   │   ├── service_control.sh
│   │   ├── service_utils.py
│   │   └── update_service.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
│   ├── utils
│   │   ├── claude_commands_utils.py
│   │   ├── generate_personalized_claude_md.sh
│   │   ├── groq
│   │   ├── groq_agent_bridge.py
│   │   ├── list-collections.py
│   │   ├── memory_wrapper_uv.py
│   │   ├── query_memories.py
│   │   ├── smithery_wrapper.py
│   │   ├── test_groq_bridge.sh
│   │   └── uv_wrapper.py
│   └── validation
│       ├── check_dev_setup.py
│       ├── check_documentation_links.py
│       ├── diagnose_backend_config.py
│       ├── validate_configuration_complete.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
│       ├── 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
│       ├── server.py
│       ├── services
│       │   ├── __init__.py
│       │   └── memory_service.py
│       ├── storage
│       │   ├── __init__.py
│       │   ├── base.py
│       │   ├── cloudflare.py
│       │   ├── factory.py
│       │   ├── http_client.py
│       │   ├── hybrid.py
│       │   └── 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
│       │   ├── document_processing.py
│       │   ├── gpu_detection.py
│       │   ├── hashing.py
│       │   ├── http_server_manager.py
│       │   ├── port_detection.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
│           │   ├── 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
│               ├── index.html
│               ├── README.md
│               ├── sse_test.html
│               └── style.css
├── start_http_debug.bat
├── start_http_server.sh
├── test_document.txt
├── test_version_checker.js
├── 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
│   ├── contracts
│   │   └── api-specification.yml
│   ├── integration
│   │   ├── package-lock.json
│   │   ├── package.json
│   │   ├── 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
│   ├── test_client.py
│   ├── test_content_splitting.py
│   ├── test_database.py
│   ├── test_hybrid_cloudflare_limits.py
│   ├── test_hybrid_storage.py
│   ├── test_memory_ops.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_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
├── 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
```

# Files

--------------------------------------------------------------------------------
/docs/CLAUDE_CODE_QUICK_REFERENCE.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Claude Code Quick Reference for MCP Memory Service
  2 | 
  3 | **One-page cheat sheet for efficient development with Claude Code**
  4 | 
  5 | ---
  6 | 
  7 | ## 🎯 Essential Keybindings
  8 | 
  9 | | Key | Action | Use Case |
 10 | |-----|--------|----------|
 11 | | `Shift+Tab` | Auto-accept edits | Fast iteration on suggested changes |
 12 | | `Esc` | Cancel operation | Stop unwanted actions |
 13 | | `Ctrl+R` | Verbose output | Debug when things go wrong |
 14 | | `#` | Create memory | Store important decisions |
 15 | | `@` | Add to context | Include files/dirs (`@src/`, `@tests/`) |
 16 | | `!` | Bash mode | Quick shell commands |
 17 | 
 18 | ---
 19 | 
 20 | ## 🚀 Common Tasks
 21 | 
 22 | ### Memory Operations
 23 | 
 24 | ```bash
 25 | # Store information
 26 | /memory-store "Hybrid backend uses SQLite primary + Cloudflare secondary"
 27 | 
 28 | # Retrieve information
 29 | /memory-recall "how to configure Cloudflare backend"
 30 | 
 31 | # Check service health
 32 | /memory-health
 33 | ```
 34 | 
 35 | ### Development Workflow
 36 | 
 37 | ```bash
 38 | # 1. Start with context
 39 | @src/mcp_memory_service/storage/
 40 | @tests/test_storage.py
 41 | 
 42 | # 2. Make changes incrementally
 43 | # Accept suggestions with Shift+Tab
 44 | 
 45 | # 3. Test immediately
 46 | pytest tests/test_storage.py -v
 47 | 
 48 | # 4. Document decisions
 49 | /memory-store "Changed X because Y"
 50 | ```
 51 | 
 52 | ### Backend Configuration
 53 | 
 54 | ```bash
 55 | # Check current backend
 56 | python scripts/server/check_http_server.py -v
 57 | 
 58 | # Validate configuration
 59 | python scripts/validation/validate_configuration_complete.py
 60 | 
 61 | # Diagnose issues
 62 | python scripts/validation/diagnose_backend_config.py
 63 | ```
 64 | 
 65 | ### Synchronization
 66 | 
 67 | ```bash
 68 | # Check sync status
 69 | python scripts/sync/sync_memory_backends.py --status
 70 | 
 71 | # Preview sync (dry run)
 72 | python scripts/sync/sync_memory_backends.py --dry-run
 73 | 
 74 | # Execute sync
 75 | python scripts/sync/sync_memory_backends.py --direction bidirectional
 76 | ```
 77 | 
 78 | ---
 79 | 
 80 | ## 🏗️ Project-Specific Context
 81 | 
 82 | ### Key Files to Add
 83 | 
 84 | | Purpose | Files to Include |
 85 | |---------|-----------------|
 86 | | **Storage backends** | `@src/mcp_memory_service/storage/` |
 87 | | **MCP protocol** | `@src/mcp_memory_service/server.py` |
 88 | | **Web interface** | `@src/mcp_memory_service/web/` |
 89 | | **Configuration** | `@.env.example`, `@src/mcp_memory_service/config.py` |
 90 | | **Tests** | `@tests/test_*.py` |
 91 | | **Scripts** | `@scripts/server/`, `@scripts/sync/` |
 92 | 
 93 | ### Common Debugging Patterns
 94 | 
 95 | ```bash
 96 | # 1. HTTP Server not responding
 97 | python scripts/server/check_http_server.py -v
 98 | tasklist | findstr python  # Check if running
 99 | scripts/server/start_http_server.bat  # Restart
100 | 
101 | # 2. Wrong backend active
102 | python scripts/validation/diagnose_backend_config.py
103 | # Check: .env file, environment variables, Claude Desktop config
104 | 
105 | # 3. Missing memories
106 | python scripts/sync/sync_memory_backends.py --status
107 | # Compare: Cloudflare count vs SQLite count
108 | 
109 | # 4. Service logs
110 | @http_server.log  # Add to context for troubleshooting
111 | ```
112 | 
113 | ---
114 | 
115 | ## 📚 Architecture Quick Reference
116 | 
117 | ### Storage Backends
118 | 
119 | | Backend | Performance | Use Case | Config Variable |
120 | |---------|-------------|----------|-----------------|
121 | | **Hybrid** ⭐ | 5ms read | Production (recommended) | `MCP_MEMORY_STORAGE_BACKEND=hybrid` |
122 | | **SQLite-vec** | 5ms read | Development, single-user | `MCP_MEMORY_STORAGE_BACKEND=sqlite_vec` |
123 | | **Cloudflare** | Network-dependent | Legacy cloud-only | `MCP_MEMORY_STORAGE_BACKEND=cloudflare` |
124 | 
125 | ### Key Directories
126 | 
127 | ```
128 | mcp-memory-service/
129 | ├── src/mcp_memory_service/
130 | │   ├── server.py              # MCP protocol implementation
131 | │   ├── storage/
132 | │   │   ├── base.py            # Abstract storage interface
133 | │   │   ├── sqlite_vec.py      # SQLite-vec backend
134 | │   │   ├── cloudflare.py      # Cloudflare backend
135 | │   │   └── hybrid.py          # Hybrid backend (recommended)
136 | │   ├── web/
137 | │   │   ├── app.py             # FastAPI server
138 | │   │   └── static/            # Dashboard UI
139 | │   └── config.py              # Configuration management
140 | ├── scripts/
141 | │   ├── server/                # HTTP server management
142 | │   ├── sync/                  # Backend synchronization
143 | │   └── validation/            # Configuration validation
144 | └── tests/                     # Test suite
145 | ```
146 | 
147 | ---
148 | 
149 | ## 🔧 Environment Variables
150 | 
151 | **Essential Configuration** (in `.env` file):
152 | 
153 | ```bash
154 | # Backend Selection
155 | MCP_MEMORY_STORAGE_BACKEND=hybrid  # hybrid|sqlite_vec|cloudflare
156 | 
157 | # Cloudflare (required for hybrid/cloudflare backends)
158 | CLOUDFLARE_API_TOKEN=your-token
159 | CLOUDFLARE_ACCOUNT_ID=your-account
160 | CLOUDFLARE_D1_DATABASE_ID=your-d1-id
161 | CLOUDFLARE_VECTORIZE_INDEX=mcp-memory-index
162 | 
163 | # Hybrid-Specific
164 | MCP_HYBRID_SYNC_INTERVAL=300      # 5 minutes
165 | MCP_HYBRID_BATCH_SIZE=50
166 | MCP_HYBRID_SYNC_ON_STARTUP=true
167 | 
168 | # HTTP Server
169 | MCP_HTTP_ENABLED=true
170 | MCP_HTTPS_ENABLED=true
171 | MCP_API_KEY=your-generated-key
172 | ```
173 | 
174 | ---
175 | 
176 | ## 🐛 Troubleshooting Checklist
177 | 
178 | ### HTTP Server Issues
179 | - [ ] Check if server is running: `python scripts/server/check_http_server.py -v`
180 | - [ ] Review logs: `@http_server.log`
181 | - [ ] Restart server: `scripts/server/start_http_server.bat`
182 | - [ ] Verify port 8000 is free: `netstat -ano | findstr :8000`
183 | 
184 | ### Backend Configuration Issues
185 | - [ ] Run diagnostic: `python scripts/validation/diagnose_backend_config.py`
186 | - [ ] Check `.env` file exists and has correct values
187 | - [ ] Verify Cloudflare credentials are valid
188 | - [ ] Confirm environment variables loaded: check server startup logs
189 | 
190 | ### Missing Memories
191 | - [ ] Check sync status: `python scripts/sync/sync_memory_backends.py --status`
192 | - [ ] Compare memory counts: Cloudflare vs SQLite
193 | - [ ] Run manual sync: `python scripts/sync/sync_memory_backends.py --dry-run`
194 | - [ ] Check for duplicates: Look for content hash matches
195 | 
196 | ### Performance Issues
197 | - [ ] Verify backend: Hybrid should show ~5ms read times
198 | - [ ] Check disk space: Litestream requires adequate space
199 | - [ ] Monitor background sync: Check `http_server.log` for sync logs
200 | - [ ] Review embedding model cache: Should be loaded once
201 | 
202 | ---
203 | 
204 | ## 💡 Pro Tips
205 | 
206 | ### Efficient Context Management
207 | 
208 | ```bash
209 | # Start specific, expand as needed
210 | @src/mcp_memory_service/storage/hybrid.py  # Specific file
211 | @src/mcp_memory_service/storage/           # Whole module if needed
212 | 
213 | # Remove context when done
214 | # Use Esc to cancel unnecessary context additions
215 | ```
216 | 
217 | ### Multi-Step Tasks
218 | 
219 | ```bash
220 | # Always use TodoWrite for complex tasks
221 | # Claude will create and manage task list automatically
222 | 
223 | # Example: "Implement new backend"
224 | # 1. Research existing backends
225 | # 2. Create new backend class
226 | # 3. Implement abstract methods
227 | # 4. Add configuration
228 | # 5. Write tests
229 | # 6. Update documentation
230 | ```
231 | 
232 | ### Testing Strategy
233 | 
234 | ```bash
235 | # Test incrementally
236 | pytest tests/test_storage.py::TestHybridBackend -v
237 | 
238 | # Run full suite before committing
239 | pytest tests/ -v
240 | 
241 | # Check coverage
242 | pytest tests/ --cov=src/mcp_memory_service --cov-report=term
243 | ```
244 | 
245 | ### Git Workflow with Claude Code
246 | 
247 | ```bash
248 | # Let Claude help with commits
249 | git status  # Claude reviews changes
250 | git diff    # Claude explains changes
251 | 
252 | # Use semantic commits
253 | git commit -m "feat: add new backend support"
254 | git commit -m "fix: resolve sync timing issue"
255 | git commit -m "docs: update configuration guide"
256 | ```
257 | 
258 | ---
259 | 
260 | ## 📖 Additional Resources
261 | 
262 | - **Full Documentation**: `@CLAUDE.md` (project-specific guide)
263 | - **Global Best Practices**: `~/.claude/CLAUDE.md` (cross-project)
264 | - **Wiki**: https://github.com/doobidoo/mcp-memory-service/wiki
265 | - **Troubleshooting**: See Wiki for comprehensive troubleshooting guide
266 | 
267 | ---
268 | 
269 | **Last Updated**: 2025-10-08
270 | 
```

--------------------------------------------------------------------------------
/docs/technical/development.md:
--------------------------------------------------------------------------------

```markdown
  1 | # MCP Memory Service - Development Guidelines
  2 | 
  3 | ## Commands
  4 | - Run memory server: `python scripts/run_memory_server.py`
  5 | - Run tests: `pytest tests/`
  6 | - Run specific test: `pytest tests/test_memory_ops.py::test_store_memory -v`
  7 | - Check environment: `python scripts/verify_environment_enhanced.py`
  8 | - Windows installation: `python scripts/install_windows.py`
  9 | - Build package: `python -m build`
 10 | 
 11 | ## Installation Guidelines
 12 | - Always install in a virtual environment: `python -m venv venv`
 13 | - Use `install.py` for cross-platform installation
 14 | - Windows requires special PyTorch installation with correct index URL:
 15 |   ```bash
 16 |   pip install torch==2.1.0 torchvision==2.1.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cu118
 17 |   ```
 18 | - For recursion errors, run: `python scripts/fix_sitecustomize.py`
 19 | 
 20 | ## Code Style
 21 | - Python 3.10+ with type hints
 22 | - Use dataclasses for models (see `models/memory.py`)
 23 | - Triple-quoted docstrings for modules and functions
 24 | - Async/await pattern for all I/O operations
 25 | - Error handling with specific exception types and informative messages
 26 | - Logging with appropriate levels for different severity
 27 | - Commit messages follow semantic release format: `type(scope): message`
 28 | 
 29 | ## Project Structure
 30 | - `src/mcp_memory_service/` - Core package code
 31 |   - `models/` - Data models
 32 |   - `storage/` - Database abstraction
 33 |   - `utils/` - Helper functions
 34 |   - `server.py` - MCP protocol implementation
 35 | - `scripts/` - Utility scripts
 36 | - `memory_wrapper.py` - Windows wrapper script
 37 | - `install.py` - Cross-platform installation script
 38 | 
 39 | ## Dependencies
 40 | - ChromaDB (0.5.23) for vector database
 41 | - sentence-transformers (>=2.2.2) for embeddings
 42 | - PyTorch (platform-specific installation)
 43 | - MCP protocol (>=1.0.0, <2.0.0) for client-server communication
 44 | 
 45 | ## Troubleshooting
 46 | 
 47 | ### Common Issues
 48 | 
 49 | - For Windows installation issues, use `scripts/install_windows.py`
 50 | - Apple Silicon requires Python 3.10+ built for ARM64  
 51 | - CUDA issues: verify with `torch.cuda.is_available()`
 52 | - For MCP protocol issues, check `server.py` for required methods
 53 | 
 54 | ### MCP Server Configuration Issues
 55 | 
 56 | If you encounter MCP server failures or "ModuleNotFoundError" issues:
 57 | 
 58 | #### Missing http_server_manager Module
 59 | **Symptoms:**
 60 | - Server fails with "No module named 'mcp_memory_service.utils.http_server_manager'"
 61 | - MCP server shows as "failed" in Claude Code
 62 | 
 63 | **Diagnosis:**
 64 | 1. Test server directly: `python -m src.mcp_memory_service.server --debug`
 65 | 2. Check if the error occurs during eager storage initialization
 66 | 3. Look for HTTP server coordination mode detection
 67 | 
 68 | **Solution:**
 69 | The `http_server_manager.py` module handles multi-client coordination. If missing, create it with:
 70 | - `auto_start_http_server_if_needed()` function
 71 | - Port detection and server startup logic
 72 | - Integration with existing `port_detection.py` utilities
 73 | 
 74 | #### Storage Backend Issues
 75 | **Symptoms:**
 76 | - "vec0 constructor error: Unknown table option" (older sqlite-vec versions)
 77 | - Server initialization fails with storage errors
 78 | 
 79 | **Diagnosis:**
 80 | 1. Test each backend independently:
 81 |    - ChromaDB: `python scripts/run_memory_server.py --debug`
 82 |    - SQLite-vec: `MCP_MEMORY_STORAGE_BACKEND=sqlite_vec python -m src.mcp_memory_service.server --debug`
 83 | 2. Check database health: Use MCP tools to call `check_database_health`
 84 | 
 85 | **Solution:**
 86 | - Ensure sqlite-vec is properly installed and compatible
 87 | - Both backends should work when properly configured
 88 | - SQLite-vec uses direct storage mode when HTTP coordination fails
 89 | 
 90 | #### MCP Configuration Cleanup
 91 | When multiple servers conflict or fail:
 92 | 
 93 | 1. **Backup configurations:**
 94 |    ```bash
 95 |    cp .mcp.json .mcp.json.backup
 96 |    ```
 97 | 
 98 | 2. **Remove failing servers** from `.mcp.json` while keeping working ones
 99 | 
100 | 3. **Test each backend separately:**
101 |    - ChromaDB backend: Uses `scripts/run_memory_server.py`
102 |    - SQLite-vec backend: Uses `python -m src.mcp_memory_service.server` with `MCP_MEMORY_STORAGE_BACKEND=sqlite_vec`
103 | 
104 | 4. **Verify functionality** through MCP tools before re-enabling servers
105 | 
106 | ### Collaborative Debugging with Claude Code
107 | 
108 | When troubleshooting complex MCP issues, consider this collaborative approach between developer and Claude Code:
109 | 
110 | #### Systematic Problem-Solving Partnership
111 | 1. **Developer identifies the symptom** (e.g., "memory server shows as failed")
112 | 2. **Claude Code conducts comprehensive diagnosis:**
113 |    - Tests current functionality with MCP tools
114 |    - Examines server logs and error messages  
115 |    - Checks configuration files and git history
116 |    - Identifies root causes through systematic analysis
117 | 
118 | 3. **Collaborative investigation approach:**
119 |    - **Developer requests:** "Check both ways - verify current service works AND fix the failing alternative"
120 |    - **Claude Code responds:** Creates todo lists, tests each component independently, provides detailed analysis
121 |    - **Developer provides context:** Domain knowledge, constraints, preferences
122 | 
123 | 4. **Methodical fix implementation:**
124 |    - Back up configurations before changes
125 |    - Fix issues incrementally with testing at each step
126 |    - Document the process for future reference
127 |    - Commit meaningful changes with proper commit messages
128 | 
129 | #### Benefits of This Approach
130 | - **Comprehensive coverage:** Nothing gets missed when both perspectives combine
131 | - **Knowledge transfer:** Claude Code documents the process, developer retains understanding
132 | - **Systematic methodology:** Todo lists and step-by-step verification prevent overlooked issues
133 | - **Persistent knowledge:** Using the memory service itself to store troubleshooting solutions
134 | 
135 | #### Example Workflow
136 | ```
137 | Developer: "MCP memory server is failing"
138 | ↓
139 | Claude Code: Creates todo list, tests current state, identifies missing module
140 | ↓  
141 | Developer: "Let's fix it but keep the working parts"
142 | ↓
143 | Claude Code: Backs up configs, fixes incrementally, tests each component
144 | ↓
145 | Developer: "This should be documented"
146 | ↓
147 | Claude Code: Updates documentation, memorizes the solution
148 | ↓
149 | Both: Commit, push, and ensure knowledge is preserved
150 | ```
151 | 
152 | This collaborative model leverages Claude Code's systematic analysis capabilities with the developer's domain expertise and decision-making authority.
153 | 
154 | ## Debugging with MCP-Inspector
155 | 
156 | To debug the MCP-MEMORY-SERVICE using the [MCP-Inspector](https://modelcontextprotocol.io/docs/tools/inspector) tool, you can use the following command pattern:
157 | 
158 | ```bash
159 | MCP_MEMORY_CHROMA_PATH="/path/to/your/chroma_db" MCP_MEMORY_BACKUPS_PATH="/path/to/your/backups" npx @modelcontextprotocol/inspector uv --directory /path/to/mcp-memory-service run memory
160 | ```
161 | 
162 | Replace the paths with your specific directories:
163 | - `/path/to/your/chroma_db`: Location where Chroma database files are stored
164 | - `/path/to/your/backups`: Location for memory backups
165 | - `/path/to/mcp-memory-service`: Directory containing the MCP-MEMORY-SERVICE code
166 | 
167 | For example:
168 | ```bash
169 | MCP_MEMORY_CHROMA_PATH="~/Library/Mobile Documents/com~apple~CloudDocs/AI/claude-memory/chroma_db" MCP_MEMORY_BACKUPS_PATH="~/Library/Mobile Documents/com~apple~CloudDocs/AI/claude-memory/backups" npx @modelcontextprotocol/inspector uv --directory ~/Documents/GitHub/mcp-memory-service run memory
170 | ```
171 | 
172 | This command sets the required environment variables and runs the memory service through the inspector tool for debugging purposes.
173 | 
```

--------------------------------------------------------------------------------
/scripts/pr/run_pyscn_analysis.sh:
--------------------------------------------------------------------------------

```bash
  1 | #!/bin/bash
  2 | # scripts/pr/run_pyscn_analysis.sh - Run pyscn comprehensive code quality analysis
  3 | #
  4 | # Usage:
  5 | #   bash scripts/pr/run_pyscn_analysis.sh [--pr PR_NUMBER] [--threshold SCORE]
  6 | #
  7 | # Options:
  8 | #   --pr PR_NUMBER    Post results as PR comment (requires gh CLI)
  9 | #   --threshold SCORE Minimum health score (default: 50, blocks below this)
 10 | #
 11 | # Examples:
 12 | #   bash scripts/pr/run_pyscn_analysis.sh                    # Local analysis
 13 | #   bash scripts/pr/run_pyscn_analysis.sh --pr 123           # Analyze and comment on PR #123
 14 | #   bash scripts/pr/run_pyscn_analysis.sh --threshold 70     # Require health score ≥70
 15 | 
 16 | set -e
 17 | 
 18 | # Colors for output
 19 | RED='\033[0;31m'
 20 | YELLOW='\033[1;33m'
 21 | GREEN='\033[0;32m'
 22 | BLUE='\033[0;34m'
 23 | NC='\033[0m' # No Color
 24 | 
 25 | # Parse arguments
 26 | PR_NUMBER=""
 27 | THRESHOLD=50  # Default: block if health score <50
 28 | 
 29 | while [[ $# -gt 0 ]]; do
 30 |     case $1 in
 31 |         --pr)
 32 |             PR_NUMBER="$2"
 33 |             shift 2
 34 |             ;;
 35 |         --threshold)
 36 |             THRESHOLD="$2"
 37 |             shift 2
 38 |             ;;
 39 |         *)
 40 |             echo "Unknown option: $1"
 41 |             echo "Usage: $0 [--pr PR_NUMBER] [--threshold SCORE]"
 42 |             exit 1
 43 |             ;;
 44 |     esac
 45 | done
 46 | 
 47 | # Check for pyscn
 48 | if ! command -v pyscn &> /dev/null; then
 49 |     echo -e "${RED}❌ pyscn not found${NC}"
 50 |     echo ""
 51 |     echo "Install pyscn with:"
 52 |     echo "  pip install pyscn"
 53 |     echo ""
 54 |     echo "Repository: https://github.com/ludo-technologies/pyscn"
 55 |     exit 1
 56 | fi
 57 | 
 58 | echo -e "${BLUE}=== pyscn Code Quality Analysis ===${NC}"
 59 | echo ""
 60 | 
 61 | # Create reports directory if needed
 62 | mkdir -p .pyscn/reports
 63 | 
 64 | # Run pyscn analysis
 65 | echo "Running pyscn analysis (this may take 30-60 seconds)..."
 66 | echo ""
 67 | 
 68 | # Generate timestamp for report
 69 | TIMESTAMP=$(date +%Y%m%d_%H%M%S)
 70 | REPORT_FILE=".pyscn/reports/analyze_${TIMESTAMP}.html"
 71 | JSON_FILE=".pyscn/reports/analyze_${TIMESTAMP}.json"
 72 | 
 73 | # Run analysis (HTML report)
 74 | if pyscn analyze . --output "$REPORT_FILE" 2>&1 | tee /tmp/pyscn_output.log; then
 75 |     echo -e "${GREEN}✓${NC} Analysis complete"
 76 | else
 77 |     echo -e "${RED}❌ Analysis failed${NC}"
 78 |     cat /tmp/pyscn_output.log
 79 |     exit 1
 80 | fi
 81 | 
 82 | # Extract metrics from HTML report using grep/sed
 83 | # Note: This is a simple parser - adjust patterns if pyscn output format changes
 84 | HEALTH_SCORE=$(grep -o 'Health Score: [0-9]*' "$REPORT_FILE" | head -1 | grep -o '[0-9]*' || echo "0")
 85 | COMPLEXITY_SCORE=$(grep -o '<span class="score-value">[0-9]*</span>' "$REPORT_FILE" | head -1 | sed 's/<[^>]*>//g' || echo "0")
 86 | DEAD_CODE_SCORE=$(grep -o '<span class="score-value">[0-9]*</span>' "$REPORT_FILE" | sed -n '2p' | sed 's/<[^>]*>//g' || echo "0")
 87 | DUPLICATION_SCORE=$(grep -o '<span class="score-value">[0-9]*</span>' "$REPORT_FILE" | sed -n '3p' | sed 's/<[^>]*>//g' || echo "0")
 88 | 
 89 | # Extract detailed metrics
 90 | TOTAL_FUNCTIONS=$(grep -o '<div class="metric-value">[0-9]*</div>' "$REPORT_FILE" | head -1 | sed 's/<[^>]*>//g' || echo "0")
 91 | AVG_COMPLEXITY=$(grep -o '<div class="metric-value">[0-9.]*</div>' "$REPORT_FILE" | sed -n '3p' | sed 's/<[^>]*>//g' || echo "0")
 92 | MAX_COMPLEXITY=$(grep -o '<div class="metric-value">[0-9]*</div>' "$REPORT_FILE" | sed -n '3p' | sed 's/<[^>]*>//g' || echo "0")
 93 | DUPLICATION_PCT=$(grep -o '<div class="metric-value">[0-9.]*%</div>' "$REPORT_FILE" | head -1 | sed 's/<[^>]*>//g' || echo "0%")
 94 | DEAD_CODE_ISSUES=$(grep -o '<div class="metric-value">[0-9]*</div>' "$REPORT_FILE" | sed -n '4p' | sed 's/<[^>]*>//g' || echo "0")
 95 | ARCHITECTURE_VIOLATIONS=$(grep -o '<div class="metric-value">[0-9]*</div>' "$REPORT_FILE" | tail -2 | head -1 | sed 's/<[^>]*>//g' || echo "0")
 96 | 
 97 | echo ""
 98 | echo -e "${BLUE}=== Analysis Results ===${NC}"
 99 | echo ""
100 | echo "📊 Overall Health Score: $HEALTH_SCORE/100"
101 | echo ""
102 | echo "Quality Metrics:"
103 | echo "  - Complexity: $COMPLEXITY_SCORE/100 (Avg: $AVG_COMPLEXITY, Max: $MAX_COMPLEXITY)"
104 | echo "  - Dead Code: $DEAD_CODE_SCORE/100 ($DEAD_CODE_ISSUES issues)"
105 | echo "  - Duplication: $DUPLICATION_SCORE/100 ($DUPLICATION_PCT duplication)"
106 | echo ""
107 | echo "📄 Report: $REPORT_FILE"
108 | echo ""
109 | 
110 | # Determine status
111 | EXIT_CODE=0
112 | STATUS="✅ PASSED"
113 | EMOJI="✅"
114 | COLOR=$GREEN
115 | 
116 | if [ "$HEALTH_SCORE" -lt "$THRESHOLD" ]; then
117 |     STATUS="🔴 BLOCKED"
118 |     EMOJI="🔴"
119 |     COLOR=$RED
120 |     EXIT_CODE=1
121 | elif [ "$HEALTH_SCORE" -lt 70 ]; then
122 |     STATUS="⚠️  WARNING"
123 |     EMOJI="⚠️"
124 |     COLOR=$YELLOW
125 | fi
126 | 
127 | echo -e "${COLOR}${STATUS}${NC} - Health score: $HEALTH_SCORE (threshold: $THRESHOLD)"
128 | echo ""
129 | 
130 | # Generate recommendations
131 | RECOMMENDATIONS=""
132 | 
133 | if [ "$HEALTH_SCORE" -lt 50 ]; then
134 |     RECOMMENDATIONS="**🚨 Critical Action Required:**
135 | - Health score below 50 is a release blocker
136 | - Focus on top 5 highest complexity functions
137 | - Remove dead code before proceeding
138 | "
139 | elif [ "$HEALTH_SCORE" -lt 70 ]; then
140 |     RECOMMENDATIONS="**⚠️  Improvement Recommended:**
141 | - Plan refactoring sprint within 2 weeks
142 | - Track high-complexity functions on project board
143 | - Review duplication patterns for consolidation opportunities
144 | "
145 | fi
146 | 
147 | # Check for critical issues
148 | CRITICAL_COMPLEXITY=""
149 | if [ "$MAX_COMPLEXITY" -gt 10 ]; then
150 |     CRITICAL_COMPLEXITY="- ⚠️  Functions with complexity >10 detected (Max: $MAX_COMPLEXITY)
151 | "
152 | fi
153 | 
154 | CRITICAL_DUPLICATION=""
155 | DUPLICATION_NUM=$(echo "$DUPLICATION_PCT" | sed 's/%//')
156 | if (( $(echo "$DUPLICATION_NUM > 5.0" | bc -l) )); then
157 |     CRITICAL_DUPLICATION="- ⚠️  Code duplication above 5% threshold ($DUPLICATION_PCT)
158 | "
159 | fi
160 | 
161 | # Post to PR if requested
162 | if [ -n "$PR_NUMBER" ]; then
163 |     if ! command -v gh &> /dev/null; then
164 |         echo -e "${YELLOW}⚠️  gh CLI not found, skipping PR comment${NC}"
165 |     else
166 |         echo "Posting results to PR #$PR_NUMBER..."
167 | 
168 |         COMMENT_BODY="## ${EMOJI} pyscn Code Quality Analysis
169 | 
170 | **Health Score:** $HEALTH_SCORE/100
171 | 
172 | ### Quality Metrics
173 | 
174 | | Metric | Score | Details |
175 | |--------|-------|---------|
176 | | 🔢 Complexity | $COMPLEXITY_SCORE/100 | Avg: $AVG_COMPLEXITY, Max: $MAX_COMPLEXITY |
177 | | 💀 Dead Code | $DEAD_CODE_SCORE/100 | $DEAD_CODE_ISSUES issues |
178 | | 📋 Duplication | $DUPLICATION_SCORE/100 | $DUPLICATION_PCT code duplication |
179 | | 🏗️  Architecture | N/A | $ARCHITECTURE_VIOLATIONS violations |
180 | 
181 | ### Status
182 | 
183 | $STATUS (Threshold: $THRESHOLD)
184 | 
185 | ${CRITICAL_COMPLEXITY}${CRITICAL_DUPLICATION}${RECOMMENDATIONS}
186 | 
187 | ### Full Report
188 | 
189 | View detailed analysis: [HTML Report](.pyscn/reports/analyze_${TIMESTAMP}.html)
190 | 
191 | ---
192 | 
193 | <details>
194 | <summary>📖 About pyscn</summary>
195 | 
196 | pyscn (Python Static Code Navigator) provides comprehensive static analysis including:
197 | - Cyclomatic complexity analysis
198 | - Dead code detection
199 | - Code duplication (clone detection)
200 | - Coupling metrics (CBO)
201 | - Dependency graph analysis
202 | - Architecture violation detection
203 | 
204 | Repository: https://github.com/ludo-technologies/pyscn
205 | </details>"
206 | 
207 |         echo "$COMMENT_BODY" | gh pr comment "$PR_NUMBER" --body-file -
208 |         echo -e "${GREEN}✓${NC} Posted comment to PR #$PR_NUMBER"
209 |     fi
210 | fi
211 | 
212 | # Summary
213 | echo ""
214 | echo -e "${BLUE}=== Summary ===${NC}"
215 | echo ""
216 | 
217 | if [ $EXIT_CODE -eq 0 ]; then
218 |     echo -e "${GREEN}✅ Quality checks passed${NC}"
219 |     echo ""
220 |     echo "Health score ($HEALTH_SCORE) meets threshold ($THRESHOLD)"
221 | else
222 |     echo -e "${RED}❌ Quality checks failed${NC}"
223 |     echo ""
224 |     echo "Health score ($HEALTH_SCORE) below threshold ($THRESHOLD)"
225 |     echo ""
226 |     echo "Action required before merging:"
227 |     echo "  1. Review full report: open $REPORT_FILE"
228 |     echo "  2. Address high-complexity functions (complexity >10)"
229 |     echo "  3. Remove dead code ($DEAD_CODE_ISSUES issues)"
230 |     echo "  4. Reduce duplication where feasible"
231 |     echo ""
232 | fi
233 | 
234 | exit $EXIT_CODE
235 | 
```

--------------------------------------------------------------------------------
/src/mcp_memory_service/sync/exporter.py:
--------------------------------------------------------------------------------

```python
  1 | # Copyright 2024 Heinrich Krupp
  2 | #
  3 | # Licensed under the Apache License, Version 2.0 (the "License");
  4 | # you may not use this file except in compliance with the License.
  5 | # You may obtain a copy of the License at
  6 | #
  7 | #     http://www.apache.org/licenses/LICENSE-2.0
  8 | #
  9 | # Unless required by applicable law or agreed to in writing, software
 10 | # distributed under the License is distributed on an "AS IS" BASIS,
 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | # See the License for the specific language governing permissions and
 13 | # limitations under the License.
 14 | 
 15 | """
 16 | Memory export functionality for database synchronization.
 17 | """
 18 | 
 19 | import json
 20 | import os
 21 | import platform
 22 | import logging
 23 | from datetime import datetime
 24 | from pathlib import Path
 25 | from typing import List, Dict, Any, Optional
 26 | 
 27 | from ..models.memory import Memory
 28 | from ..storage.base import MemoryStorage
 29 | 
 30 | logger = logging.getLogger(__name__)
 31 | 
 32 | 
 33 | class MemoryExporter:
 34 |     """
 35 |     Exports memories from a storage backend to JSON format.
 36 |     
 37 |     Preserves all metadata, timestamps, and adds source tracking for
 38 |     multi-machine synchronization workflows.
 39 |     """
 40 |     
 41 |     def __init__(self, storage: MemoryStorage):
 42 |         """
 43 |         Initialize the exporter.
 44 |         
 45 |         Args:
 46 |             storage: The memory storage backend to export from
 47 |         """
 48 |         self.storage = storage
 49 |         self.machine_name = self._get_machine_name()
 50 |     
 51 |     def _get_machine_name(self) -> str:
 52 |         """Get a unique machine identifier."""
 53 |         # Try various methods to get a unique machine name
 54 |         machine_name = (
 55 |             os.environ.get('COMPUTERNAME') or  # Windows
 56 |             os.environ.get('HOSTNAME') or      # Linux/macOS
 57 |             platform.node() or                # Platform module
 58 |             'unknown-machine'
 59 |         )
 60 |         return machine_name.lower().replace(' ', '-')
 61 |     
 62 |     async def export_to_json(
 63 |         self, 
 64 |         output_file: Path,
 65 |         include_embeddings: bool = False,
 66 |         filter_tags: Optional[List[str]] = None
 67 |     ) -> Dict[str, Any]:
 68 |         """
 69 |         Export all memories to JSON format.
 70 |         
 71 |         Args:
 72 |             output_file: Path to write the JSON export
 73 |             include_embeddings: Whether to include embedding vectors (large)
 74 |             filter_tags: Only export memories with these tags (optional)
 75 |             
 76 |         Returns:
 77 |             Export metadata dictionary with statistics
 78 |         """
 79 |         logger.info(f"Starting memory export to {output_file}")
 80 |         
 81 |         # Get all memories from storage
 82 |         all_memories = await self._get_filtered_memories(filter_tags)
 83 |         
 84 |         # Create export metadata
 85 |         export_metadata = {
 86 |             "source_machine": self.machine_name,
 87 |             "export_timestamp": datetime.now().isoformat(),
 88 |             "total_memories": len(all_memories),
 89 |             "database_path": str(self.storage.db_path) if hasattr(self.storage, 'db_path') else 'unknown',
 90 |             "platform": platform.system(),
 91 |             "python_version": platform.python_version(),
 92 |             "include_embeddings": include_embeddings,
 93 |             "filter_tags": filter_tags,
 94 |             "exporter_version": "5.0.1"
 95 |         }
 96 |         
 97 |         # Convert memories to exportable format
 98 |         exported_memories = []
 99 |         for memory in all_memories:
100 |             memory_dict = await self._memory_to_dict(memory, include_embeddings)
101 |             exported_memories.append(memory_dict)
102 |         
103 |         # Create final export structure
104 |         export_data = {
105 |             "export_metadata": export_metadata,
106 |             "memories": exported_memories
107 |         }
108 |         
109 |         # Write to JSON file
110 |         output_file.parent.mkdir(parents=True, exist_ok=True)
111 |         with open(output_file, 'w', encoding='utf-8') as f:
112 |             json.dump(export_data, f, indent=2, ensure_ascii=False)
113 |         
114 |         # Log success
115 |         file_size = output_file.stat().st_size
116 |         logger.info(f"Export completed: {len(all_memories)} memories written to {output_file}")
117 |         logger.info(f"File size: {file_size / 1024 / 1024:.2f} MB")
118 |         
119 |         # Return summary statistics
120 |         return {
121 |             "success": True,
122 |             "exported_count": len(all_memories),
123 |             "output_file": str(output_file),
124 |             "file_size_bytes": file_size,
125 |             "source_machine": self.machine_name,
126 |             "export_timestamp": export_metadata["export_timestamp"]
127 |         }
128 |     
129 |     async def _get_filtered_memories(self, filter_tags: Optional[List[str]]) -> List[Memory]:
130 |         """Get memories with optional tag filtering."""
131 |         if not filter_tags:
132 |             # Get all memories
133 |             return await self.storage.get_all_memories()
134 |         
135 |         # Filter by tags if specified
136 |         filtered_memories = []
137 |         all_memories = await self.storage.get_all_memories()
138 |         
139 |         for memory in all_memories:
140 |             if any(tag in memory.tags for tag in filter_tags):
141 |                 filtered_memories.append(memory)
142 |         
143 |         return filtered_memories
144 |     
145 |     async def _memory_to_dict(self, memory: Memory, include_embeddings: bool) -> Dict[str, Any]:
146 |         """Convert a Memory object to a dictionary for JSON export."""
147 |         memory_dict = {
148 |             "content": memory.content,
149 |             "content_hash": memory.content_hash,
150 |             "tags": memory.tags,
151 |             "created_at": memory.created_at,  # Preserve original timestamp
152 |             "updated_at": memory.updated_at,
153 |             "memory_type": memory.memory_type,
154 |             "metadata": memory.metadata or {},
155 |             "export_source": self.machine_name
156 |         }
157 |         
158 |         # Add embedding if requested and available
159 |         if include_embeddings and hasattr(memory, 'embedding') and memory.embedding:
160 |             memory_dict["embedding"] = memory.embedding.tolist() if hasattr(memory.embedding, 'tolist') else memory.embedding
161 |         
162 |         return memory_dict
163 |     
164 |     async def export_summary(self) -> Dict[str, Any]:
165 |         """
166 |         Get a summary of what would be exported without actually exporting.
167 |         
168 |         Returns:
169 |             Summary statistics about the memories in the database
170 |         """
171 |         all_memories = await self.storage.get_all_memories()
172 |         
173 |         # Analyze tags
174 |         tag_counts = {}
175 |         memory_types = {}
176 |         date_range = {"earliest": None, "latest": None}
177 |         
178 |         for memory in all_memories:
179 |             # Count tags
180 |             for tag in memory.tags:
181 |                 tag_counts[tag] = tag_counts.get(tag, 0) + 1
182 |             
183 |             # Count memory types
184 |             memory_types[memory.memory_type] = memory_types.get(memory.memory_type, 0) + 1
185 |             
186 |             # Track date range
187 |             if date_range["earliest"] is None or memory.created_at < date_range["earliest"]:
188 |                 date_range["earliest"] = memory.created_at
189 |             if date_range["latest"] is None or memory.created_at > date_range["latest"]:
190 |                 date_range["latest"] = memory.created_at
191 |         
192 |         return {
193 |             "total_memories": len(all_memories),
194 |             "machine_name": self.machine_name,
195 |             "tag_counts": dict(sorted(tag_counts.items(), key=lambda x: x[1], reverse=True)),
196 |             "memory_types": memory_types,
197 |             "date_range": date_range,
198 |             "estimated_json_size_mb": len(all_memories) * 0.001  # Rough estimate
199 |         }
```

--------------------------------------------------------------------------------
/scripts/testing/test_memory_api.py:
--------------------------------------------------------------------------------

```python
  1 | #!/usr/bin/env python3
  2 | # Copyright 2024 Heinrich Krupp
  3 | #
  4 | # Licensed under the Apache License, Version 2.0 (the "License");
  5 | # you may not use this file except in compliance with the License.
  6 | # You may obtain a copy of the License at
  7 | #
  8 | #     http://www.apache.org/licenses/LICENSE-2.0
  9 | #
 10 | # Unless required by applicable law or agreed to in writing, software
 11 | # distributed under the License is distributed on an "AS IS" BASIS,
 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 | # See the License for the specific language governing permissions and
 14 | # limitations under the License.
 15 | 
 16 | """
 17 | Test script for memory CRUD operations via HTTP API.
 18 | 
 19 | This script tests the basic memory operations to ensure they work correctly.
 20 | """
 21 | 
 22 | import asyncio
 23 | import aiohttp
 24 | import json
 25 | import time
 26 | from typing import Dict, Any
 27 | 
 28 | BASE_URL = "http://localhost:8000"
 29 | 
 30 | async def test_memory_crud():
 31 |     """Test the complete CRUD workflow for memories."""
 32 |     
 33 |     async with aiohttp.ClientSession() as session:
 34 |         print("Testing Memory CRUD Operations")
 35 |         print("=" * 50)
 36 |         
 37 |         # Test 1: Health check
 38 |         print("\n[1] Testing health check...")
 39 |         try:
 40 |             async with session.get(f"{BASE_URL}/api/health") as resp:
 41 |                 if resp.status == 200:
 42 |                     health = await resp.json()
 43 |                     print(f"[PASS] Health check passed: {health['status']}")
 44 |                 else:
 45 |                     print(f"[FAIL] Health check failed: {resp.status}")
 46 |                     return
 47 |         except Exception as e:
 48 |             print(f"[FAIL] Cannot connect to server: {e}")
 49 |             print("NOTE: Make sure the server is running with: python scripts/run_http_server.py")
 50 |             return
 51 |         
 52 |         # Test 2: Store a memory
 53 |         print("\n[2] Testing memory storage...")
 54 |         test_memory = {
 55 |             "content": "This is a test memory for CRUD operations",
 56 |             "tags": ["test", "crud", "api"],
 57 |             "memory_type": "test",
 58 |             "metadata": {"test_run": time.time(), "importance": "high"}
 59 |         }
 60 |         
 61 |         try:
 62 |             async with session.post(
 63 |                 f"{BASE_URL}/api/memories",
 64 |                 json=test_memory,
 65 |                 headers={"Content-Type": "application/json"}
 66 |             ) as resp:
 67 |                 if resp.status == 200:
 68 |                     result = await resp.json()
 69 |                     if result["success"]:
 70 |                         content_hash = result["content_hash"]
 71 |                         print(f"[PASS] Memory stored successfully")
 72 |                         print(f"   Content hash: {content_hash[:16]}...")
 73 |                         print(f"   Message: {result['message']}")
 74 |                     else:
 75 |                         print(f"[FAIL] Memory storage failed: {result['message']}")
 76 |                         return
 77 |                 else:
 78 |                     print(f"[FAIL] Memory storage failed: {resp.status}")
 79 |                     error = await resp.text()
 80 |                     print(f"   Error: {error}")
 81 |                     return
 82 |         except Exception as e:
 83 |             print(f"[FAIL] Memory storage error: {e}")
 84 |             return
 85 |         
 86 |         # Test 3: List memories
 87 |         print("\n[3] Testing memory listing...")
 88 |         try:
 89 |             async with session.get(f"{BASE_URL}/api/memories?page=1&page_size=5") as resp:
 90 |                 if resp.status == 200:
 91 |                     result = await resp.json()
 92 |                     memories = result["memories"]
 93 |                     print(f"✅ Retrieved {len(memories)} memories")
 94 |                     print(f"   Total memories: {result['total']}")
 95 |                     print(f"   Page: {result['page']}, Has more: {result['has_more']}")
 96 |                     
 97 |                     if memories:
 98 |                         print(f"   First memory preview: {memories[0]['content'][:50]}...")
 99 |                 else:
100 |                     print(f"❌ Memory listing failed: {resp.status}")
101 |                     error = await resp.text()
102 |                     print(f"   Error: {error}")
103 |         except Exception as e:
104 |             print(f"❌ Memory listing error: {e}")
105 |         
106 |         # Test 4: Get specific memory
107 |         print("\n4️⃣  Testing specific memory retrieval...")
108 |         try:
109 |             async with session.get(f"{BASE_URL}/api/memories/{content_hash}") as resp:
110 |                 if resp.status == 200:
111 |                     memory = await resp.json()
112 |                     print(f"✅ Retrieved specific memory")
113 |                     print(f"   Content: {memory['content'][:50]}...")
114 |                     print(f"   Tags: {memory['tags']}")
115 |                     print(f"   Type: {memory['memory_type']}")
116 |                 elif resp.status == 404:
117 |                     print(f"⚠️  Memory not found (this might be expected if get-by-hash isn't implemented)")
118 |                 else:
119 |                     print(f"❌ Memory retrieval failed: {resp.status}")
120 |                     error = await resp.text()
121 |                     print(f"   Error: {error}")
122 |         except Exception as e:
123 |             print(f"❌ Memory retrieval error: {e}")
124 |         
125 |         # Test 5: Filter by tag
126 |         print("\n5️⃣  Testing tag filtering...")
127 |         try:
128 |             async with session.get(f"{BASE_URL}/api/memories?tag=test") as resp:
129 |                 if resp.status == 200:
130 |                     result = await resp.json()
131 |                     memories = result["memories"]
132 |                     print(f"✅ Retrieved {len(memories)} memories with tag 'test'")
133 |                     if memories:
134 |                         for memory in memories[:2]:  # Show first 2
135 |                             print(f"   - {memory['content'][:40]}... (tags: {memory['tags']})")
136 |                 else:
137 |                     print(f"❌ Tag filtering failed: {resp.status}")
138 |         except Exception as e:
139 |             print(f"❌ Tag filtering error: {e}")
140 |         
141 |         # Test 6: Delete memory
142 |         print("\n6️⃣  Testing memory deletion...")
143 |         try:
144 |             async with session.delete(f"{BASE_URL}/api/memories/{content_hash}") as resp:
145 |                 if resp.status == 200:
146 |                     result = await resp.json()
147 |                     if result["success"]:
148 |                         print(f"✅ Memory deleted successfully")
149 |                         print(f"   Message: {result['message']}")
150 |                     else:
151 |                         print(f"❌ Memory deletion failed: {result['message']}")
152 |                 else:
153 |                     print(f"❌ Memory deletion failed: {resp.status}")
154 |                     error = await resp.text()
155 |                     print(f"   Error: {error}")
156 |         except Exception as e:
157 |             print(f"❌ Memory deletion error: {e}")
158 |         
159 |         # Test 7: Verify deletion
160 |         print("\n7️⃣  Verifying memory deletion...")
161 |         try:
162 |             async with session.get(f"{BASE_URL}/api/memories/{content_hash}") as resp:
163 |                 if resp.status == 404:
164 |                     print(f"✅ Memory successfully deleted (404 as expected)")
165 |                 elif resp.status == 200:
166 |                     print(f"⚠️  Memory still exists after deletion")
167 |                 else:
168 |                     print(f"❓ Unexpected response: {resp.status}")
169 |         except Exception as e:
170 |             print(f"❌ Deletion verification error: {e}")
171 |         
172 |         print("\n" + "=" * 50)
173 |         print("🎉 Memory CRUD testing completed!")
174 | 
175 | 
176 | if __name__ == "__main__":
177 |     asyncio.run(test_memory_crud())
```

--------------------------------------------------------------------------------
/docs/first-time-setup.md:
--------------------------------------------------------------------------------

```markdown
  1 | # First-Time Setup Guide
  2 | 
  3 | This guide explains what to expect when running MCP Memory Service for the first time.
  4 | 
  5 | ## 🎯 What to Expect on First Run
  6 | 
  7 | When you start the MCP Memory Service for the first time, you'll see several warnings and messages. **This is completely normal behavior** as the service initializes and downloads necessary components.
  8 | 
  9 | ## 📋 Normal First-Time Warnings
 10 | 
 11 | ### 1. Snapshots Directory Warning
 12 | ```
 13 | WARNING:mcp_memory_service.storage.sqlite_vec:Failed to load from cache: No snapshots directory
 14 | ```
 15 | 
 16 | **What it means:** 
 17 | - The service is checking for previously downloaded embedding models
 18 | - On first run, no cache exists yet, so this warning appears
 19 | - The service will automatically download the model
 20 | 
 21 | **This is normal:** ✅ Expected on first run
 22 | 
 23 | ### 2. TRANSFORMERS_CACHE Warning
 24 | ```
 25 | WARNING: Using TRANSFORMERS_CACHE is deprecated
 26 | ```
 27 | 
 28 | **What it means:**
 29 | - This is an informational warning from the Hugging Face library
 30 | - It doesn't affect the service functionality
 31 | - The service handles caching internally
 32 | 
 33 | **This is normal:** ✅ Can be safely ignored
 34 | 
 35 | ### 3. Model Download Progress
 36 | ```
 37 | Downloading model 'all-MiniLM-L6-v2'...
 38 | ```
 39 | 
 40 | **What it means:**
 41 | - The service is downloading the embedding model (approximately 25MB)
 42 | - This happens only once on first setup
 43 | - Download time: 1-2 minutes on average internet connection
 44 | 
 45 | **This is normal:** ✅ One-time download
 46 | 
 47 | ## 🚦 Success Indicators
 48 | 
 49 | After successful first-time setup, you should see:
 50 | 
 51 | ```
 52 | INFO: SQLite-vec storage initialized successfully with embedding dimension: 384
 53 | INFO: Memory service started on port 8443
 54 | INFO: Ready to accept connections
 55 | ```
 56 | 
 57 | ## 📊 First-Time Setup Timeline
 58 | 
 59 | | Step | Duration | What's Happening |
 60 | |------|----------|-----------------|
 61 | | 1. Service Start | Instant | Loading configuration |
 62 | | 2. Cache Check | 1-2 seconds | Checking for existing models |
 63 | | 3. Model Download | 1-2 minutes | Downloading embedding model (~25MB) |
 64 | | 4. Model Loading | 5-10 seconds | Loading model into memory |
 65 | | 5. Database Init | 2-3 seconds | Creating database structure |
 66 | | 6. Ready | - | Service is ready to use |
 67 | 
 68 | **Total first-time setup:** 2-3 minutes
 69 | 
 70 | ## 🔄 Subsequent Runs
 71 | 
 72 | After the first successful run:
 73 | - No download warnings will appear
 74 | - Model loads from cache (5-10 seconds)
 75 | - Service starts much faster (10-15 seconds total)
 76 | 
 77 | ## 🐍 Python 3.13 Compatibility
 78 | 
 79 | ### Known Issues
 80 | Python 3.13 users may encounter installation issues with **sqlite-vec** due to missing pre-built wheels. The installer now includes automatic fallback methods:
 81 | 
 82 | 1. **Automatic Retry Logic**: Tries multiple installation strategies
 83 | 2. **Source Building**: Attempts to build from source if wheels unavailable
 84 | 3. **GitHub Installation**: Falls back to installing directly from repository
 85 | 4. **Backend Switching**: Option to switch to ChromaDB if sqlite-vec fails
 86 | 
 87 | ### Recommended Solutions
 88 | If you encounter sqlite-vec installation failures on Python 3.13:
 89 | 
 90 | **Option 1: Use Python 3.12 (Recommended)**
 91 | ```bash
 92 | # macOS
 93 | brew install [email protected]
 94 | python3.12 -m venv .venv
 95 | source .venv/bin/activate
 96 | python install.py
 97 | 
 98 | # Ubuntu/Linux
 99 | sudo apt install python3.12 python3.12-venv
100 | python3.12 -m venv .venv
101 | source .venv/bin/activate
102 | python install.py
103 | ```
104 | 
105 | **Option 2: Use ChromaDB Backend**
106 | ```bash
107 | python install.py --storage-backend chromadb
108 | ```
109 | 
110 | **Option 3: Manual sqlite-vec Installation**
111 | ```bash
112 | # Try building from source
113 | pip install --no-binary :all: sqlite-vec
114 | 
115 | # Or install from GitHub
116 | pip install git+https://github.com/asg017/sqlite-vec.git#subdirectory=python
117 | ```
118 | 
119 | ## 🍎 macOS SQLite Extension Issues
120 | 
121 | ### Problem: `AttributeError: 'sqlite3.Connection' object has no attribute 'enable_load_extension'`
122 | 
123 | This error occurs on **macOS with system Python** because it's not compiled with SQLite extension support.
124 | 
125 | **Why this happens:**
126 | - macOS system Python lacks `--enable-loadable-sqlite-extensions`
127 | - The bundled SQLite library doesn't support loadable extensions
128 | - This is a security-focused default configuration
129 | 
130 | **Solutions:**
131 | 
132 | **Option 1: Homebrew Python (Recommended)**
133 | ```bash
134 | # Install Python via Homebrew (includes extension support)
135 | brew install python
136 | hash -r  # Refresh command cache
137 | python3 --version  # Verify you're using Homebrew Python
138 | 
139 | # Then install MCP Memory Service
140 | python3 install.py
141 | ```
142 | 
143 | **Option 2: pyenv with Extension Support**
144 | ```bash
145 | # Install pyenv if not already installed
146 | brew install pyenv
147 | 
148 | # Install Python with extension support
149 | PYTHON_CONFIGURE_OPTS="--enable-loadable-sqlite-extensions" pyenv install 3.12.0
150 | pyenv local 3.12.0
151 | 
152 | # Verify extension support
153 | python3 -c "import sqlite3; conn=sqlite3.connect(':memory:'); conn.enable_load_extension(True); print('Extensions supported!')"
154 | ```
155 | 
156 | **Option 3: Use ChromaDB Backend**
157 | ```bash
158 | # ChromaDB doesn't require SQLite extensions
159 | python3 install.py --storage-backend chromadb
160 | ```
161 | 
162 | ### Verification
163 | Check if your Python supports extensions:
164 | ```bash
165 | python3 -c "
166 | import sqlite3
167 | conn = sqlite3.connect(':memory:')
168 | print('✅ Extension support available' if hasattr(conn, 'enable_load_extension') else '❌ No extension support')
169 | "
170 | ```
171 | 
172 | ## 🐧 Ubuntu/Linux Specific Notes
173 | 
174 | For Ubuntu 24 and other Linux distributions:
175 | 
176 | ### Prerequisites
177 | ```bash
178 | # System dependencies
179 | sudo apt update
180 | sudo apt install python3.10 python3.10-venv python3.10-dev python3-pip
181 | sudo apt install build-essential libblas3 liblapack3 liblapack-dev libblas-dev gfortran
182 | ```
183 | 
184 | ### Recommended Setup
185 | ```bash
186 | # Create virtual environment
187 | python3 -m venv venv
188 | source venv/bin/activate
189 | 
190 | # Install the service
191 | python install.py
192 | 
193 | # Start the service
194 | uv run memory server
195 | ```
196 | 
197 | ## 🔧 Troubleshooting First-Time Issues
198 | 
199 | ### Issue: Download Fails
200 | **Solution:**
201 | - Check internet connection
202 | - Verify firewall/proxy settings
203 | - Clear cache and retry: `rm -rf ~/.cache/huggingface`
204 | 
205 | ### Issue: "No module named 'sentence_transformers'"
206 | **Solution:**
207 | ```bash
208 | pip install sentence-transformers torch
209 | ```
210 | 
211 | ### Issue: Permission Denied
212 | **Solution:**
213 | ```bash
214 | # Fix permissions
215 | chmod +x scripts/*.sh
216 | sudo chown -R $USER:$USER ~/.mcp_memory_service/
217 | ```
218 | 
219 | ### Issue: Service Doesn't Start After Download
220 | **Solution:**
221 | 1. Check logs: `uv run memory server --debug`
222 | 2. Verify installation: `python scripts/verify_environment.py`
223 | 3. Restart with clean state: 
224 |    ```bash
225 |    rm -rf ~/.mcp_memory_service
226 |    uv run memory server
227 |    ```
228 | 
229 | ## ✅ Verification
230 | 
231 | To verify successful setup:
232 | 
233 | ```bash
234 | # Check service health
235 | curl -k https://localhost:8443/api/health
236 | 
237 | # Or using the CLI
238 | uv run memory health
239 | ```
240 | 
241 | Expected response:
242 | ```json
243 | {
244 |   "status": "healthy",
245 |   "storage_backend": "sqlite_vec",
246 |   "model_loaded": true
247 | }
248 | ```
249 | 
250 | ## 🎉 Setup Complete!
251 | 
252 | Once you see the success indicators and the warnings have disappeared on subsequent runs, your MCP Memory Service is fully operational and ready to use!
253 | 
254 | ### Next Steps:
255 | - [Configure Claude Desktop](../README.md#claude-desktop-integration)
256 | - [Store your first memory](../README.md#basic-usage)
257 | - [Explore the API](https://github.com/doobidoo/mcp-memory-service/wiki)
258 | 
259 | ## 📝 Notes
260 | 
261 | - The model download is a one-time operation
262 | - Downloaded models are cached in `~/.cache/huggingface/`
263 | - The service creates a database in `~/.mcp_memory_service/`
264 | - All warnings shown during first-time setup are expected behavior
265 | - If you see different errors (not warnings), check the [Troubleshooting Guide](troubleshooting/general.md)
266 | 
267 | ---
268 | 
269 | Remember: **First-time warnings are normal!** The service is working correctly and setting itself up for optimal performance.
```

--------------------------------------------------------------------------------
/tests/performance/test_hybrid_live.py:
--------------------------------------------------------------------------------

```python
  1 | #!/usr/bin/env python3
  2 | """
  3 | Live performance test of the hybrid storage backend implementation.
  4 | Demonstrates performance, functionality, and sync capabilities under load.
  5 | """
  6 | 
  7 | import asyncio
  8 | import sys
  9 | import time
 10 | import tempfile
 11 | import os
 12 | from pathlib import Path
 13 | 
 14 | # Add src to path for standalone execution
 15 | sys.path.insert(0, str(Path(__file__).parent.parent.parent / 'src'))
 16 | 
 17 | from mcp_memory_service.storage.hybrid import HybridMemoryStorage
 18 | from mcp_memory_service.models.memory import Memory
 19 | import hashlib
 20 | 
 21 | async def test_hybrid_storage():
 22 |     """Test the hybrid storage implementation with live demonstrations."""
 23 | 
 24 |     print("🚀 Testing Hybrid Storage Backend")
 25 |     print("=" * 50)
 26 | 
 27 |     # Create a temporary SQLite database for testing
 28 |     with tempfile.NamedTemporaryFile(suffix='.db', delete=False) as tmp_file:
 29 |         db_path = tmp_file.name
 30 | 
 31 |     try:
 32 |         # Initialize hybrid storage (without Cloudflare for this demo)
 33 |         print("📍 Step 1: Initializing Hybrid Storage")
 34 |         storage = HybridMemoryStorage(
 35 |             sqlite_db_path=db_path,
 36 |             embedding_model="all-MiniLM-L6-v2",
 37 |             cloudflare_config=None,  # Will operate in SQLite-only mode
 38 |             sync_interval=30,  # Short interval for demo
 39 |             batch_size=5
 40 |         )
 41 | 
 42 |         print("   Initializing storage backend...")
 43 |         await storage.initialize()
 44 |         print(f"   ✅ Storage initialized")
 45 |         print(f"   📊 Primary: {storage.primary.__class__.__name__}")
 46 |         print(f"   📊 Secondary: {storage.secondary.__class__.__name__ if storage.secondary else 'None (SQLite-only mode)'}")
 47 |         print(f"   📊 Sync Service: {'Running' if storage.sync_service and storage.sync_service.is_running else 'Disabled'}")
 48 |         print()
 49 | 
 50 |         # Test 1: Performance measurement
 51 |         print("📍 Step 2: Performance Test")
 52 |         memories_to_test = []
 53 | 
 54 |         for i in range(5):
 55 |             content = f"Performance test memory #{i+1} - testing hybrid storage speed"
 56 |             content_hash = hashlib.sha256(content.encode()).hexdigest()
 57 | 
 58 |             memory = Memory(
 59 |                 content=content,
 60 |                 content_hash=content_hash,
 61 |                 tags=["hybrid", "test", f"batch_{i}"],
 62 |                 memory_type="performance_test",
 63 |                 metadata={"test_batch": i, "test_type": "performance"},
 64 |                 created_at=time.time()
 65 |             )
 66 |             memories_to_test.append(memory)
 67 | 
 68 |         # Measure write performance
 69 |         print("   Testing write performance...")
 70 |         write_times = []
 71 |         for i, memory in enumerate(memories_to_test):
 72 |             start_time = time.time()
 73 |             success, message = await storage.store(memory)
 74 |             duration = time.time() - start_time
 75 |             write_times.append(duration)
 76 | 
 77 |             if success:
 78 |                 print(f"   ✅ Write #{i+1}: {duration*1000:.1f}ms")
 79 |             else:
 80 |                 print(f"   ❌ Write #{i+1} failed: {message}")
 81 | 
 82 |         avg_write_time = sum(write_times) / len(write_times)
 83 |         print(f"   📊 Average write time: {avg_write_time*1000:.1f}ms")
 84 |         print()
 85 | 
 86 |         # Test 2: Read performance
 87 |         print("📍 Step 3: Read Performance Test")
 88 |         read_times = []
 89 | 
 90 |         for i in range(3):
 91 |             start_time = time.time()
 92 |             results = await storage.retrieve("performance test", n_results=5)
 93 |             duration = time.time() - start_time
 94 |             read_times.append(duration)
 95 | 
 96 |             print(f"   ✅ Read #{i+1}: {duration*1000:.1f}ms ({len(results)} results)")
 97 | 
 98 |         avg_read_time = sum(read_times) / len(read_times)
 99 |         print(f"   📊 Average read time: {avg_read_time*1000:.1f}ms")
100 |         print()
101 | 
102 |         # Test 3: Different operations
103 |         print("📍 Step 4: Testing Various Operations")
104 | 
105 |         # Search by tags
106 |         start_time = time.time()
107 |         tagged_memories = await storage.search_by_tags(["hybrid"])
108 |         tag_search_time = time.time() - start_time
109 |         print(f"   ✅ Tag search: {tag_search_time*1000:.1f}ms ({len(tagged_memories)} results)")
110 | 
111 |         # Get stats
112 |         start_time = time.time()
113 |         stats = await storage.get_stats()
114 |         stats_time = time.time() - start_time
115 |         print(f"   ✅ Stats retrieval: {stats_time*1000:.1f}ms")
116 |         print(f"      - Backend: {stats.get('storage_backend')}")
117 |         print(f"      - Total memories: {stats.get('total_memories', 0)}")
118 |         print(f"      - Sync enabled: {stats.get('sync_enabled', False)}")
119 | 
120 |         # Test delete
121 |         if memories_to_test:
122 |             test_memory = memories_to_test[0]
123 |             start_time = time.time()
124 |             success, message = await storage.delete(test_memory.content_hash)
125 |             delete_time = time.time() - start_time
126 |             print(f"   ✅ Delete operation: {delete_time*1000:.1f}ms ({'Success' if success else 'Failed'})")
127 | 
128 |         print()
129 | 
130 |         # Test 4: Concurrent operations
131 |         print("📍 Step 5: Concurrent Operations Test")
132 | 
133 |         async def store_memory(content_suffix):
134 |             content = f"Concurrent test memory {content_suffix}"
135 |             content_hash = hashlib.sha256(content.encode()).hexdigest()
136 | 
137 |             memory = Memory(
138 |                 content=content,
139 |                 content_hash=content_hash,
140 |                 tags=["concurrent", "hybrid"],
141 |                 memory_type="concurrent_test",
142 |                 metadata={"test_id": content_suffix},
143 |                 created_at=time.time()
144 |             )
145 |             return await storage.store(memory)
146 | 
147 |         start_time = time.time()
148 |         concurrent_tasks = [store_memory(i) for i in range(10)]
149 |         results = await asyncio.gather(*concurrent_tasks)
150 |         concurrent_time = time.time() - start_time
151 | 
152 |         successful_ops = sum(1 for success, _ in results if success)
153 |         print(f"   ✅ Concurrent operations: {concurrent_time*1000:.1f}ms")
154 |         print(f"      - Operations: 10 concurrent stores")
155 |         print(f"      - Successful: {successful_ops}/10")
156 |         print(f"      - Avg per operation: {(concurrent_time/10)*1000:.1f}ms")
157 |         print()
158 | 
159 |         # Final stats
160 |         print("📍 Step 6: Final Statistics")
161 |         final_stats = await storage.get_stats()
162 |         print(f"   📊 Total memories stored: {final_stats.get('total_memories', 0)}")
163 |         print(f"   📊 Storage backend: {final_stats.get('storage_backend')}")
164 | 
165 |         if storage.sync_service:
166 |             sync_status = await storage.sync_service.get_sync_status()
167 |             print(f"   📊 Sync queue size: {sync_status.get('queue_size', 0)}")
168 |             print(f"   📊 Operations processed: {sync_status.get('stats', {}).get('operations_processed', 0)}")
169 | 
170 |         print()
171 |         print("🎉 Hybrid Storage Test Complete!")
172 |         print("=" * 50)
173 | 
174 |         # Performance summary
175 |         print("📊 PERFORMANCE SUMMARY:")
176 |         print(f"   • Average Write: {avg_write_time*1000:.1f}ms")
177 |         print(f"   • Average Read:  {avg_read_time*1000:.1f}ms")
178 |         print(f"   • Tag Search:    {tag_search_time*1000:.1f}ms")
179 |         print(f"   • Stats Query:   {stats_time*1000:.1f}ms")
180 |         print(f"   • Delete Op:     {delete_time*1000:.1f}ms")
181 |         print(f"   • Concurrent:    {(concurrent_time/10)*1000:.1f}ms per op")
182 | 
183 |         # Cleanup
184 |         await storage.close()
185 | 
186 |     finally:
187 |         # Clean up temp file
188 |         if os.path.exists(db_path):
189 |             os.unlink(db_path)
190 | 
191 | if __name__ == "__main__":
192 |     print("🚀 Hybrid Storage Live Demo")
193 |     print("Testing the new hybrid backend implementation...")
194 |     print()
195 | 
196 |     # Run the async test
197 |     asyncio.run(test_hybrid_storage())
```

--------------------------------------------------------------------------------
/.github/workflows/publish-and-test.yml:
--------------------------------------------------------------------------------

```yaml
  1 | name: Publish and Test (Tags)
  2 | 
  3 | on:
  4 |   push:
  5 |     tags:
  6 |       - 'v*.*.*'
  7 |   workflow_dispatch:
  8 | 
  9 | jobs:
 10 |   test-uvx-compatibility:
 11 |     runs-on: ubuntu-latest
 12 |     name: Test uvx compatibility
 13 |     
 14 |     steps:
 15 |     - name: Checkout repository
 16 |       uses: actions/checkout@v4
 17 | 
 18 |     - name: Set up Python
 19 |       uses: actions/setup-python@v4
 20 |       with:
 21 |         python-version: '3.11'
 22 | 
 23 |     - name: Install uv
 24 |       run: |
 25 |         curl -LsSf https://astral.sh/uv/install.sh | sh
 26 |         source $HOME/.cargo/env
 27 | 
 28 |     - name: Install package locally
 29 |       run: |
 30 |         source $HOME/.cargo/env
 31 |         uv pip install --system -e .
 32 | 
 33 |     - name: Test entry point
 34 |       run: |
 35 |         python -c "import mcp_memory_service.server; print('✓ Package can be imported')"
 36 |         python -m mcp_memory_service.server --version
 37 | 
 38 |     - name: Test uvx functionality
 39 |       run: |
 40 |         source $HOME/.cargo/env
 41 |         # uvx is now part of uv itself, no separate installation needed
 42 |         uv --version
 43 |         
 44 |         # Build wheel for uvx testing
 45 |         uv build
 46 |         
 47 |         # Test if uvx command is available
 48 |         which uvx || echo "uvx command provided by uv"
 49 |         
 50 |         # Test package structure compatibility
 51 |         echo "✓ Package structure compatible with uvx"
 52 | 
 53 |   test-docker-build:
 54 |     runs-on: ubuntu-latest
 55 |     name: Test Docker build
 56 |     
 57 |     steps:
 58 |     - name: Checkout repository
 59 |       uses: actions/checkout@v4
 60 | 
 61 |     - name: Set up Docker Buildx
 62 |       uses: docker/setup-buildx-action@v3
 63 | 
 64 |     - name: Debug - Check required files
 65 |       run: |
 66 |         echo "=== Checking required files for Docker build ==="
 67 |         echo "Dockerfile exists:" && ls -la tools/docker/Dockerfile
 68 |         echo "Source directory exists:" && ls -la src/
 69 |         echo "Entrypoint scripts exist:" && ls -la tools/docker/docker-entrypoint*.sh
 70 |         echo "Utils scripts exist:" && ls -la scripts/utils/
 71 |         echo "pyproject.toml exists:" && ls -la pyproject.toml
 72 |         echo "uv.lock exists:" && ls -la uv.lock
 73 | 
 74 |     - name: Build Docker image
 75 |       uses: docker/build-push-action@v5
 76 |       with:
 77 |         context: .
 78 |         file: ./tools/docker/Dockerfile
 79 |         platforms: linux/amd64
 80 |         push: false
 81 |         load: true
 82 |         tags: mcp-memory-service:test
 83 |         cache-from: type=gha
 84 |         cache-to: type=gha,mode=max
 85 |         build-args: |
 86 |           SKIP_MODEL_DOWNLOAD=true
 87 | 
 88 |     - name: Test Docker image
 89 |       run: |
 90 |         # Test image can be created (override entrypoint to run python directly)
 91 |         docker run --rm --entrypoint="" mcp-memory-service:test python -c "print('✓ Docker image works')"
 92 |         
 93 |         # Test that the server can show help
 94 |         docker run --rm mcp-memory-service:test --help > /dev/null && echo "✓ Server help works"
 95 | 
 96 |   publish-docker:
 97 |     needs: [test-uvx-compatibility, test-docker-build]
 98 |     runs-on: ubuntu-latest
 99 |     name: Publish Docker image
100 |     if: github.event_name != 'pull_request'
101 |     permissions:
102 |       contents: read
103 |       packages: write
104 |       id-token: write
105 |     
106 |     steps:
107 |     - name: Checkout repository
108 |       uses: actions/checkout@v4
109 | 
110 |     - name: Set up Docker Buildx
111 |       uses: docker/setup-buildx-action@v3
112 | 
113 |     - name: Debug - Check required files for GHCR build
114 |       run: |
115 |         echo "=== Checking required files for GHCR Docker build ==="
116 |         echo "Dockerfile exists:" && ls -la tools/docker/Dockerfile
117 |         echo "Source directory exists:" && ls -la src/
118 |         echo "Entrypoint scripts exist:" && ls -la tools/docker/docker-entrypoint*.sh
119 |         echo "Utils scripts exist:" && ls -la scripts/utils/
120 |         echo "pyproject.toml exists:" && ls -la pyproject.toml
121 |         echo "uv.lock exists:" && ls -la uv.lock
122 | 
123 |     - name: Log in to GitHub Container Registry
124 |       uses: docker/login-action@v3
125 |       with:
126 |         registry: ghcr.io
127 |         username: ${{ github.actor }}
128 |         password: ${{ secrets.GITHUB_TOKEN }}
129 | 
130 |     - name: Extract metadata
131 |       id: meta
132 |       uses: docker/metadata-action@v5
133 |       with:
134 |         images: ghcr.io/doobidoo/mcp-memory-service
135 |         tags: |
136 |           type=ref,event=branch
137 |           type=semver,pattern={{version}}
138 |           type=semver,pattern={{major}}.{{minor}}
139 |           type=semver,pattern={{major}}
140 |           type=raw,value=latest,enable={{is_default_branch}}
141 | 
142 |     - name: Build and push Docker image
143 |       uses: docker/build-push-action@v5
144 |       with:
145 |         context: .
146 |         file: ./tools/docker/Dockerfile
147 |         platforms: linux/amd64,linux/arm64
148 |         push: true
149 |         tags: ${{ steps.meta.outputs.tags }}
150 |         labels: ${{ steps.meta.outputs.labels }}
151 |         cache-from: type=gha
152 |         cache-to: type=gha,mode=max
153 |         build-args: |
154 |           SKIP_MODEL_DOWNLOAD=true
155 |         outputs: type=registry
156 | 
157 |   publish-pypi:
158 |     needs: [test-uvx-compatibility, test-docker-build]
159 |     runs-on: ubuntu-latest
160 |     name: Publish to PyPI
161 |     if: github.event_name != 'pull_request'
162 |     permissions:
163 |       id-token: write
164 |       contents: read
165 | 
166 |     steps:
167 |     - name: Checkout repository
168 |       uses: actions/checkout@v4
169 | 
170 |     - name: Set up Python
171 |       uses: actions/setup-python@v4
172 |       with:
173 |         python-version: '3.11'
174 | 
175 |     - name: Install build dependencies
176 |       run: |
177 |         python -m pip install --upgrade pip
178 |         python -m pip install build twine
179 | 
180 |     - name: Build package
181 |       run: python -m build
182 | 
183 |     - name: Publish to PyPI
184 |       env:
185 |         TWINE_USERNAME: __token__
186 |         TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
187 |       run: |
188 |         twine upload dist/*
189 | 
190 |   update-documentation:
191 |     needs: [publish-docker, publish-pypi]
192 |     runs-on: ubuntu-latest
193 |     name: Update documentation
194 |     if: github.event_name != 'pull_request'
195 |     
196 |     steps:
197 |     - name: Checkout repository
198 |       uses: actions/checkout@v4
199 | 
200 |     - name: Update README with GitHub Container Registry info
201 |       run: |
202 |         echo "Docker image published successfully!" >> docker-publish.log
203 |         echo "Available at: ghcr.io/doobidoo/mcp-memory-service" >> docker-publish.log
204 | 
205 |     - name: Create/update installation docs
206 |       run: |
207 |         mkdir -p docs/installation
208 |         cat > docs/installation/github-container-registry.md << 'EOF'
209 |         # GitHub Container Registry Installation
210 |         
211 |         The MCP Memory Service is now available on GitHub Container Registry for easy installation.
212 |         
213 |         ## Quick Start
214 |         
215 |         ```bash
216 |         # Pull the latest image
217 |         docker pull ghcr.io/doobidoo/mcp-memory-service:latest
218 |         
219 |         # Run with default settings
220 |         docker run -d -p 8000:8000 \
221 |           -v $(pwd)/data/chroma_db:/app/chroma_db \
222 |           -v $(pwd)/data/backups:/app/backups \
223 |           ghcr.io/doobidoo/mcp-memory-service:latest
224 |         
225 |         # Run in standalone mode
226 |         docker run -d -p 8000:8000 \
227 |           -e MCP_STANDALONE_MODE=1 \
228 |           -v $(pwd)/data/chroma_db:/app/chroma_db \
229 |           -v $(pwd)/data/backups:/app/backups \
230 |           ghcr.io/doobidoo/mcp-memory-service:latest
231 |         ```
232 |         
233 |         ## Available Tags
234 |         
235 |         - `latest` - Latest stable release
236 |         - `main` - Latest development version
237 |         - `v*.*.*` - Specific version tags
238 |         
239 |         ## uvx Installation
240 |         
241 |         You can also install using uvx (included with uv):
242 |         
243 |         ```bash
244 |         # Install uv if not already installed
245 |         pip install uv
246 |         # Or use the installer script:
247 |         # curl -LsSf https://astral.sh/uv/install.sh | sh
248 |         
249 |         # Install and run the memory service with uvx
250 |         uvx mcp-memory-service
251 |         ```
252 |         EOF
```

--------------------------------------------------------------------------------
/docs/research/code-execution-interface-summary.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Code Execution Interface - Executive Summary
  2 | ## Issue #206 Implementation Guide
  3 | 
  4 | **TL;DR:** Implement Python code API to reduce token consumption by 90-95% while maintaining full backward compatibility. Start with session hooks (75% reduction, 109M+ tokens saved annually).
  5 | 
  6 | ---
  7 | 
  8 | ## The Problem
  9 | 
 10 | Current MCP tool-based architecture consumes excessive tokens:
 11 | - **Session hooks:** 3,600-9,600 tokens per session start
 12 | - **Search operations:** 2,625 tokens for 5 results
 13 | - **Document ingestion:** 57,400 tokens for 50 PDFs
 14 | - **Annual waste:** 17-379 million tokens across user base
 15 | 
 16 | ## The Solution
 17 | 
 18 | Replace verbose MCP tool calls with direct Python code execution:
 19 | 
 20 | ```python
 21 | # Before (625 tokens)
 22 | result = await mcp.call_tool('retrieve_memory', {
 23 |     'query': 'architecture decisions',
 24 |     'limit': 5,
 25 |     'similarity_threshold': 0.7
 26 | })
 27 | 
 28 | # After (25 tokens)
 29 | from mcp_memory_service.api import search
 30 | results = search('architecture decisions', limit=5)
 31 | ```
 32 | 
 33 | ## Key Components
 34 | 
 35 | ### 1. Compact Data Types (91% size reduction)
 36 | 
 37 | ```python
 38 | # CompactMemory: 73 tokens vs 820 tokens for full Memory
 39 | class CompactMemory(NamedTuple):
 40 |     hash: str           # 8-char hash
 41 |     preview: str        # First 200 chars
 42 |     tags: tuple[str]    # Immutable tags
 43 |     created: float      # Unix timestamp
 44 |     score: float        # Relevance score
 45 | ```
 46 | 
 47 | ### 2. Simple API Functions
 48 | 
 49 | ```python
 50 | from mcp_memory_service.api import search, store, health
 51 | 
 52 | # Search (20 tokens)
 53 | results = search("query", limit=5)
 54 | 
 55 | # Store (15 tokens)
 56 | hash = store("content", tags=['note'])
 57 | 
 58 | # Health (5 tokens)
 59 | info = health()
 60 | ```
 61 | 
 62 | ### 3. Hook Integration
 63 | 
 64 | ```javascript
 65 | // Node.js hook with fallback
 66 | try {
 67 |     // Code execution (fast, efficient)
 68 |     const output = execSync('python -c "from mcp_memory_service.api import search; ..."');
 69 |     memories = parseCompactResults(output);
 70 | } catch (error) {
 71 |     // Fallback to MCP tools
 72 |     memories = await mcpClient.retrieve_memory({...});
 73 | }
 74 | ```
 75 | 
 76 | ## Expected Impact
 77 | 
 78 | | Metric | Current | Target | Improvement |
 79 | |--------|---------|--------|-------------|
 80 | | Session hooks | 3,600-9,600 tokens | 900-2,400 | **75% reduction** |
 81 | | Search (5 results) | 2,625 tokens | 385 | **85% reduction** |
 82 | | Store memory | 150 tokens | 15 | **90% reduction** |
 83 | | Annual savings (10 users) | - | 109.5M tokens | **$16.43/year** |
 84 | | Annual savings (100 users) | - | 2.19B tokens | **$328.50/year** |
 85 | 
 86 | ## Implementation Timeline
 87 | 
 88 | ```
 89 | Week 1-2: Core Infrastructure
 90 | ├─ Compact types (CompactMemory, CompactSearchResult)
 91 | ├─ API functions (search, store, health)
 92 | ├─ Tests and benchmarks
 93 | └─ Documentation
 94 | 
 95 | Week 3: Session Hook Migration (HIGHEST PRIORITY)
 96 | ├─ Update session-start.js
 97 | ├─ Add fallback mechanism
 98 | ├─ Validate 75% reduction
 99 | └─ Deploy to beta
100 | 
101 | Week 4-5: Search Operations
102 | ├─ Mid-conversation hooks
103 | ├─ Topic-change hooks
104 | └─ Document best practices
105 | 
106 | Week 6+: Polish & Extensions
107 | ```
108 | 
109 | ## Technical Architecture
110 | 
111 | ### Filesystem Structure
112 | ```
113 | src/mcp_memory_service/
114 | ├── api/                    # NEW: Code execution interface
115 | │   ├── __init__.py        # Public API exports
116 | │   ├── compact.py         # Compact result types
117 | │   ├── search.py          # Search operations
118 | │   ├── storage.py         # Storage operations
119 | │   └── utils.py           # Utilities
120 | ├── models/
121 | │   └── compact.py         # NEW: CompactMemory types
122 | └── server.py              # EXISTING: MCP server (unchanged)
123 | ```
124 | 
125 | ### Key Design Decisions
126 | 
127 | 1. **NamedTuple for Compact Types**
128 |    - ✅ Fast (C-based), immutable, type-safe
129 |    - ✅ 60-90% size reduction
130 |    - ✅ Clear field names
131 | 
132 | 2. **Sync Wrappers**
133 |    - ✅ Hide asyncio complexity
134 |    - ✅ Connection reuse
135 |    - ✅ <10ms overhead
136 | 
137 | 3. **Backward Compatibility**
138 |    - ✅ MCP tools continue working
139 |    - ✅ Gradual opt-in migration
140 |    - ✅ Zero breaking changes
141 | 
142 | ## Validation from Research
143 | 
144 | ### Industry Alignment
145 | - ✅ **Anthropic (Nov 2025):** Official MCP code execution announcement
146 | - ✅ **CodeAgents Framework:** 70%+ token reduction demonstrated
147 | - ✅ **mcp-python-interpreter:** Proven code execution patterns
148 | 
149 | ### Performance Benchmarks
150 | - ✅ **NamedTuple:** 8% faster creation, fastest access
151 | - ✅ **Compact types:** 85-91% token reduction measured
152 | - ✅ **Real-world savings:** 109M+ tokens annually (conservative)
153 | 
154 | ## Risk Assessment
155 | 
156 | | Risk | Severity | Mitigation |
157 | |------|----------|------------|
158 | | Breaking changes | HIGH | Parallel operation, fallback mechanism |
159 | | Performance degradation | MEDIUM | Benchmarks show <5ms overhead |
160 | | Async/sync mismatch | LOW | Sync wrappers with asyncio.run() |
161 | | Connection management | LOW | Global instance with reuse |
162 | | Error handling | LOW | Expand function for debugging |
163 | 
164 | **Overall Risk:** LOW - Incremental approach with proven patterns
165 | 
166 | ## Success Criteria
167 | 
168 | ### Phase 1 (Core Infrastructure)
169 | - ✅ API functions work in sync context
170 | - ✅ Token reduction ≥85% measured
171 | - ✅ Performance overhead <5ms
172 | - ✅ Unit tests ≥90% coverage
173 | 
174 | ### Phase 2 (Session Hooks)
175 | - ✅ Token reduction ≥75% in production
176 | - ✅ Hook execution <500ms
177 | - ✅ Fallback mechanism validates
178 | - ✅ Zero user-reported issues
179 | 
180 | ### Phase 3 (Search Operations)
181 | - ✅ Token reduction ≥90%
182 | - ✅ Migration guide complete
183 | - ✅ Community feedback positive
184 | 
185 | ## Next Steps
186 | 
187 | ### Immediate Actions (This Week)
188 | 1. Create `src/mcp_memory_service/api/` directory structure
189 | 2. Implement `CompactMemory` and `CompactSearchResult` types
190 | 3. Write `search()`, `store()`, `health()` functions
191 | 4. Add unit tests with token benchmarks
192 | 
193 | ### Priority Tasks
194 | 1. **Session hook migration** - Highest impact (3,600 → 900 tokens)
195 | 2. **Documentation** - API reference with examples
196 | 3. **Beta testing** - Validate with real users
197 | 4. **Metrics collection** - Measure actual token savings
198 | 
199 | ## Recommended Reading
200 | 
201 | ### Full Research Document
202 | - `docs/research/code-execution-interface-implementation.md`
203 |   - Comprehensive analysis (10,000+ words)
204 |   - Detailed code examples
205 |   - Industry research findings
206 |   - Complete implementation guide
207 | 
208 | ### Key Sections
209 | 1. **Architecture Recommendations** (Section 3)
210 | 2. **Implementation Examples** (Section 4)
211 | 3. **Migration Approach** (Section 7)
212 | 4. **Success Metrics** (Section 8)
213 | 
214 | ---
215 | 
216 | ## Quick Reference
217 | 
218 | ### Token Savings Calculator
219 | 
220 | ```python
221 | # Current MCP approach
222 | tool_schema = 125 tokens
223 | full_memory = 820 tokens per result
224 | total = tool_schema + (full_memory * num_results)
225 | 
226 | # Example: 5 results
227 | current = 125 + (820 * 5) = 4,225 tokens
228 | 
229 | # Code execution approach
230 | import_cost = 10 tokens (once)
231 | compact_memory = 73 tokens per result
232 | total = import_cost + (compact_memory * num_results)
233 | 
234 | # Example: 5 results
235 | new = 10 + (73 * 5) = 375 tokens
236 | 
237 | # Reduction
238 | reduction = (4225 - 375) / 4225 * 100 = 91.1%
239 | ```
240 | 
241 | ### Common Patterns
242 | 
243 | ```python
244 | # Pattern 1: Simple search
245 | from mcp_memory_service.api import search
246 | results = search("query", limit=5)
247 | for m in results.memories:
248 |     print(f"{m.hash}: {m.preview[:50]}")
249 | 
250 | # Pattern 2: Tag filtering
251 | from mcp_memory_service.api import search_by_tag
252 | results = search_by_tag(['architecture', 'decision'], limit=10)
253 | 
254 | # Pattern 3: Store with fallback
255 | from mcp_memory_service.api import store
256 | try:
257 |     hash = store("content", tags=['note'])
258 |     print(f"Stored: {hash}")
259 | except Exception as e:
260 |     # Fallback to MCP tool
261 |     await mcp_client.store_memory({...})
262 | 
263 | # Pattern 4: Health check
264 | from mcp_memory_service.api import health
265 | info = health()
266 | if info.ready:
267 |     print(f"Backend: {info.backend}, Count: {info.count}")
268 | ```
269 | 
270 | ---
271 | 
272 | **Document Version:** 1.0
273 | **Last Updated:** November 6, 2025
274 | **Status:** Ready for Implementation
275 | **Estimated Effort:** 2-3 weeks (Phase 1-2)
276 | **ROI:** 109M+ tokens saved annually (conservative)
277 | 
```

--------------------------------------------------------------------------------
/scripts/pr/quality_gate.sh:
--------------------------------------------------------------------------------

```bash
  1 | #!/bin/bash
  2 | # scripts/pr/quality_gate.sh - Run all quality checks before PR review
  3 | #
  4 | # Usage: bash scripts/pr/quality_gate.sh <PR_NUMBER> [--with-pyscn]
  5 | # Example: bash scripts/pr/quality_gate.sh 123
  6 | # Example: bash scripts/pr/quality_gate.sh 123 --with-pyscn  # Comprehensive analysis
  7 | 
  8 | set -e
  9 | 
 10 | PR_NUMBER=$1
 11 | RUN_PYSCN=false
 12 | 
 13 | # Parse arguments
 14 | shift  # Remove PR_NUMBER from arguments
 15 | while [[ $# -gt 0 ]]; do
 16 |     case $1 in
 17 |         --with-pyscn)
 18 |             RUN_PYSCN=true
 19 |             shift
 20 |             ;;
 21 |         *)
 22 |             echo "Unknown option: $1"
 23 |             echo "Usage: $0 <PR_NUMBER> [--with-pyscn]"
 24 |             exit 1
 25 |             ;;
 26 |     esac
 27 | done
 28 | 
 29 | if [ -z "$PR_NUMBER" ]; then
 30 |     echo "Usage: $0 <PR_NUMBER> [--with-pyscn]"
 31 |     exit 1
 32 | fi
 33 | 
 34 | if ! command -v gh &> /dev/null; then
 35 |     echo "Error: GitHub CLI (gh) is not installed"
 36 |     exit 1
 37 | fi
 38 | 
 39 | if ! command -v gemini &> /dev/null; then
 40 |     echo "Error: Gemini CLI is not installed"
 41 |     exit 1
 42 | fi
 43 | 
 44 | echo "=== PR Quality Gate for #$PR_NUMBER ==="
 45 | echo ""
 46 | 
 47 | exit_code=0
 48 | warnings=()
 49 | critical_issues=()
 50 | 
 51 | # Get changed Python files
 52 | echo "Fetching changed files..."
 53 | changed_files=$(gh pr diff $PR_NUMBER --name-only | grep '\.py$' || echo "")
 54 | 
 55 | if [ -z "$changed_files" ]; then
 56 |     echo "No Python files changed in this PR."
 57 |     exit 0
 58 | fi
 59 | 
 60 | echo "Changed Python files:"
 61 | echo "$changed_files"
 62 | echo ""
 63 | 
 64 | # Check 1: Code complexity
 65 | echo "=== Check 1: Code Complexity ==="
 66 | echo "$changed_files" | while IFS= read -r file; do
 67 |     if [ -z "$file" ]; then
 68 |         continue
 69 |     fi
 70 | 
 71 |     if [ ! -f "$file" ]; then
 72 |         echo "Skipping $file (file not found in working directory)"
 73 |         continue
 74 |     fi
 75 | 
 76 |     echo "Analyzing: $file"
 77 |     result=$(gemini "Analyze code complexity. Rate each function 1-10 (1=simple, 10=very complex). Report ONLY functions with score >7 in format 'FunctionName: Score X - Reason'. File content:
 78 | 
 79 | $(cat "$file")" 2>&1 || echo "")
 80 | 
 81 |     if echo "$result" | grep -qi "score [89]\|score 10"; then
 82 |         warnings+=("High complexity in $file: $result")
 83 |         exit_code=1
 84 |     fi
 85 | done
 86 | echo ""
 87 | 
 88 | # Check 2: Security scan
 89 | echo "=== Check 2: Security Vulnerabilities ==="
 90 | echo "$changed_files" | while IFS= read -r file; do
 91 |     if [ -z "$file" ]; then
 92 |         continue
 93 |     fi
 94 | 
 95 |     if [ ! -f "$file" ]; then
 96 |         continue
 97 |     fi
 98 | 
 99 |     echo "Scanning: $file"
100 |     # Request machine-parseable output (similar to pre-commit hook)
101 |     result=$(gemini "Security audit. Check for: SQL injection (raw SQL), XSS (unescaped HTML), command injection (os.system, subprocess with shell=True), path traversal, hardcoded secrets.
102 | 
103 | IMPORTANT: Output format:
104 | - If ANY vulnerability found, start response with: VULNERABILITY_DETECTED: [type]
105 | - If NO vulnerabilities found, start response with: SECURITY_CLEAN
106 | - Then provide details
107 | 
108 | File content:
109 | $(cat "$file")" 2>&1 || echo "SECURITY_CLEAN")
110 | 
111 |     # Check for machine-parseable vulnerability marker (more reliable than grep)
112 |     if echo "$result" | grep -q "^VULNERABILITY_DETECTED:"; then
113 |         critical_issues+=("🔴 Security issue in $file: $result")
114 |         exit_code=2
115 |     fi
116 | done
117 | echo ""
118 | 
119 | # Check 3: Test coverage
120 | echo "=== Check 3: Test Coverage ==="
121 | test_files=$(gh pr diff $PR_NUMBER --name-only | grep -c '^tests/.*\.py$' || echo "0")
122 | # Count code files directly from changed_files
123 | code_files=$(echo "$changed_files" | grep -c '\.py$' || echo "0")
124 | 
125 | if [ $code_files -gt 0 ] && [ $test_files -eq 0 ]; then
126 |     warnings+=("No test files added/modified despite $code_files code file(s) changed")
127 |     if [ $exit_code -eq 0 ]; then
128 |         exit_code=1
129 |     fi
130 | fi
131 | echo "Code files changed: $code_files"
132 | echo "Test files changed: $test_files"
133 | echo ""
134 | 
135 | # Check 4: Breaking changes
136 | echo "=== Check 4: Breaking Changes ==="
137 | head_branch=$(gh pr view $PR_NUMBER --json headRefName --jq '.headRefName')
138 | 
139 | # Get API-related changes
140 | api_changes=$(git diff origin/main...origin/$head_branch -- \
141 |     src/mcp_memory_service/tools.py \
142 |     src/mcp_memory_service/web/api/ \
143 |     2>/dev/null || echo "")
144 | 
145 | if [ ! -z "$api_changes" ]; then
146 |     echo "Analyzing API changes..."
147 |     # Truncate to 200 lines (increased from 100) to capture more context while preventing overflow
148 |     # Note: Large PRs may still lose context, but this is a reasonable trade-off for performance
149 |     breaking_result=$(gemini "Analyze for breaking changes. Breaking changes include: removed functions/endpoints, changed signatures (parameters removed/reordered), changed return types, renamed public APIs, changed HTTP paths/methods. Report ONLY if breaking changes found with severity (CRITICAL/HIGH/MEDIUM). Changes:
150 | 
151 | $(echo "$api_changes" | head -200)" 2>&1 || echo "")
152 | 
153 |     if echo "$breaking_result" | grep -qi "breaking\|CRITICAL\|HIGH"; then
154 |         warnings+=("⚠️  Potential breaking changes detected: $breaking_result")
155 |         if [ $exit_code -eq 0 ]; then
156 |             exit_code=1
157 |         fi
158 |     fi
159 | else
160 |     echo "No API changes detected"
161 | fi
162 | echo ""
163 | 
164 | # Check 5: pyscn comprehensive analysis (optional)
165 | if [ "$RUN_PYSCN" = true ]; then
166 |     echo "=== Check 5: pyscn Comprehensive Analysis ==="
167 | 
168 |     if command -v pyscn &> /dev/null; then
169 |         echo "Running pyscn static analysis..."
170 | 
171 |         # Run pyscn analysis (will post comment if successful)
172 |         if bash scripts/pr/run_pyscn_analysis.sh --pr $PR_NUMBER --threshold 50; then
173 |             echo "✅ pyscn analysis passed"
174 |         else
175 |             echo "⚠️  pyscn analysis found quality issues"
176 |             # Note: Don't block on pyscn failures (informational only for now)
177 |             # exit_code can be set to 1 here if you want to block on pyscn failures
178 |         fi
179 |     else
180 |         echo "⚠️  pyscn not installed, skipping comprehensive analysis"
181 |         echo "Install with: pip install pyscn"
182 |     fi
183 |     echo ""
184 | fi
185 | 
186 | # Report results
187 | echo "=== Quality Gate Summary ==="
188 | echo ""
189 | 
190 | if [ $exit_code -eq 0 ]; then
191 |     echo "✅ ALL CHECKS PASSED"
192 |     echo ""
193 |     echo "Quality Gate Results:"
194 |     echo "- Code complexity: ✅ OK"
195 |     echo "- Security scan: ✅ OK"
196 |     echo "- Test coverage: ✅ OK"
197 |     echo "- Breaking changes: ✅ None detected"
198 |     if [ "$RUN_PYSCN" = true ]; then
199 |         echo "- pyscn analysis: ✅ OK (see separate comment)"
200 |     fi
201 |     echo ""
202 | 
203 |     pyscn_note=""
204 |     if [ "$RUN_PYSCN" = true ]; then
205 |         pyscn_note="
206 | - ✅ pyscn comprehensive analysis: See detailed report comment"
207 |     fi
208 | 
209 |     gh pr comment $PR_NUMBER --body "✅ **Quality Gate PASSED**
210 | 
211 | All automated checks completed successfully:
212 | - ✅ Code complexity: OK
213 | - ✅ Security scan: OK
214 | - ✅ Test coverage: OK
215 | - ✅ Breaking changes: None detected${pyscn_note}
216 | 
217 | PR is ready for Gemini review."
218 | 
219 | elif [ $exit_code -eq 2 ]; then
220 |     echo "🔴 CRITICAL FAILURES"
221 |     echo ""
222 |     for issue in "${critical_issues[@]}"; do
223 |         echo "$issue"
224 |     done
225 |     echo ""
226 | 
227 |     # Format issues for comment
228 |     issues_md=$(printf '%s\n' "${critical_issues[@]}" | sed 's/^/- /')
229 | 
230 |     gh pr comment $PR_NUMBER --body "🔴 **Quality Gate FAILED - CRITICAL**
231 | 
232 | Security vulnerabilities detected. PR is blocked until issues are resolved.
233 | 
234 | $issues_md
235 | 
236 | **Action Required:**
237 | Run \`bash scripts/security/scan_vulnerabilities.sh\` locally and fix all security issues before proceeding."
238 | 
239 | else
240 |     echo "⚠️  WARNINGS (non-blocking)"
241 |     echo ""
242 |     for warning in "${warnings[@]}"; do
243 |         echo "- $warning"
244 |     done
245 |     echo ""
246 | 
247 |     # Format warnings for comment
248 |     warnings_md=$(printf '%s\n' "${warnings[@]}" | sed 's/^/- /')
249 | 
250 |     gh pr comment $PR_NUMBER --body "⚠️ **Quality Gate WARNINGS**
251 | 
252 | Some checks require attention (non-blocking):
253 | 
254 | $warnings_md
255 | 
256 | **Recommendation:**
257 | Consider addressing these issues before requesting review to improve code quality."
258 | 
259 | fi
260 | 
261 | exit $exit_code
262 | 
```

--------------------------------------------------------------------------------
/docs/enhancement-roadmap-issue-14.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Memory Awareness Enhancement Roadmap - Issue #14
  2 | 
  3 | ## Executive Summary
  4 | 
  5 | This roadmap outlines the transformation of GitHub issue #14 from a basic external utility to a sophisticated memory-aware Claude Code experience leveraging advanced features like hooks, project awareness, and MCP deep integration.
  6 | 
  7 | ## Phase 1: Automatic Memory Awareness (Weeks 1-2)
  8 | 
  9 | ### 1.1 Session Startup Hooks
 10 | **Goal**: Automatically inject relevant memories when starting a Claude Code session
 11 | 
 12 | **Implementation**:
 13 | ```javascript
 14 | // claude-hooks/session-start.js
 15 | export async function onSessionStart(context) {
 16 |   const projectContext = await detectProjectContext(context.workingDirectory);
 17 |   const relevantMemories = await queryMemoryService({
 18 |     tags: [projectContext.name, 'key-decisions', 'recent-insights'],
 19 |     timeRange: 'last-2-weeks',
 20 |     limit: 8
 21 |   });
 22 |   
 23 |   if (relevantMemories.length > 0) {
 24 |     await injectSystemMessage(`
 25 |       Recent project context from memory:
 26 |       ${formatMemoriesForContext(relevantMemories)}
 27 |     `);
 28 |   }
 29 | }
 30 | ```
 31 | 
 32 | **Features**:
 33 | - Project detection based on git repository and directory structure
 34 | - Smart memory filtering by project relevance and recency
 35 | - Automatic context injection without user intervention
 36 | 
 37 | ### 1.2 Project-Aware Memory Selection
 38 | **Goal**: Intelligently select memories based on current project context
 39 | 
 40 | **Implementation**:
 41 | ```python
 42 | # Enhanced memory retrieval with project awareness
 43 | class ProjectAwareMemoryRetrieval:
 44 |     def select_relevant_memories(self, project_context):
 45 |         # Score memories by relevance to current project
 46 |         memories = self.memory_service.search_by_tags([
 47 |             project_context.name,
 48 |             f"tech:{project_context.language}",
 49 |             "decisions", "architecture", "bugs-fixed"
 50 |         ])
 51 |         
 52 |         # Apply relevance scoring
 53 |         scored_memories = self.score_by_relevance(memories, project_context)
 54 |         return scored_memories[:10]
 55 | ```
 56 | 
 57 | ### 1.3 Conversation Context Injection
 58 | **Goal**: Seamlessly inject memory context into conversation flow
 59 | 
 60 | **Deliverables**:
 61 | - Session initialization hooks
 62 | - Project context detection algorithm
 63 | - Memory relevance scoring system
 64 | - Context formatting and injection utilities
 65 | 
 66 | ## Phase 2: Intelligent Context Updates (Weeks 3-4)
 67 | 
 68 | ### 2.1 Dynamic Memory Loading
 69 | **Goal**: Update memory context as conversation topics evolve
 70 | 
 71 | **Implementation**:
 72 | ```javascript
 73 | // claude-hooks/topic-change.js
 74 | export async function onTopicChange(context, newTopics) {
 75 |   const additionalMemories = await queryMemoryService({
 76 |     semanticSearch: newTopics,
 77 |     excludeAlreadyLoaded: context.loadedMemoryHashes,
 78 |     limit: 5
 79 |   });
 80 |   
 81 |   if (additionalMemories.length > 0) {
 82 |     await updateContext(`
 83 |       Additional relevant context:
 84 |       ${formatMemoriesForContext(additionalMemories)}
 85 |     `);
 86 |   }
 87 | }
 88 | ```
 89 | 
 90 | ### 2.2 Conversation Continuity
 91 | **Goal**: Link conversations across sessions for seamless continuity
 92 | 
 93 | **Features**:
 94 | - Cross-session conversation linking
 95 | - Session outcome consolidation
 96 | - Persistent conversation threads
 97 | 
 98 | ### 2.3 Smart Memory Filtering
 99 | **Goal**: AI-powered memory selection based on conversation analysis
100 | 
101 | **Implementation**:
102 | - Natural language processing for topic extraction
103 | - Semantic similarity matching
104 | - Relevance decay algorithms
105 | - User preference learning
106 | 
107 | ## Phase 3: Advanced Integration Features (Weeks 5-6)
108 | 
109 | ### 3.1 Auto-Tagging Conversations
110 | **Goal**: Automatically categorize and tag conversation outcomes
111 | 
112 | **Implementation**:
113 | ```javascript
114 | // claude-hooks/session-end.js
115 | export async function onSessionEnd(context) {
116 |   const sessionSummary = await analyzeSession(context.conversation);
117 |   const autoTags = await generateTags(sessionSummary);
118 |   
119 |   await storeMemory({
120 |     content: sessionSummary,
121 |     tags: [...autoTags, 'session-outcome', context.project.name],
122 |     type: 'session-summary'
123 |   });
124 | }
125 | ```
126 | 
127 | ### 3.2 Memory Consolidation System
128 | **Goal**: Intelligent organization of session insights and outcomes
129 | 
130 | **Features**:
131 | - Duplicate detection and merging
132 | - Insight extraction and categorization
133 | - Knowledge graph building
134 | - Memory lifecycle management
135 | 
136 | ### 3.3 Cross-Session Intelligence
137 | **Goal**: Maintain knowledge continuity across different coding sessions
138 | 
139 | **Implementation**:
140 | - Session relationship mapping
141 | - Progressive memory building
142 | - Context evolution tracking
143 | - Learning pattern recognition
144 | 
145 | ## Technical Architecture
146 | 
147 | ### Core Components
148 | 
149 | 1. **Memory Hook System**
150 |    - Session lifecycle hooks
151 |    - Project context detection
152 |    - Dynamic memory injection
153 | 
154 | 2. **Intelligent Memory Selection**
155 |    - Relevance scoring algorithms
156 |    - Topic analysis and matching
157 |    - Context-aware filtering
158 | 
159 | 3. **Context Management**
160 |    - Dynamic context updates
161 |    - Memory formatting utilities
162 |    - Conversation continuity tracking
163 | 
164 | 4. **Integration Layer**
165 |    - Claude Code hooks interface
166 |    - MCP Memory Service connector
167 |    - Project structure analysis
168 | 
169 | ### API Enhancements
170 | 
171 | ```python
172 | # New memory service endpoints for Claude Code integration
173 | @app.post("/claude-code/session-context")
174 | async def get_session_context(project: ProjectContext):
175 |     """Get relevant memories for Claude Code session initialization."""
176 |     
177 | @app.post("/claude-code/dynamic-context")  
178 | async def get_dynamic_context(topics: List[str], exclude: List[str]):
179 |     """Get additional context based on evolving conversation topics."""
180 |     
181 | @app.post("/claude-code/consolidate-session")
182 | async def consolidate_session(session_data: SessionData):
183 |     """Store and organize session outcomes with intelligent tagging."""
184 | ```
185 | 
186 | ## Success Metrics
187 | 
188 | ### Phase 1 Targets
189 | - ✅ 100% automatic session context injection
190 | - ✅ <2 second session startup time with memory loading
191 | - ✅ 90%+ relevant memory selection accuracy
192 | 
193 | ### Phase 2 Targets  
194 | - ✅ Real-time context updates based on conversation flow
195 | - ✅ 95%+ conversation continuity across sessions
196 | - ✅ Intelligent topic detection and memory matching
197 | 
198 | ### Phase 3 Targets
199 | - ✅ Fully autonomous memory management
200 | - ✅ Cross-session knowledge building
201 | - ✅ Adaptive learning from user interactions
202 | 
203 | ## Implementation Priority
204 | 
205 | **High Priority (Phase 1)**:
206 | 1. Session startup hooks for automatic memory injection
207 | 2. Project-aware memory selection algorithms
208 | 3. Basic context injection utilities
209 | 
210 | **Medium Priority (Phase 2)**:
211 | 1. Dynamic memory loading based on conversation topics
212 | 2. Cross-session conversation linking
213 | 3. Smart memory filtering enhancements
214 | 
215 | **Enhancement Priority (Phase 3)**:
216 | 1. Auto-tagging and session outcome consolidation
217 | 2. Advanced memory organization systems
218 | 3. Machine learning-based relevance optimization
219 | 
220 | ## Risk Mitigation
221 | 
222 | ### Technical Risks
223 | - **Performance Impact**: Implement lazy loading and caching strategies
224 | - **Context Overload**: Smart filtering and relevance-based selection  
225 | - **Memory Service Availability**: Graceful degradation without memory service
226 | 
227 | ### User Experience Risks
228 | - **Information Overload**: Configurable memory injection levels
229 | - **Privacy Concerns**: Clear memory access controls and user preferences
230 | - **Learning Curve**: Seamless integration with minimal configuration required
231 | 
232 | ## Conclusion
233 | 
234 | This enhancement transforms issue #14 from a basic utility into a revolutionary memory-aware Claude Code experience. By leveraging Claude Code's advanced features, we can deliver the original vision of automatic memory context injection while providing intelligent, context-aware assistance that learns and adapts to user patterns.
235 | 
236 | The phased approach ensures incremental value delivery while building towards a sophisticated memory-aware development environment that fundamentally changes how developers interact with their code and project knowledge.
```

--------------------------------------------------------------------------------
/scripts/maintenance/cleanup_organize.py:
--------------------------------------------------------------------------------

```python
  1 | #!/usr/bin/env python3
  2 | # Copyright 2024 Heinrich Krupp
  3 | #
  4 | # Licensed under the Apache License, Version 2.0 (the "License");
  5 | # you may not use this file except in compliance with the License.
  6 | # You may obtain a copy of the License at
  7 | #
  8 | #     http://www.apache.org/licenses/LICENSE-2.0
  9 | #
 10 | # Unless required by applicable law or agreed to in writing, software
 11 | # distributed under the License is distributed on an "AS IS" BASIS,
 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 | # See the License for the specific language governing permissions and
 14 | # limitations under the License.
 15 | 
 16 | """
 17 | MCP-MEMORY-SERVICE Cleanup and Organization Script
 18 | 
 19 | This script implements the cleanup plan documented in CLEANUP_PLAN.md.
 20 | It creates the necessary directory structure, moves files to their new locations,
 21 | and prepares everything for committing to the new branch.
 22 | """
 23 | 
 24 | import os
 25 | import sys
 26 | import shutil
 27 | from pathlib import Path
 28 | import subprocess
 29 | import datetime
 30 | 
 31 | def run_command(command):
 32 |     """Run a shell command and print the result."""
 33 |     print(f"Running: {command}")
 34 |     result = subprocess.run(command, shell=True, capture_output=True, text=True)
 35 |     if result.returncode != 0:
 36 |         print(f"ERROR: {result.stderr}")
 37 |         return False
 38 |     print(f"SUCCESS: {result.stdout}")
 39 |     return True
 40 | 
 41 | def create_directory(path):
 42 |     """Create a directory if it doesn't exist."""
 43 |     if not os.path.exists(path):
 44 |         print(f"Creating directory: {path}")
 45 |         os.makedirs(path)
 46 |     else:
 47 |         print(f"Directory already exists: {path}")
 48 | 
 49 | def move_file(src, dest):
 50 |     """Move a file from src to dest, creating destination directory if needed."""
 51 |     dest_dir = os.path.dirname(dest)
 52 |     # Only try to create the directory if dest_dir is not empty
 53 |     if dest_dir and not os.path.exists(dest_dir):
 54 |         os.makedirs(dest_dir)
 55 |     
 56 |     if os.path.exists(src):
 57 |         print(f"Moving {src} to {dest}")
 58 |         shutil.move(src, dest)
 59 |     else:
 60 |         print(f"WARNING: Source file does not exist: {src}")
 61 | 
 62 | def copy_file(src, dest):
 63 |     """Copy a file from src to dest, creating destination directory if needed."""
 64 |     dest_dir = os.path.dirname(dest)
 65 |     # Only try to create the directory if dest_dir is not empty
 66 |     if dest_dir and not os.path.exists(dest_dir):
 67 |         os.makedirs(dest_dir)
 68 |     
 69 |     if os.path.exists(src):
 70 |         print(f"Copying {src} to {dest}")
 71 |         shutil.copy2(src, dest)
 72 |     else:
 73 |         print(f"WARNING: Source file does not exist: {src}")
 74 | 
 75 | def create_readme(path, content):
 76 |     """Create a README.md file with the given content."""
 77 |     with open(path, 'w') as f:
 78 |         f.write(content)
 79 |     print(f"Created README: {path}")
 80 | 
 81 | def main():
 82 |     # Change to the repository root directory
 83 |     repo_root = os.getcwd()
 84 |     print(f"Working in repository root: {repo_root}")
 85 |     
 86 |     # 1. Create test directory structure
 87 |     test_dirs = [
 88 |         "tests/integration",
 89 |         "tests/unit",
 90 |         "tests/performance"
 91 |     ]
 92 |     for directory in test_dirs:
 93 |         create_directory(directory)
 94 |     
 95 |     # 2. Create documentation directory structure
 96 |     doc_dirs = [
 97 |         "docs/guides",
 98 |         "docs/implementation",
 99 |         "docs/api",
100 |         "docs/examples"
101 |     ]
102 |     for directory in doc_dirs:
103 |         create_directory(directory)
104 |     
105 |     # 3. Create archive directory
106 |     today = datetime.date.today().strftime("%Y-%m-%d")
107 |     archive_dir = f"archive/{today}"
108 |     create_directory(archive_dir)
109 |     
110 |     # 4. Move test files
111 |     test_files = [
112 |         ("test_chromadb.py", "tests/unit/test_chroma.py"),
113 |         ("test_health_check_fixes.py", "tests/integration/test_storage.py"),
114 |         ("test_issue_5_fix.py", "tests/unit/test_tags.py"),
115 |         ("test_performance_optimizations.py", "tests/performance/test_caching.py")
116 |     ]
117 |     for src, dest in test_files:
118 |         move_file(src, dest)
119 |     
120 |     # 5. Move documentation files
121 |     doc_files = [
122 |         ("HEALTH_CHECK_FIXES_SUMMARY.md", "docs/implementation/health_checks.md"),
123 |         ("PERFORMANCE_OPTIMIZATION_SUMMARY.md", "docs/implementation/performance.md"),
124 |         ("CLAUDE.md", "docs/guides/claude_integration.md")
125 |     ]
126 |     for src, dest in doc_files:
127 |         move_file(src, dest)
128 |     
129 |     # 6. Archive backup files
130 |     archive_files = [
131 |         ("backup_performance_optimization", f"{archive_dir}/backup_performance_optimization")
132 |     ]
133 |     for src, dest in archive_files:
134 |         if os.path.exists(src):
135 |             if os.path.exists(dest):
136 |                 print(f"Archive destination already exists: {dest}")
137 |             else:
138 |                 shutil.copytree(src, dest)
139 |                 print(f"Archived {src} to {dest}")
140 |         else:
141 |             print(f"WARNING: Source directory does not exist: {src}")
142 |     
143 |     # 7. Update CHANGELOG.md
144 |     if os.path.exists("CHANGELOG.md.new"):
145 |         move_file("CHANGELOG.md.new", "CHANGELOG.md")
146 |     
147 |     # 8. Create test README files
148 |     test_readme = """# MCP-MEMORY-SERVICE Tests
149 | 
150 | This directory contains tests for the MCP-MEMORY-SERVICE project.
151 | 
152 | ## Directory Structure
153 | 
154 | - `integration/` - Integration tests between components
155 | - `unit/` - Unit tests for individual components
156 | - `performance/` - Performance benchmarks
157 | 
158 | ## Running Tests
159 | 
160 | ```bash
161 | # Run all tests
162 | pytest
163 | 
164 | # Run specific test category
165 | pytest tests/unit/
166 | pytest tests/integration/
167 | pytest tests/performance/
168 | ```
169 | """
170 |     create_readme("tests/README.md", test_readme)
171 |     
172 |     # 9. Create docs README file
173 |     docs_readme = """# MCP-MEMORY-SERVICE Documentation
174 | 
175 | This directory contains documentation for the MCP-MEMORY-SERVICE project.
176 | 
177 | ## Directory Structure
178 | 
179 | - `guides/` - User guides and tutorials
180 | - `implementation/` - Implementation details and technical documentation
181 | - `api/` - API reference documentation
182 | - `examples/` - Example code and usage patterns
183 | """
184 |     create_readme("docs/README.md", docs_readme)
185 |     
186 |     # 10. Create archive README file
187 |     archive_readme = f"""# Archive Directory
188 | 
189 | This directory contains archived files from previous versions of MCP-MEMORY-SERVICE.
190 | 
191 | ## {today}/
192 | 
193 | - `backup_performance_optimization/` - Backup files from performance optimization work
194 | """
195 |     create_readme(f"{archive_dir}/README.md", archive_readme)
196 |     
197 |     # 11. Create pytest.ini
198 |     pytest_ini = """[pytest]
199 | testpaths = tests
200 | python_files = test_*.py
201 | python_classes = Test*
202 | python_functions = test_*
203 | markers =
204 |     unit: unit tests
205 |     integration: integration tests
206 |     performance: performance tests
207 | """
208 |     with open("pytest.ini", 'w') as f:
209 |         f.write(pytest_ini)
210 |     print("Created pytest.ini")
211 |     
212 |     # 12. Create conftest.py
213 |     conftest = """import pytest
214 | import os
215 | import sys
216 | import tempfile
217 | import shutil
218 | 
219 | # Add src directory to Python path
220 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
221 | 
222 | @pytest.fixture
223 | def temp_db_path():
224 |     '''Create a temporary directory for ChromaDB testing.'''
225 |     temp_dir = tempfile.mkdtemp()
226 |     yield temp_dir
227 |     # Clean up after test
228 |     shutil.rmtree(temp_dir)
229 | """
230 |     with open("tests/conftest.py", 'w') as f:
231 |         f.write(conftest)
232 |     print("Created tests/conftest.py")
233 |     
234 |     print("\nCleanup and organization completed!")
235 |     print("Next steps:")
236 |     print("1. Verify all files are in their correct locations")
237 |     print("2. Run tests to ensure everything still works")
238 |     print("3. Create a new git branch and commit the changes")
239 |     print("   git checkout -b feature/cleanup-and-organization")
240 |     print("   git add .")
241 |     print("   git commit -m \"Organize tests, documentation, and archive old files\"")
242 |     print("4. Push the branch for hardware testing")
243 |     print("   git push origin feature/cleanup-and-organization")
244 | 
245 | if __name__ == "__main__":
246 |     main()
247 | 
```

--------------------------------------------------------------------------------
/archive/docs-removed-2025-08-23/complete-setup-guide.md:
--------------------------------------------------------------------------------

```markdown
  1 | # MCP Memory Service - Complete Setup Guide
  2 | 
  3 | ## ✅ Successfully Configured Features
  4 | 
  5 | ### 🧠 **Consolidation System**
  6 | - **Exponential Decay**: Memory aging with retention periods
  7 | - **Creative Associations**: Auto-discovery of memory connections  
  8 | - **Semantic Clustering**: DBSCAN algorithm grouping
  9 | - **Memory Compression**: 500-char summaries with originals preserved
 10 | - **Controlled Forgetting**: Relevance-based archival
 11 | - **Automated Scheduling**: Daily/weekly/monthly runs
 12 | 
 13 | ### 🌐 **mDNS Multi-Client HTTPS**
 14 | - **Service Name**: `memory.local` (clean, no port needed)
 15 | - **Service Type**: `_http._tcp.local.` (standard HTTP service)
 16 | - **Port**: 443 (standard HTTPS)
 17 | - **Auto-Discovery**: Zero-configuration client setup
 18 | - **HTTPS**: Self-signed certificates (auto-generated)
 19 | - **Multi-Interface**: Available on all network interfaces
 20 | - **Real-time Updates**: Server-Sent Events (SSE)
 21 | - **Security**: Non-root binding via CAP_NET_BIND_SERVICE
 22 | 
 23 | ### 🚀 **Auto-Startup Service**
 24 | - **Systemd Integration**: Starts on boot automatically
 25 | - **Auto-Restart**: Recovers from failures
 26 | - **User Service**: Runs as regular user (not root)
 27 | - **Logging**: Integrated with systemd journal
 28 | 
 29 | ## 📋 **Complete Installation Steps**
 30 | 
 31 | ### **1. Initial Setup**
 32 | ```bash
 33 | # Create virtual environment and install
 34 | python3 -m venv venv
 35 | source venv/bin/activate
 36 | python install.py --server-mode --enable-http-api
 37 | ```
 38 | 
 39 | ### **2. Configure Auto-Startup**
 40 | ```bash
 41 | # Install systemd service
 42 | bash install_service.sh
 43 | 
 44 | # Update service configuration (fixed version)
 45 | ./update_service.sh
 46 | 
 47 | # Start service
 48 | sudo systemctl start mcp-memory
 49 | 
 50 | # Verify it's running
 51 | sudo systemctl status mcp-memory
 52 | ```
 53 | 
 54 | ### **3. Configure Firewall**
 55 | ```bash
 56 | # Allow mDNS discovery
 57 | sudo ufw allow 5353/udp
 58 | 
 59 | # Allow HTTPS server
 60 | sudo ufw allow 8000/tcp
 61 | ```
 62 | 
 63 | ## 🔧 **Service Configuration**
 64 | 
 65 | ### **Environment Variables**
 66 | ```bash
 67 | MCP_CONSOLIDATION_ENABLED=true
 68 | MCP_MDNS_ENABLED=true  
 69 | MCP_HTTPS_ENABLED=true
 70 | MCP_MDNS_SERVICE_NAME="memory"
 71 | MCP_HTTP_HOST=0.0.0.0
 72 | MCP_HTTP_PORT=8000
 73 | MCP_MEMORY_STORAGE_BACKEND=sqlite_vec
 74 | MCP_API_KEY=mcp-0b1ccbde2197a08dcb12d41af4044be6
 75 | ```
 76 | 
 77 | ### **Consolidation Settings**
 78 | - **Retention Periods**: Critical (365d), Reference (180d), Standard (30d), Temporary (7d)
 79 | - **Association Discovery**: Similarity range 0.3-0.7, max 100 pairs per run
 80 | - **Clustering**: DBSCAN algorithm, minimum 5 memories per cluster
 81 | - **Compression**: 500 character summaries, preserve originals
 82 | - **Forgetting**: Relevance threshold 0.1, 90-day access threshold
 83 | - **Schedule**: Daily 2AM, Weekly Sunday 3AM, Monthly 1st 4AM
 84 | 
 85 | ## 🌐 **Access Points**
 86 | 
 87 | ### **Local Access**
 88 | - **Dashboard**: https://localhost:443 or https://memory.local
 89 | - **API Documentation**: https://memory.local/api/docs  
 90 | - **Health Check**: https://memory.local/api/health
 91 | - **SSE Events**: https://memory.local/api/events
 92 | - **Connection Stats**: https://memory.local/api/events/stats
 93 | 
 94 | ### **Network Access**
 95 | - **Clean mDNS**: https://memory.local (no port needed!)
 96 | - **mDNS Discovery**: `memory._http._tcp.local.`
 97 | - **Auto-Discovery**: Clients find service automatically
 98 | - **Standard Port**: 443 (HTTPS default)
 99 | 
100 | ## 🛠️ **Service Management**
101 | 
102 | ### **Using Control Script**
103 | ```bash
104 | ./service_control.sh start     # Start service
105 | ./service_control.sh stop      # Stop service
106 | ./service_control.sh restart   # Restart service  
107 | ./service_control.sh status    # Show status
108 | ./service_control.sh logs      # View live logs
109 | ./service_control.sh health    # Test API health
110 | ```
111 | 
112 | ### **Direct systemctl Commands**
113 | ```bash
114 | sudo systemctl start mcp-memory      # Start
115 | sudo systemctl stop mcp-memory       # Stop
116 | sudo systemctl restart mcp-memory    # Restart
117 | sudo systemctl status mcp-memory     # Status
118 | sudo systemctl enable mcp-memory     # Enable startup
119 | sudo systemctl disable mcp-memory    # Disable startup
120 | sudo journalctl -u mcp-memory -f     # Live logs
121 | ```
122 | 
123 | ## 🔍 **Verification Tests**
124 | 
125 | ### **1. Service Status**
126 | ```bash
127 | sudo systemctl status mcp-memory
128 | # Should show: Active: active (running)
129 | ```
130 | 
131 | ### **2. API Health**  
132 | ```bash
133 | curl -k https://localhost:8000/api/health
134 | # Should return: {"status": "healthy", ...}
135 | ```
136 | 
137 | ### **3. mDNS Discovery**
138 | ```bash
139 | avahi-browse -t _mcp-memory._tcp
140 | # Should show: memory on multiple interfaces
141 | ```
142 | 
143 | ### **4. HTTPS Certificate**
144 | ```bash
145 | openssl s_client -connect localhost:8000 -servername localhost < /dev/null
146 | # Should show certificate details
147 | ```
148 | 
149 | ## 📁 **File Structure**
150 | 
151 | ### **Core Files**
152 | - `mcp-memory.service` - Systemd service configuration
153 | - `install_service.sh` - Service installation script
154 | - `service_control.sh` - Service management script
155 | - `update_service.sh` - Configuration update script
156 | - `test_service.sh` - Debug testing script
157 | 
158 | ### **Setup Scripts**  
159 | - `setup_consolidation_mdns.sh` - Manual startup script
160 | - `COMPLETE_SETUP_GUIDE.md` - This comprehensive guide
161 | - `STARTUP_SETUP_GUIDE.md` - Original startup guide
162 | 
163 | ## 🔐 **Security Configuration**
164 | 
165 | ### **API Authentication**
166 | - **API Key**: `mcp-0b1ccbde2197a08dcb12d41af4044be6`
167 | - **HTTPS Only**: Self-signed certificates for development
168 | - **Local Network**: mDNS discovery limited to local network
169 | 
170 | ### **Systemd Security**
171 | - **User Service**: Runs as `hkr` user (not root)
172 | - **Working Directory**: `/home/hkr/repositories/mcp-memory-service`
173 | - **No Privilege Escalation**: NoNewPrivileges removed for compatibility
174 | 
175 | ## 🎯 **Client Configuration**
176 | 
177 | ### **Claude Desktop Auto-Discovery**
178 | ```json
179 | {
180 |   "mcpServers": {
181 |     "memory": {
182 |       "command": "node",
183 |       "args": ["/path/to/examples/http-mcp-bridge.js"],
184 |       "env": {
185 |         "MCP_MEMORY_AUTO_DISCOVER": "true",
186 |         "MCP_MEMORY_PREFER_HTTPS": "true", 
187 |         "MCP_MEMORY_API_KEY": "mcp-0b1ccbde2197a08dcb12d41af4044be6"
188 |       }
189 |     }
190 |   }
191 | }
192 | ```
193 | 
194 | ### **Manual Connection**
195 | ```json
196 | {
197 |   "mcpServers": {
198 |     "memory": {
199 |       "command": "node", 
200 |       "args": ["/path/to/examples/http-mcp-bridge.js"],
201 |       "env": {
202 |         "MCP_MEMORY_HTTP_ENDPOINT": "https://memory.local/api",
203 |         "MCP_MEMORY_API_KEY": "mcp-0b1ccbde2197a08dcb12d41af4044be6"
204 |       }
205 |     }
206 |   }
207 | }
208 | ```
209 | 
210 | ## 🚨 **Troubleshooting**
211 | 
212 | ### **Service Won't Start**
213 | ```bash
214 | # Check detailed logs
215 | sudo journalctl -u mcp-memory --no-pager -n 50
216 | 
217 | # Test manual startup
218 | ./test_service.sh
219 | 
220 | # Verify virtual environment
221 | ls -la venv/bin/python
222 | ```
223 | 
224 | ### **Can't Connect to API**
225 | ```bash
226 | # Check if service is listening
227 | ss -tlnp | grep :443
228 | 
229 | # Test local connection
230 | curl -k https://memory.local/api/health
231 | 
232 | # Check firewall
233 | sudo ufw status
234 | ```
235 | 
236 | ### **No mDNS Discovery**
237 | ```bash
238 | # Test mDNS
239 | avahi-browse -t _http._tcp | grep memory
240 | 
241 | # Test resolution
242 | avahi-resolve-host-name memory.local
243 | 
244 | # Check network interfaces
245 | ip addr show
246 | 
247 | # Verify multicast support
248 | ping 224.0.0.251
249 | ```
250 | 
251 | ### **Port 443 Conflicts (Pi-hole, etc.)**
252 | ```bash
253 | # Check what's using port 443
254 | sudo netstat -tlnp | grep :443
255 | 
256 | # Disable conflicting services (example: Pi-hole)
257 | sudo systemctl stop pihole-FTL
258 | sudo systemctl disable pihole-FTL
259 | sudo systemctl stop lighttpd
260 | sudo systemctl disable lighttpd
261 | 
262 | # Then restart memory service
263 | sudo systemctl restart mcp-memory
264 | ```
265 | 
266 | ## ✅ **Success Indicators**
267 | 
268 | When everything is working correctly, you should see:
269 | 
270 | 1. **Service Status**: `Active: active (running)`
271 | 2. **API Response**: `{"status": "healthy"}` 
272 | 3. **mDNS Discovery**: Service visible on multiple interfaces
273 | 4. **HTTPS Access**: Dashboard accessible at https://localhost:8000
274 | 5. **Auto-Startup**: Service starts automatically on boot
275 | 6. **Consolidation**: Logs show consolidation system enabled
276 | 7. **Client Connections**: Multiple clients can connect simultaneously
277 | 
278 | ---
279 | 
280 | **🎉 Your MCP Memory Service is now fully operational with consolidation, mDNS auto-discovery, HTTPS, and automatic startup!**
```

--------------------------------------------------------------------------------
/scripts/pr/auto_review.sh:
--------------------------------------------------------------------------------

```bash
  1 | #!/bin/bash
  2 | # scripts/pr/auto_review.sh - Automated PR review loop using Gemini CLI
  3 | #
  4 | # Usage: bash scripts/pr/auto_review.sh <PR_NUMBER> [MAX_ITERATIONS] [SAFE_FIX_MODE]
  5 | # Example: bash scripts/pr/auto_review.sh 123 5 true
  6 | 
  7 | set -e
  8 | 
  9 | # Get script directory for sourcing helpers
 10 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 11 | 
 12 | # Source GraphQL helpers for thread resolution
 13 | if [ -f "$SCRIPT_DIR/lib/graphql_helpers.sh" ]; then
 14 |     source "$SCRIPT_DIR/lib/graphql_helpers.sh"
 15 |     GRAPHQL_AVAILABLE=true
 16 | else
 17 |     echo "Warning: GraphQL helpers not available, thread auto-resolution disabled"
 18 |     GRAPHQL_AVAILABLE=false
 19 | fi
 20 | 
 21 | PR_NUMBER=$1
 22 | MAX_ITERATIONS=${2:-5}
 23 | SAFE_FIX_MODE=${3:-true}
 24 | 
 25 | if [ -z "$PR_NUMBER" ]; then
 26 |     echo "Usage: $0 <PR_NUMBER> [MAX_ITERATIONS] [SAFE_FIX_MODE]"
 27 |     echo "Example: $0 123 5 true"
 28 |     exit 1
 29 | fi
 30 | 
 31 | # Check dependencies
 32 | if ! command -v gh &> /dev/null; then
 33 |     echo "Error: GitHub CLI (gh) is not installed"
 34 |     echo "Install: https://cli.github.com/"
 35 |     exit 1
 36 | fi
 37 | 
 38 | if ! command -v gemini &> /dev/null; then
 39 |     echo "Error: Gemini CLI is not installed"
 40 |     exit 1
 41 | fi
 42 | 
 43 | echo "=== Automated PR Review Loop ==="
 44 | echo "PR Number: #$PR_NUMBER"
 45 | echo "Max Iterations: $MAX_ITERATIONS"
 46 | echo "Safe Fix Mode: $SAFE_FIX_MODE"
 47 | echo "GraphQL Thread Resolution: $([ "$GRAPHQL_AVAILABLE" = true ] && echo "Enabled" || echo "Disabled")"
 48 | echo ""
 49 | 
 50 | # Get repository from git remote (portable across forks)
 51 | REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || echo "doobidoo/mcp-memory-service")
 52 | 
 53 | iteration=1
 54 | approved=false
 55 | 
 56 | while [ $iteration -le $MAX_ITERATIONS ] && [ "$approved" = false ]; do
 57 |     echo "=== Iteration $iteration/$MAX_ITERATIONS ==="
 58 | 
 59 |     # Trigger Gemini review (use /gemini review for inline comments)
 60 |     echo "Requesting Gemini code review (inline comments)..."
 61 |     gh pr comment $PR_NUMBER --body "/gemini review"
 62 | 
 63 |     # Wait for Gemini to process
 64 |     echo "Waiting for Gemini review (90 seconds)..."
 65 |     sleep 90
 66 | 
 67 |     # Fetch latest review status and comments
 68 |     echo "Fetching review feedback..."
 69 | 
 70 |     # Get review state (APPROVED, CHANGES_REQUESTED, COMMENTED)
 71 |     review_state=$(gh pr view $PR_NUMBER --json reviews --jq '[.reviews[] | select(.author.login == "gemini-code-assist[bot]")] | last | .state')
 72 | 
 73 |     # Fetch actual comment bodies for categorization first
 74 |     review_comments=$(gh api "repos/$REPO/pulls/$PR_NUMBER/comments" | \
 75 |         jq -r '[.[] | select(.user.login == "gemini-code-assist[bot]")] | .[] | "- \(.path):\(.line) - \(.body[0:200])"' | \
 76 |         head -50)
 77 | 
 78 |     # Get inline review comments count
 79 |     review_comments_count=$(gh api "repos/$REPO/pulls/$PR_NUMBER/comments" | jq '[.[] | select(.user.login == "gemini-code-assist[bot]")] | length')
 80 | 
 81 |     echo "Review State: $review_state"
 82 |     echo "Inline Comments: $review_comments_count"
 83 | 
 84 |     # Display thread status if GraphQL available
 85 |     if [ "$GRAPHQL_AVAILABLE" = true ]; then
 86 |         thread_stats=$(get_thread_stats "$PR_NUMBER" 2>/dev/null || echo '{"total":0,"resolved":0,"unresolved":0}')
 87 |         total_threads=$(echo "$thread_stats" | jq -r '.total // 0')
 88 |         resolved_threads=$(echo "$thread_stats" | jq -r '.resolved // 0')
 89 |         unresolved_threads=$(echo "$thread_stats" | jq -r '.unresolved // 0')
 90 |         echo "Review Threads: $total_threads total, $resolved_threads resolved, $unresolved_threads unresolved"
 91 |     fi
 92 | 
 93 |     echo ""
 94 | 
 95 |     # Check if approved
 96 |     if [ "$review_state" = "APPROVED" ]; then
 97 |         echo "✅ PR approved by Gemini!"
 98 |         approved=true
 99 |         break
100 |     fi
101 | 
102 |     # If no inline comments, we're done
103 |     if [ "$review_comments_count" -eq 0 ] && [ "$review_state" != "CHANGES_REQUESTED" ]; then
104 |         echo "✅ No issues found in review"
105 |         approved=true
106 |         break
107 |     fi
108 | 
109 |     # Extract actionable issues
110 |     if [ "$SAFE_FIX_MODE" = true ]; then
111 |         echo "Analyzing feedback for safe auto-fixes..."
112 | 
113 |         # Get PR diff
114 |         pr_diff=$(gh pr diff $PR_NUMBER)
115 | 
116 |         # Use Gemini to categorize issues (request JSON format)
117 |         categorization=$(gemini "Categorize these code review comments into a JSON object.
118 | 
119 | Review feedback:
120 | $review_comments
121 | 
122 | Categories:
123 | - safe: Simple fixes (formatting, imports, type hints, docstrings, variable renaming)
124 | - unsafe: Logic changes, API modifications, security-critical code
125 | - non_code: Documentation, discussion, questions
126 | 
127 | IMPORTANT: Output ONLY valid JSON in this exact format:
128 | {
129 |   \"safe\": [\"issue 1\", \"issue 2\"],
130 |   \"unsafe\": [\"issue 1\"],
131 |   \"non_code\": [\"comment 1\"]
132 | }")
133 | 
134 |         echo "$categorization"
135 | 
136 |         # Extract safe issues using jq
137 |         safe_issues=$(echo "$categorization" | jq -r '.safe[]' 2>/dev/null || echo "")
138 | 
139 |         if [ -z "$safe_issues" ]; then
140 |             echo "No safe auto-fixable issues found. Manual intervention required."
141 |             break
142 |         fi
143 | 
144 |         echo ""
145 |         echo "Safe issues to auto-fix:"
146 |         echo "$safe_issues"
147 |         echo ""
148 | 
149 |         # Generate fixes for safe issues
150 |         echo "Generating code fixes..."
151 |         fixes=$(gemini "Generate git diff patches for these safe fixes:
152 | 
153 | Issues to fix:
154 | $safe_issues
155 | 
156 | Current code (PR diff):
157 | $pr_diff
158 | 
159 | Output only the git diff patch that can be applied with 'git apply'. Include file paths and line numbers.")
160 | 
161 |         # Use mktemp for patch file
162 |         patch_file=$(mktemp -t pr_fixes_${PR_NUMBER}_${iteration}.XXXXXX)
163 |         echo "$fixes" > "$patch_file"
164 | 
165 |         # Attempt to apply fixes
166 |         echo "Attempting to apply fixes..."
167 |         if git apply --check "$patch_file" 2>/dev/null; then
168 |             git apply "$patch_file"
169 |             git add -A
170 | 
171 |             # Create commit message
172 |             commit_msg="fix: apply Gemini review feedback (iteration $iteration)
173 | 
174 | Addressed:
175 | $safe_issues
176 | 
177 | Co-Authored-By: Gemini Code Assist <[email protected]>"
178 | 
179 |             git commit -m "$commit_msg"
180 |             git push
181 | 
182 |             echo "✅ Fixes applied and pushed"
183 | 
184 |             # Auto-resolve review threads for files we just fixed
185 |             if [ "$GRAPHQL_AVAILABLE" = true ]; then
186 |                 echo ""
187 |                 echo "Resolving review threads for fixed code..."
188 | 
189 |                 # Get the commit SHA we just created
190 |                 latest_commit=$(git rev-parse HEAD)
191 | 
192 |                 # Run thread resolution in auto mode
193 |                 if bash "$SCRIPT_DIR/resolve_threads.sh" "$PR_NUMBER" "$latest_commit" --auto 2>&1 | grep -q "Resolved:"; then
194 |                     echo "✅ Review threads auto-resolved"
195 |                 else
196 |                     echo "ℹ️  No threads needed resolution"
197 |                 fi
198 |             fi
199 | 
200 |             # Clean up temp file
201 |             rm -f "$patch_file"
202 |         else
203 |             echo "⚠️  Could not auto-apply fixes. Patch saved to $patch_file"
204 |             echo "Manual application required."
205 |             break
206 |         fi
207 |     else
208 |         echo "Manual fix mode enabled. Review feedback above and apply manually."
209 |         break
210 |     fi
211 | 
212 |     iteration=$((iteration + 1))
213 |     echo ""
214 |     echo "Waiting 10 seconds before next iteration..."
215 |     sleep 10
216 | done
217 | 
218 | echo ""
219 | echo "=== Review Loop Complete ==="
220 | 
221 | if [ "$approved" = true ]; then
222 |     echo "🎉 PR #$PR_NUMBER is approved and ready to merge!"
223 |     gh pr comment $PR_NUMBER --body "✅ **Automated Review Complete**
224 | 
225 | All review iterations completed successfully. PR is approved and ready for merge.
226 | 
227 | Iterations: $((iteration - 1))/$MAX_ITERATIONS"
228 |     exit 0
229 | else
230 |     echo "⚠️  Max iterations reached or manual intervention needed"
231 |     gh pr comment $PR_NUMBER --body "⚠️ **Automated Review Incomplete**
232 | 
233 | Review loop completed $((iteration - 1)) iterations but approval not received.
234 | Manual review and intervention may be required.
235 | 
236 | Please review the latest feedback and apply necessary changes."
237 |     exit 1
238 | fi
239 | 
```

--------------------------------------------------------------------------------
/scripts/service/service_utils.py:
--------------------------------------------------------------------------------

```python
  1 | #!/usr/bin/env python3
  2 | """
  3 | Shared utilities for cross-platform service installation.
  4 | Provides common functionality for all platform-specific service installers.
  5 | """
  6 | import os
  7 | import sys
  8 | import json
  9 | import secrets
 10 | import platform
 11 | import subprocess
 12 | from pathlib import Path
 13 | from typing import Dict, Optional, Tuple
 14 | 
 15 | 
 16 | def get_project_root() -> Path:
 17 |     """Get the project root directory."""
 18 |     current_file = Path(__file__).resolve()
 19 |     return current_file.parent.parent
 20 | 
 21 | 
 22 | def get_python_executable() -> str:
 23 |     """Get the current Python executable path."""
 24 |     return sys.executable
 25 | 
 26 | 
 27 | def get_venv_path() -> Optional[Path]:
 28 |     """Get the virtual environment path if in a venv."""
 29 |     if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix):
 30 |         return Path(sys.prefix)
 31 |     return None
 32 | 
 33 | 
 34 | def generate_api_key() -> str:
 35 |     """Generate a secure API key for the service."""
 36 |     return f"mcp-{secrets.token_hex(16)}"
 37 | 
 38 | 
 39 | def get_service_paths() -> Dict[str, Path]:
 40 |     """Get common paths used by the service."""
 41 |     project_root = get_project_root()
 42 |     
 43 |     paths = {
 44 |         'project_root': project_root,
 45 |         'scripts_dir': project_root / 'scripts',
 46 |         'src_dir': project_root / 'src',
 47 |         'venv_dir': get_venv_path() or project_root / 'venv',
 48 |         'config_dir': Path.home() / '.mcp_memory_service',
 49 |         'log_dir': Path.home() / '.mcp_memory_service' / 'logs',
 50 |     }
 51 |     
 52 |     # Ensure config and log directories exist
 53 |     paths['config_dir'].mkdir(parents=True, exist_ok=True)
 54 |     paths['log_dir'].mkdir(parents=True, exist_ok=True)
 55 |     
 56 |     return paths
 57 | 
 58 | 
 59 | def get_service_environment() -> Dict[str, str]:
 60 |     """Get environment variables for the service."""
 61 |     paths = get_service_paths()
 62 |     venv_path = get_venv_path()
 63 |     
 64 |     env = {
 65 |         'PYTHONPATH': str(paths['src_dir']),
 66 |         'MCP_MEMORY_STORAGE_BACKEND': os.getenv('MCP_MEMORY_STORAGE_BACKEND', 'sqlite_vec'),
 67 |         'MCP_HTTP_ENABLED': 'true',
 68 |         'MCP_HTTP_HOST': '0.0.0.0',
 69 |         'MCP_HTTP_PORT': '8000',
 70 |         'MCP_HTTPS_ENABLED': 'true',
 71 |         'MCP_MDNS_ENABLED': 'true',
 72 |         'MCP_MDNS_SERVICE_NAME': 'memory',
 73 |         'MCP_CONSOLIDATION_ENABLED': 'true',
 74 |     }
 75 |     
 76 |     # Add venv to PATH if available
 77 |     if venv_path:
 78 |         bin_dir = venv_path / ('Scripts' if platform.system() == 'Windows' else 'bin')
 79 |         current_path = os.environ.get('PATH', '')
 80 |         env['PATH'] = f"{bin_dir}{os.pathsep}{current_path}"
 81 |     
 82 |     return env
 83 | 
 84 | 
 85 | def save_service_config(config: Dict[str, any]) -> Path:
 86 |     """Save service configuration to file."""
 87 |     paths = get_service_paths()
 88 |     config_file = paths['config_dir'] / 'service_config.json'
 89 |     
 90 |     with open(config_file, 'w') as f:
 91 |         json.dump(config, f, indent=2)
 92 |     
 93 |     return config_file
 94 | 
 95 | 
 96 | def load_service_config() -> Optional[Dict[str, any]]:
 97 |     """Load service configuration from file."""
 98 |     paths = get_service_paths()
 99 |     config_file = paths['config_dir'] / 'service_config.json'
100 |     
101 |     if config_file.exists():
102 |         with open(config_file, 'r') as f:
103 |             return json.load(f)
104 |     return None
105 | 
106 | 
107 | def check_dependencies() -> Tuple[bool, str]:
108 |     """Check if all required dependencies are installed."""
109 |     try:
110 |         # Check Python version
111 |         if sys.version_info < (3, 10):
112 |             return False, f"Python 3.10+ required, found {sys.version}"
113 |         
114 |         # Check if in virtual environment (recommended)
115 |         if not get_venv_path():
116 |             print("WARNING: Not running in a virtual environment")
117 |         
118 |         # Check core dependencies
119 |         required_modules = [
120 |             'mcp',
121 |             'chromadb',
122 |             'sentence_transformers',
123 |         ]
124 |         
125 |         missing = []
126 |         for module in required_modules:
127 |             try:
128 |                 __import__(module)
129 |             except ImportError:
130 |                 missing.append(module)
131 |         
132 |         if missing:
133 |             return False, f"Missing dependencies: {', '.join(missing)}"
134 |         
135 |         return True, "All dependencies satisfied"
136 |         
137 |     except Exception as e:
138 |         return False, f"Error checking dependencies: {str(e)}"
139 | 
140 | 
141 | def get_service_command() -> list:
142 |     """Get the command to run the service."""
143 |     paths = get_service_paths()
144 |     python_exe = get_python_executable()
145 |     
146 |     # Use HTTP server script if available, otherwise fall back to main server
147 |     http_server = paths['scripts_dir'] / 'run_http_server.py'
148 |     main_server = paths['scripts_dir'] / 'run_memory_server.py'
149 |     
150 |     if http_server.exists():
151 |         return [python_exe, str(http_server)]
152 |     elif main_server.exists():
153 |         return [python_exe, str(main_server)]
154 |     else:
155 |         # Fall back to module execution
156 |         return [python_exe, '-m', 'mcp_memory_service.server']
157 | 
158 | 
159 | def test_service_startup() -> Tuple[bool, str]:
160 |     """Test if the service can start successfully."""
161 |     try:
162 |         cmd = get_service_command()
163 |         env = os.environ.copy()
164 |         env.update(get_service_environment())
165 |         
166 |         # Try to start the service briefly
167 |         proc = subprocess.Popen(
168 |             cmd,
169 |             env=env,
170 |             stdout=subprocess.PIPE,
171 |             stderr=subprocess.PIPE,
172 |             text=True
173 |         )
174 |         
175 |         # Give it a moment to start
176 |         import time
177 |         time.sleep(2)
178 |         
179 |         # Check if process is still running
180 |         if proc.poll() is None:
181 |             # Service started successfully, terminate it
182 |             proc.terminate()
183 |             proc.wait(timeout=5)
184 |             return True, "Service starts successfully"
185 |         else:
186 |             # Process exited, get error
187 |             stdout, stderr = proc.communicate()
188 |             error_msg = stderr or stdout or "Unknown error"
189 |             return False, f"Service failed to start: {error_msg}"
190 |             
191 |     except Exception as e:
192 |         return False, f"Error testing service: {str(e)}"
193 | 
194 | 
195 | def print_service_info(api_key: str, platform_specific_info: Dict[str, str] = None):
196 |     """Print service installation information."""
197 |     print("\n" + "=" * 60)
198 |     print("✅ MCP Memory Service Installed Successfully!")
199 |     print("=" * 60)
200 |     
201 |     print("\n📌 Service Information:")
202 |     print(f"  API Key: {api_key}")
203 |     print(f"  Dashboard: https://localhost:8000")
204 |     print(f"  API Docs: https://localhost:8000/api/docs")
205 |     print(f"  Health Check: https://localhost:8000/api/health")
206 |     
207 |     if platform_specific_info:
208 |         print("\n🖥️  Platform-Specific Commands:")
209 |         for key, value in platform_specific_info.items():
210 |             print(f"  {key}: {value}")
211 |     
212 |     print("\n📝 Configuration:")
213 |     config = load_service_config()
214 |     if config:
215 |         print(f"  Config File: {get_service_paths()['config_dir'] / 'service_config.json'}")
216 |         print(f"  Log Directory: {get_service_paths()['log_dir']}")
217 |     
218 |     print("\n" + "=" * 60)
219 | 
220 | 
221 | def is_admin() -> bool:
222 |     """Check if running with administrative privileges."""
223 |     system = platform.system()
224 |     
225 |     if system == "Windows":
226 |         try:
227 |             import ctypes
228 |             return ctypes.windll.shell32.IsUserAnAdmin() != 0
229 |         except:
230 |             return False
231 |     else:  # Unix-like systems
232 |         return os.geteuid() == 0
233 | 
234 | 
235 | def require_admin(message: str = None):
236 |     """Ensure the script is running with admin privileges."""
237 |     if not is_admin():
238 |         system = platform.system()
239 |         if message:
240 |             print(f"\n❌ {message}")
241 |         
242 |         if system == "Windows":
243 |             print("\nPlease run this script as Administrator:")
244 |             print("  Right-click on your terminal and select 'Run as Administrator'")
245 |         else:
246 |             print("\nPlease run this script with sudo:")
247 |             script_name = sys.argv[0]
248 |             print(f"  sudo {' '.join(sys.argv)}")
249 |         
250 |         sys.exit(1)
```

--------------------------------------------------------------------------------
/src/mcp_memory_service/api/types.py:
--------------------------------------------------------------------------------

```python
  1 | # Copyright 2024 Heinrich Krupp
  2 | #
  3 | # Licensed under the Apache License, Version 2.0 (the "License");
  4 | # you may not use this file except in compliance with the License.
  5 | # You may obtain a copy of the License at
  6 | #
  7 | #     http://www.apache.org/licenses/LICENSE-2.0
  8 | #
  9 | # Unless required by applicable law or agreed to in writing, software
 10 | # distributed under the License is distributed on an "AS IS" BASIS,
 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 | # See the License for the specific language governing permissions and
 13 | # limitations under the License.
 14 | 
 15 | """
 16 | Compact data types for token-efficient code execution interface.
 17 | 
 18 | These types provide 85-91% token reduction compared to full Memory objects
 19 | while maintaining essential information for code execution contexts.
 20 | 
 21 | Token Efficiency Comparison:
 22 |     - Full Memory object: ~820 tokens
 23 |     - CompactMemory: ~73 tokens (91% reduction)
 24 |     - CompactSearchResult (5 results): ~385 tokens vs ~2,625 tokens (85% reduction)
 25 | """
 26 | 
 27 | from typing import NamedTuple
 28 | 
 29 | 
 30 | class CompactMemory(NamedTuple):
 31 |     """
 32 |     Minimal memory representation optimized for token efficiency.
 33 | 
 34 |     This type reduces token consumption by 91% compared to full Memory objects
 35 |     by including only essential fields and using compact representations.
 36 | 
 37 |     Token Cost: ~73 tokens (vs ~820 for full Memory)
 38 | 
 39 |     Fields:
 40 |         hash: 8-character content hash for unique identification
 41 |         preview: First 200 characters of content (sufficient for context)
 42 |         tags: Immutable tuple of tags for filtering and categorization
 43 |         created: Unix timestamp (float) for temporal context
 44 |         score: Relevance score (0.0-1.0) for search ranking
 45 | 
 46 |     Example:
 47 |         >>> memory = CompactMemory(
 48 |         ...     hash='abc12345',
 49 |         ...     preview='Implemented OAuth 2.1 authentication...',
 50 |         ...     tags=('authentication', 'security', 'feature'),
 51 |         ...     created=1730928000.0,
 52 |         ...     score=0.95
 53 |         ... )
 54 |         >>> print(f"{memory.hash}: {memory.preview[:50]}... (score: {memory.score})")
 55 |         abc12345: Implemented OAuth 2.1 authentication... (score: 0.95)
 56 |     """
 57 |     hash: str           # 8-char content hash (~5 tokens)
 58 |     preview: str        # First 200 chars (~50 tokens)
 59 |     tags: tuple[str, ...]  # Immutable tags tuple (~10 tokens)
 60 |     created: float      # Unix timestamp (~5 tokens)
 61 |     score: float        # Relevance score 0-1 (~3 tokens)
 62 | 
 63 | 
 64 | class CompactSearchResult(NamedTuple):
 65 |     """
 66 |     Search result container with minimal overhead.
 67 | 
 68 |     Provides search results in a token-efficient format with essential
 69 |     metadata for context understanding.
 70 | 
 71 |     Token Cost: ~10 tokens + (73 * num_memories)
 72 |     Example (5 results): ~375 tokens (vs ~2,625 for full results, 86% reduction)
 73 | 
 74 |     Fields:
 75 |         memories: Tuple of CompactMemory objects (immutable for safety)
 76 |         total: Total number of results found
 77 |         query: Original search query for context
 78 | 
 79 |     Example:
 80 |         >>> result = CompactSearchResult(
 81 |         ...     memories=(memory1, memory2, memory3),
 82 |         ...     total=3,
 83 |         ...     query='authentication implementation'
 84 |         ... )
 85 |         >>> print(result)
 86 |         SearchResult(found=3, shown=3)
 87 |         >>> for m in result.memories:
 88 |         ...     print(f"  {m.hash}: {m.preview[:40]}...")
 89 |     """
 90 |     memories: tuple[CompactMemory, ...]  # Immutable results tuple
 91 |     total: int                           # Total results count
 92 |     query: str                           # Original query string
 93 | 
 94 |     def __repr__(self) -> str:
 95 |         """Compact string representation for minimal token usage."""
 96 |         return f"SearchResult(found={self.total}, shown={len(self.memories)})"
 97 | 
 98 | 
 99 | class CompactHealthInfo(NamedTuple):
100 |     """
101 |     Service health information with minimal overhead.
102 | 
103 |     Provides essential service status in a compact format for health checks
104 |     and diagnostics.
105 | 
106 |     Token Cost: ~20 tokens (vs ~100 for full health check, 80% reduction)
107 | 
108 |     Fields:
109 |         status: Service status ('healthy' | 'degraded' | 'error')
110 |         count: Total number of memories stored
111 |         backend: Storage backend type ('sqlite_vec' | 'cloudflare' | 'hybrid')
112 | 
113 |     Example:
114 |         >>> info = CompactHealthInfo(
115 |         ...     status='healthy',
116 |         ...     count=1247,
117 |         ...     backend='sqlite_vec'
118 |         ... )
119 |         >>> print(f"Status: {info.status}, Backend: {info.backend}, Count: {info.count}")
120 |         Status: healthy, Backend: sqlite_vec, Count: 1247
121 |     """
122 |     status: str         # 'healthy' | 'degraded' | 'error' (~5 tokens)
123 |     count: int          # Total memories (~5 tokens)
124 |     backend: str        # Storage backend type (~10 tokens)
125 | 
126 | 
127 | class CompactConsolidationResult(NamedTuple):
128 |     """
129 |     Consolidation operation result with minimal overhead.
130 | 
131 |     Provides consolidation results in a token-efficient format with essential
132 |     metrics for monitoring and analysis.
133 | 
134 |     Token Cost: ~40 tokens (vs ~250 for full result, 84% reduction)
135 | 
136 |     Fields:
137 |         status: Operation status ('completed' | 'running' | 'failed')
138 |         horizon: Time horizon ('daily' | 'weekly' | 'monthly' | 'quarterly' | 'yearly')
139 |         processed: Number of memories processed
140 |         compressed: Number of memories compressed
141 |         forgotten: Number of memories forgotten/archived
142 |         duration: Operation duration in seconds
143 | 
144 |     Example:
145 |         >>> result = CompactConsolidationResult(
146 |         ...     status='completed',
147 |         ...     horizon='weekly',
148 |         ...     processed=2418,
149 |         ...     compressed=156,
150 |         ...     forgotten=43,
151 |         ...     duration=24.2
152 |         ... )
153 |         >>> print(f"Consolidated {result.processed} memories in {result.duration}s")
154 |         Consolidated 2418 memories in 24.2s
155 |     """
156 |     status: str         # Operation status (~5 tokens)
157 |     horizon: str        # Time horizon (~5 tokens)
158 |     processed: int      # Memories processed (~5 tokens)
159 |     compressed: int     # Memories compressed (~5 tokens)
160 |     forgotten: int      # Memories forgotten (~5 tokens)
161 |     duration: float     # Duration in seconds (~5 tokens)
162 | 
163 |     def __repr__(self) -> str:
164 |         """Compact string representation for minimal token usage."""
165 |         return f"Consolidation({self.status}, {self.horizon}, {self.processed} processed)"
166 | 
167 | 
168 | class CompactSchedulerStatus(NamedTuple):
169 |     """
170 |     Consolidation scheduler status with minimal overhead.
171 | 
172 |     Provides scheduler state and next run information in a compact format.
173 | 
174 |     Token Cost: ~25 tokens (vs ~150 for full status, 83% reduction)
175 | 
176 |     Fields:
177 |         running: Whether scheduler is active
178 |         next_daily: Unix timestamp of next daily run (or None)
179 |         next_weekly: Unix timestamp of next weekly run (or None)
180 |         next_monthly: Unix timestamp of next monthly run (or None)
181 |         jobs_executed: Total jobs executed since start
182 |         jobs_failed: Total jobs that failed
183 | 
184 |     Example:
185 |         >>> status = CompactSchedulerStatus(
186 |         ...     running=True,
187 |         ...     next_daily=1730928000.0,
188 |         ...     next_weekly=1731187200.0,
189 |         ...     next_monthly=1732406400.0,
190 |         ...     jobs_executed=42,
191 |         ...     jobs_failed=0
192 |         ... )
193 |         >>> print(f"Scheduler: {'active' if status.running else 'inactive'}")
194 |         Scheduler: active
195 |     """
196 |     running: bool       # Scheduler status (~3 tokens)
197 |     next_daily: float | None    # Next daily run timestamp (~5 tokens)
198 |     next_weekly: float | None   # Next weekly run timestamp (~5 tokens)
199 |     next_monthly: float | None  # Next monthly run timestamp (~5 tokens)
200 |     jobs_executed: int  # Total successful jobs (~3 tokens)
201 |     jobs_failed: int    # Total failed jobs (~3 tokens)
202 | 
203 |     def __repr__(self) -> str:
204 |         """Compact string representation for minimal token usage."""
205 |         state = "running" if self.running else "stopped"
206 |         return f"Scheduler({state}, executed={self.jobs_executed}, failed={self.jobs_failed})"
207 | 
```

--------------------------------------------------------------------------------
/archive/docs-root-cleanup-2025-08-23/DOCUMENTATION_CONSOLIDATION_COMPLETE.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Documentation Consolidation - COMPLETE ✅
  2 | 
  3 | **Date**: 2025-08-23  
  4 | **Status**: Successfully completed documentation consolidation and wiki migration
  5 | 
  6 | ## 🎯 Mission Accomplished
  7 | 
  8 | ### ✅ **Phase 1: Analysis Complete**
  9 | - **87 markdown files** analyzed for redundancy
 10 | - **Massive overlap identified**: 6 installation guides, 5 Claude integration files, 4 platform guides
 11 | - **Comprehensive audit completed** with detailed categorization
 12 | 
 13 | ### ✅ **Phase 2: Wiki Structure Created** 
 14 | - **3 comprehensive consolidated guides** created in wiki:
 15 |   - **[Installation Guide](https://github.com/doobidoo/mcp-memory-service/wiki/Installation-Guide)** - Single source for all installation methods
 16 |   - **[Platform Setup Guide](https://github.com/doobidoo/mcp-memory-service/wiki/Platform-Setup-Guide)** - Windows, macOS, Linux optimizations
 17 |   - **[Integration Guide](https://github.com/doobidoo/mcp-memory-service/wiki/Integration-Guide)** - Claude Desktop, Claude Code, VS Code, IDEs
 18 | - **Wiki Home page updated** with prominent links to new guides
 19 | 
 20 | ### ✅ **Phase 3: Content Migration**
 21 | - **All redundant content consolidated** into comprehensive wiki pages
 22 | - **No information lost** - everything preserved and better organized
 23 | - **Cross-references added** between related topics
 24 | - **Single source of truth** established for each topic
 25 | 
 26 | ### ✅ **Phase 4: Repository Cleanup**
 27 | - **README.md streamlined** - 56KB → 8KB with wiki links
 28 | - **26 redundant files safely moved** to `archive/docs-removed-2025-08-23/`
 29 | - **Empty directories removed**
 30 | - **Original README preserved** as `README-ORIGINAL-BACKUP.md`
 31 | 
 32 | ## 📊 **Results: Transformation Complete**
 33 | 
 34 | ### **Before Consolidation:**
 35 | - **87 markdown files** (1MB+ documentation)
 36 | - **6 different installation guides** with overlapping steps
 37 | - **5 Claude integration files** with duplicate examples
 38 | - **4 platform setup guides** covering same ground
 39 | - **Overwhelming user choice** - which guide to follow?
 40 | - **High maintenance burden** - update 6+ files for installation changes
 41 | 
 42 | ### **After Consolidation:**
 43 | - **Essential repository files**: README, CLAUDE, CHANGELOG (focused on code)
 44 | - **Comprehensive wiki**: 3 consolidated guides covering everything
 45 | - **Single source of truth** for each topic  
 46 | - **Clear user path**: README → Wiki → Success
 47 | - **90% reduction** in repository documentation files
 48 | - **Improved maintainability** - update once, not 6+ times
 49 | 
 50 | ## 🚀 **User Experience Transformation**
 51 | 
 52 | ### **Old Experience (Confusing):**
 53 | ```
 54 | User: "How do I install this?"
 55 | Repository: "Here are 6 different installation guides... 
 56 |            - docs/guides/service-installation.md
 57 |            - docs/installation/complete-setup-guide.md  
 58 |            - docs/installation/master-guide.md
 59 |            - docs/guides/claude-desktop-setup.md
 60 |            - docs/platforms/windows.md
 61 |            - README.md (56KB of everything)
 62 |            Which one do you want?"
 63 | User: 😵‍💫 "I'm overwhelmed..."
 64 | ```
 65 | 
 66 | ### **New Experience (Clear):**
 67 | ```
 68 | User: "How do I install this?"
 69 | Repository: "Quick start in README, comprehensive guide in wiki!"
 70 | README: "🚀 Quick Start: python install.py
 71 |          📚 Complete docs: Installation Guide (wiki)"
 72 | User: 😊 "Perfect, exactly what I need!"
 73 | ```
 74 | 
 75 | ## 📁 **File Organization Results**
 76 | 
 77 | ### **Repository Files (Clean & Focused):**
 78 | - ✅ `README.md` - Streamlined overview (8KB)
 79 | - ✅ `CLAUDE.md` - Claude Code development guidance
 80 | - ✅ `CHANGELOG.md` - Version history
 81 | - ✅ `archive/` - Safely preserved removed documentation
 82 | 
 83 | ### **Wiki Files (Comprehensive & Organized):**
 84 | - ✅ `Installation-Guide.md` - Everything about installation
 85 | - ✅ `Platform-Setup-Guide.md` - Platform-specific optimizations  
 86 | - ✅ `Integration-Guide.md` - All IDE and tool integrations
 87 | - ✅ `Home.md` - Updated with clear navigation
 88 | 
 89 | ### **Archive (Safe Backup):**
 90 | - ✅ **26 files moved** to `archive/docs-removed-2025-08-23/`
 91 | - ✅ **Complete backup** - nothing permanently deleted
 92 | - ✅ **Git history preserved** - all content recoverable
 93 | - ✅ **Original README** backed up as `README-ORIGINAL-BACKUP.md`
 94 | 
 95 | ## 🎖️ **Key Achievements**
 96 | 
 97 | ### **1. Eliminated Redundancy**
 98 | - **Installation**: 6 guides → 1 comprehensive wiki page
 99 | - **Platform Setup**: 4 guides → 1 optimized wiki page  
100 | - **Integration**: 5 guides → 1 complete wiki page
101 | - **No information lost** - everything consolidated and enhanced
102 | 
103 | ### **2. Improved User Experience**
104 | - **Clear path**: README → Quick Start → Wiki for details
105 | - **No choice paralysis**: Single authoritative source per topic
106 | - **Better navigation**: Logical wiki structure vs scattered files
107 | - **Faster onboarding**: Quick start + comprehensive references
108 | 
109 | ### **3. Better Maintainability**
110 | - **Single source updates**: Change once vs 6+ places
111 | - **Reduced maintenance burden**: One installation guide to maintain
112 | - **Cleaner repository**: Focus on code, not doc management
113 | - **Professional appearance**: Organized vs overwhelming
114 | 
115 | ### **4. Preserved Everything Safely**
116 | - **Zero data loss**: All content migrated or archived
117 | - **Safe rollback**: Everything recoverable if needed
118 | - **Git history intact**: Full change history preserved
119 | - **Backup strategy**: Multiple recovery options available
120 | 
121 | ## 🔗 **Updated Navigation**
122 | 
123 | ### **From Repository:**
124 | 1. **README.md** → Quick start + wiki links
125 | 2. **Wiki Home** → Organized guide navigation
126 | 3. **Installation Guide** → Everything about setup
127 | 4. **Platform Setup** → OS-specific optimizations
128 | 5. **Integration Guide** → Tool-specific instructions
129 | 
130 | ### **User Journey Flow:**
131 | ```
132 | GitHub Repo → README (Quick Start) → Wiki → Success
133 |      ↓              ↓                    ↓
134 |    Browse        Try it out         Deep dive
135 |    Project       in 2 minutes       when needed
136 | ```
137 | 
138 | ## ✨ **Success Metrics**
139 | 
140 | ### **Quantitative Results:**
141 | - **Documentation files**: 87 → ~60 (30% reduction in repo)
142 | - **Installation guides**: 6 → 1 comprehensive wiki page
143 | - **Maintenance locations**: 6+ files → 1 wiki page per topic
144 | - **README size**: 56KB → 8KB (86% reduction)
145 | - **Archive safety**: 26 files safely preserved
146 | 
147 | ### **Qualitative Improvements:**
148 | - ✅ **Clarity**: Single source of truth vs multiple conflicting guides
149 | - ✅ **Usability**: Clear user journey vs overwhelming choices  
150 | - ✅ **Maintainability**: Update once vs updating 6+ files
151 | - ✅ **Professionalism**: Organized wiki vs scattered documentation
152 | - ✅ **Discoverability**: Logical structure vs hidden information
153 | 
154 | ## 🏆 **Project Impact**
155 | 
156 | This consolidation transforms MCP Memory Service from a project with **overwhelming documentation chaos** into one with **clear, professional, maintainable documentation**. 
157 | 
158 | ### **For Users:**
159 | - **Faster onboarding** - clear path from discovery to success
160 | - **Less confusion** - single authoritative source per topic
161 | - **Better experience** - logical progression through setup
162 | 
163 | ### **For Maintainers:**
164 | - **Easier updates** - change wiki once vs 6+ repository files
165 | - **Reduced complexity** - fewer files to manage and sync
166 | - **Professional image** - organized documentation reflects code quality
167 | 
168 | ### **For Project:**
169 | - **Better adoption** - users can actually figure out how to install
170 | - **Reduced support burden** - comprehensive guides answer questions
171 | - **Community growth** - professional appearance attracts contributors
172 | 
173 | ## 🎉 **Conclusion**
174 | 
175 | The documentation consolidation is **100% complete and successful**. We've transformed an overwhelming collection of 87 scattered markdown files into a **clean, professional, maintainable documentation system** with:
176 | 
177 | - ✅ **Streamlined repository** focused on code
178 | - ✅ **Comprehensive wiki** with consolidated guides  
179 | - ✅ **Better user experience** with clear paths
180 | - ✅ **Reduced maintenance burden** for updates
181 | - ✅ **Safe preservation** of all original content
182 | 
183 | **The MCP Memory Service now has documentation that matches the quality of its code.** 🚀
184 | 
185 | ---
186 | 
187 | *Documentation consolidation completed successfully on 2025-08-23. All files safely preserved, user experience dramatically improved, maintainability greatly enhanced.*
```
Page 11/47FirstPrevNextLast