#
tokens: 47030/50000 1/625 files (page 44/47)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 44 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

--------------------------------------------------------------------------------
/install.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 | Installation script for MCP Memory Service with cross-platform compatibility.
  18 | This script guides users through the installation process with the appropriate
  19 | dependencies for their platform.
  20 | """
  21 | import os
  22 | import sys
  23 | import platform
  24 | import subprocess
  25 | import argparse
  26 | import shutil
  27 | from pathlib import Path
  28 | 
  29 | # Import shared GPU detection utilities
  30 | try:
  31 |     from src.mcp_memory_service.utils.gpu_detection import detect_gpu as shared_detect_gpu
  32 | except ImportError:
  33 |     # Fallback for development/testing scenarios
  34 |     sys.path.insert(0, str(Path(__file__).parent))
  35 |     from src.mcp_memory_service.utils.gpu_detection import detect_gpu as shared_detect_gpu
  36 | 
  37 | # Fix Windows console encoding issues
  38 | if platform.system() == "Windows":
  39 |     # Ensure stdout uses UTF-8 on Windows to prevent character encoding issues in logs
  40 |     if hasattr(sys.stdout, 'reconfigure'):
  41 |         try:
  42 |             sys.stdout.reconfigure(encoding='utf-8')
  43 |             sys.stderr.reconfigure(encoding='utf-8')
  44 |         except AttributeError:
  45 |             pass
  46 | 
  47 | # Enhanced logging system for installer
  48 | import logging
  49 | from datetime import datetime
  50 | 
  51 | class DualOutput:
  52 |     """Class to handle both console and file output simultaneously."""
  53 |     def __init__(self, log_file_path):
  54 |         self.console = sys.stdout
  55 |         self.log_file = None
  56 |         self.log_file_path = log_file_path
  57 |         self._setup_log_file()
  58 |     
  59 |     def _setup_log_file(self):
  60 |         """Set up the log file with proper encoding."""
  61 |         try:
  62 |             # Create log file with UTF-8 encoding
  63 |             self.log_file = open(self.log_file_path, 'w', encoding='utf-8')
  64 |             # Write header
  65 |             timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  66 |             
  67 |             # Fix Windows version display in log header
  68 |             platform_info = f"{platform.system()} {platform.release()}"
  69 |             if platform.system() == "Windows":
  70 |                 try:
  71 |                     import winreg
  72 |                     key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion")
  73 |                     build_number = winreg.QueryValueEx(key, "CurrentBuildNumber")[0]
  74 |                     winreg.CloseKey(key)
  75 |                     
  76 |                     # Windows 11 has build number >= 22000
  77 |                     if int(build_number) >= 22000:
  78 |                         platform_info = f"Windows 11"
  79 |                     else:
  80 |                         platform_info = f"Windows {platform.release()}"
  81 |                 except (ImportError, OSError, ValueError):
  82 |                     pass  # Use default
  83 |             
  84 |             header = f"""
  85 | ================================================================================
  86 | MCP Memory Service Installation Log
  87 | Started: {timestamp}
  88 | Platform: {platform_info} ({platform.machine()})
  89 | Python: {sys.version}
  90 | ================================================================================
  91 | 
  92 | """
  93 |             self.log_file.write(header)
  94 |             self.log_file.flush()
  95 |         except Exception as e:
  96 |             print(f"Warning: Could not create log file {self.log_file_path}: {e}")
  97 |             self.log_file = None
  98 |     
  99 |     def write(self, text):
 100 |         """Write to both console and log file."""
 101 |         # Write to console
 102 |         self.console.write(text)
 103 |         self.console.flush()
 104 |         
 105 |         # Write to log file if available
 106 |         if self.log_file:
 107 |             try:
 108 |                 self.log_file.write(text)
 109 |                 self.log_file.flush()
 110 |             except Exception:
 111 |                 pass  # Silently ignore log file write errors
 112 |     
 113 |     def flush(self):
 114 |         """Flush both outputs."""
 115 |         self.console.flush()
 116 |         if self.log_file:
 117 |             try:
 118 |                 self.log_file.flush()
 119 |             except Exception:
 120 |                 pass
 121 |     
 122 |     def close(self):
 123 |         """Close the log file."""
 124 |         if self.log_file:
 125 |             try:
 126 |                 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
 127 |                 footer = f"""
 128 | ================================================================================
 129 | Installation completed: {timestamp}
 130 | ================================================================================
 131 | """
 132 |                 self.log_file.write(footer)
 133 |                 self.log_file.close()
 134 |             except Exception:
 135 |                 pass
 136 | 
 137 | # Global dual output instance
 138 | _dual_output = None
 139 | 
 140 | def setup_installer_logging():
 141 |     """Set up the installer logging system."""
 142 |     global _dual_output
 143 |     
 144 |     # Create log file path
 145 |     log_file = Path.cwd() / "installation.log"
 146 |     
 147 |     # Remove old log file if it exists
 148 |     if log_file.exists():
 149 |         try:
 150 |             log_file.unlink()
 151 |         except Exception:
 152 |             pass
 153 |     
 154 |     # Set up dual output
 155 |     _dual_output = DualOutput(str(log_file))
 156 |     
 157 |     # Redirect stdout to dual output
 158 |     sys.stdout = _dual_output
 159 |     
 160 |     print(f"Installation log will be saved to: {log_file}")
 161 |     
 162 |     return str(log_file)
 163 | 
 164 | def cleanup_installer_logging():
 165 |     """Clean up the installer logging system."""
 166 |     global _dual_output
 167 |     
 168 |     if _dual_output:
 169 |         # Restore original stdout
 170 |         sys.stdout = _dual_output.console
 171 |         _dual_output.close()
 172 |         _dual_output = None
 173 | 
 174 | # Import Claude commands utilities
 175 | try:
 176 |     from scripts.claude_commands_utils import install_claude_commands, check_claude_code_cli
 177 | except ImportError:
 178 |     # Handle case where script is run from different directory
 179 |     script_dir = Path(__file__).parent
 180 |     sys.path.insert(0, str(script_dir))
 181 |     try:
 182 |         from scripts.claude_commands_utils import install_claude_commands, check_claude_code_cli
 183 |     except ImportError:
 184 |         install_claude_commands = None
 185 |         check_claude_code_cli = None
 186 | 
 187 | # Global variable to store the uv executable path
 188 | UV_EXECUTABLE_PATH = None
 189 | 
 190 | def print_header(text):
 191 |     """Print a formatted header."""
 192 |     print("\n" + "=" * 80)
 193 |     print(f" {text}")
 194 |     print("=" * 80)
 195 | 
 196 | def print_step(step, text):
 197 |     """Print a formatted step."""
 198 |     print(f"\n[{step}] {text}")
 199 | 
 200 | def print_info(text):
 201 |     """Print formatted info text."""
 202 |     print(f"  -> {text}")
 203 | 
 204 | def print_error(text):
 205 |     """Print formatted error text."""
 206 |     print(f"  [ERROR] {text}")
 207 | 
 208 | def print_success(text):
 209 |     """Print formatted success text."""
 210 |     print(f"  [OK] {text}")
 211 | 
 212 | def print_warning(text):
 213 |     """Print formatted warning text."""
 214 |     print(f"  [WARNING]  {text}")
 215 | 
 216 | def prompt_user_input(prompt_text, default_value=""):
 217 |     """
 218 |     Prompt user for input with formatted banner.
 219 | 
 220 |     Args:
 221 |         prompt_text: The input prompt to display
 222 |         default_value: Optional default value if user presses Enter
 223 | 
 224 |     Returns:
 225 |         User's input (or default if empty)
 226 |     """
 227 |     print("\n" + "=" * 60)
 228 |     print("⚠️  USER INPUT REQUIRED")
 229 |     print("=" * 60)
 230 |     response = input(prompt_text).strip()
 231 |     print("=" * 60 + "\n")
 232 |     return response if response else default_value
 233 | 
 234 | def build_mcp_server_config(storage_backend="sqlite_vec", repo_path=None):
 235 |     """
 236 |     Build MCP server configuration dict for multi-client access.
 237 | 
 238 |     Args:
 239 |         storage_backend: Storage backend to use (sqlite_vec or chromadb)
 240 |         repo_path: Repository path (defaults to current directory)
 241 | 
 242 |     Returns:
 243 |         Dict containing MCP server configuration with command, args, and env
 244 |     """
 245 |     if repo_path is None:
 246 |         repo_path = str(Path.cwd())
 247 | 
 248 |     # Build environment configuration based on storage backend
 249 |     env_config = {
 250 |         "MCP_MEMORY_STORAGE_BACKEND": storage_backend,
 251 |         "LOG_LEVEL": "INFO"
 252 |     }
 253 | 
 254 |     # Add backend-specific configuration
 255 |     if storage_backend == "sqlite_vec":
 256 |         env_config["MCP_MEMORY_SQLITE_PRAGMAS"] = "busy_timeout=15000,cache_size=20000"
 257 | 
 258 |     return {
 259 |         "command": UV_EXECUTABLE_PATH or "uv",
 260 |         "args": ["--directory", repo_path, "run", "memory"],
 261 |         "env": env_config
 262 |     }
 263 | 
 264 | # Cache for system detection to avoid duplicate calls
 265 | _system_info_cache = None
 266 | 
 267 | def detect_system():
 268 |     """Detect the system architecture and platform."""
 269 |     global _system_info_cache
 270 |     if _system_info_cache is not None:
 271 |         return _system_info_cache
 272 |     
 273 |     system = platform.system().lower()
 274 |     machine = platform.machine().lower()
 275 |     python_version = f"{sys.version_info.major}.{sys.version_info.minor}"
 276 |     
 277 |     is_windows = system == "windows"
 278 |     is_macos = system == "darwin"
 279 |     is_linux = system == "linux"
 280 |     is_arm = machine in ("arm64", "aarch64")
 281 |     is_x86 = machine in ("x86_64", "amd64", "x64")
 282 |     
 283 |     # Fix Windows version detection - Windows 11 reports as Windows 10
 284 |     if is_windows:
 285 |         try:
 286 |             import winreg
 287 |             key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion")
 288 |             build_number = winreg.QueryValueEx(key, "CurrentBuildNumber")[0]
 289 |             winreg.CloseKey(key)
 290 |             
 291 |             # Windows 11 has build number >= 22000
 292 |             if int(build_number) >= 22000:
 293 |                 windows_version = "11"
 294 |             else:
 295 |                 windows_version = platform.release()
 296 |         except (ImportError, OSError, ValueError):
 297 |             windows_version = platform.release()
 298 |         
 299 |         print_info(f"System: {platform.system()} {windows_version}")
 300 |     else:
 301 |         print_info(f"System: {platform.system()} {platform.release()}")
 302 |     
 303 |     print_info(f"Architecture: {machine}")
 304 |     print_info(f"Python: {python_version}")
 305 |     
 306 |     # Check for virtual environment
 307 |     in_venv = sys.prefix != sys.base_prefix
 308 |     if not in_venv:
 309 |         print_warning("Not running in a virtual environment. It's recommended to install in a virtual environment.")
 310 |     else:
 311 |         print_info(f"Virtual environment: {sys.prefix}")
 312 |     
 313 |     # Check for Homebrew PyTorch installation
 314 |     has_homebrew_pytorch = False
 315 |     homebrew_pytorch_version = None
 316 |     if is_macos:
 317 |         try:
 318 |             # Check if pytorch is installed via brew
 319 |             print_info("Checking for Homebrew PyTorch installation...")
 320 |             result = subprocess.run(
 321 |                 ['brew', 'list', 'pytorch', '--version'],
 322 |                 capture_output=True,
 323 |                 text=True,
 324 |                 timeout=30  # Increased timeout to prevent hanging
 325 |             )
 326 |             if result.returncode == 0:
 327 |                 has_homebrew_pytorch = True
 328 |                 # Extract version from output
 329 |                 version_line = result.stdout.strip()
 330 |                 homebrew_pytorch_version = version_line.split()[1] if len(version_line.split()) > 1 else "Unknown"
 331 |                 print_info(f"Detected Homebrew PyTorch installation: {homebrew_pytorch_version}")
 332 |         except subprocess.TimeoutExpired:
 333 |             print_info("Homebrew PyTorch detection timed out - skipping")
 334 |             has_homebrew_pytorch = False
 335 |         except (subprocess.SubprocessError, FileNotFoundError):
 336 |             pass
 337 |     
 338 |     _system_info_cache = {
 339 |         "system": system,
 340 |         "machine": machine,
 341 |         "python_version": python_version,
 342 |         "is_windows": is_windows,
 343 |         "is_macos": is_macos,
 344 |         "is_linux": is_linux,
 345 |         "is_arm": is_arm,
 346 |         "is_x86": is_x86,
 347 |         "in_venv": in_venv,
 348 |         "has_homebrew_pytorch": has_homebrew_pytorch,
 349 |         "homebrew_pytorch_version": homebrew_pytorch_version
 350 |     }
 351 |     return _system_info_cache
 352 | 
 353 | def check_sqlite_extension_support():
 354 |     """Check if Python's sqlite3 supports loading extensions."""
 355 |     import sqlite3
 356 |     
 357 |     test_conn = None
 358 |     try:
 359 |         test_conn = sqlite3.connect(":memory:")
 360 |         if not hasattr(test_conn, 'enable_load_extension'):
 361 |             return False, "Python sqlite3 module not compiled with extension support"
 362 |         
 363 |         # Test if we can actually enable extension loading
 364 |         test_conn.enable_load_extension(True)
 365 |         test_conn.enable_load_extension(False)
 366 |         return True, "Extension loading supported"
 367 |         
 368 |     except AttributeError as e:
 369 |         return False, f"enable_load_extension not available: {e}"
 370 |     except Exception as e:
 371 |         return False, f"Extension support check failed: {e}"
 372 |     finally:
 373 |         if test_conn:
 374 |             test_conn.close()
 375 | 
 376 | def detect_gpu():
 377 |     """Detect GPU and acceleration capabilities.
 378 | 
 379 |     Wrapper function that uses the shared GPU detection module.
 380 |     """
 381 |     system_info = detect_system()
 382 | 
 383 |     # Use shared GPU detection module
 384 |     gpu_info = shared_detect_gpu(system_info)
 385 | 
 386 |     # Print GPU information (maintain installer output format)
 387 |     if gpu_info.get("has_cuda"):
 388 |         cuda_version = gpu_info.get("cuda_version")
 389 |         print_info(f"CUDA detected: {cuda_version or 'Unknown version'}")
 390 |     if gpu_info.get("has_rocm"):
 391 |         rocm_version = gpu_info.get("rocm_version")
 392 |         print_info(f"ROCm detected: {rocm_version or 'Unknown version'}")
 393 |     if gpu_info.get("has_mps"):
 394 |         print_info("Apple Metal Performance Shaders (MPS) detected")
 395 |     if gpu_info.get("has_directml"):
 396 |         directml_version = gpu_info.get("directml_version")
 397 |         if directml_version:
 398 |             print_info(f"DirectML detected: {directml_version}")
 399 |         else:
 400 |             print_info("DirectML detected")
 401 | 
 402 |     if not (gpu_info.get("has_cuda") or gpu_info.get("has_rocm") or
 403 |             gpu_info.get("has_mps") or gpu_info.get("has_directml")):
 404 |         print_info("No GPU acceleration detected, will use CPU-only mode")
 405 | 
 406 |     return gpu_info
 407 | 
 408 | 
 409 | def check_dependencies():
 410 |     """Check for required dependencies.
 411 |     
 412 |     Note on package managers:
 413 |     - Traditional virtual environments (venv, virtualenv) include pip by default
 414 |     - Alternative package managers like uv may not include pip or may manage packages differently
 415 |     - We attempt multiple detection methods for pip and only fail if:
 416 |       a) We're not in a virtual environment, or
 417 |       b) We can't detect pip AND can't install dependencies
 418 |     
 419 |     We proceed with installation even if pip isn't detected when in a virtual environment,
 420 |     assuming an alternative package manager (like uv) is handling dependencies.
 421 |     
 422 |     Returns:
 423 |         bool: True if all dependencies are met, False otherwise.
 424 |     """
 425 |     print_step("2", "Checking dependencies")
 426 |     
 427 |     # Check for pip
 428 |     pip_installed = False
 429 |     
 430 |     # Try subprocess check first
 431 |     try:
 432 |         subprocess.check_call([sys.executable, '-m', 'pip', '--version'], 
 433 |                              stdout=subprocess.DEVNULL, 
 434 |                              stderr=subprocess.DEVNULL)
 435 |         pip_installed = True
 436 |         print_info("pip is installed")
 437 |     except subprocess.SubprocessError:
 438 |         # Fallback to import check
 439 |         try:
 440 |             import pip
 441 |             pip_installed = True
 442 |             print_info(f"pip is installed: {pip.__version__}")
 443 |         except ImportError:
 444 |             # Check if we're in a virtual environment
 445 |             in_venv = sys.prefix != sys.base_prefix
 446 |             if in_venv:
 447 |                 print_warning("pip could not be detected, but you're in a virtual environment. "
 448 |                             "If you're using uv or another alternative package manager, this is normal. "
 449 |                             "Continuing installation...")
 450 |                 pip_installed = True  # Proceed anyway
 451 |             else:
 452 |                 print_error("pip is not installed. Please install pip first.")
 453 |                 return False
 454 |     
 455 |     # Check for setuptools
 456 |     try:
 457 |         import setuptools
 458 |         print_info(f"setuptools is installed: {setuptools.__version__}")
 459 |     except ImportError:
 460 |         print_warning("setuptools is not installed. Will attempt to install it.")
 461 |         # If pip is available, use it to install setuptools
 462 |         if pip_installed:
 463 |             try:
 464 |                 subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'setuptools'], 
 465 |                                     stdout=subprocess.DEVNULL)
 466 |                 print_success("setuptools installed successfully")
 467 |             except subprocess.SubprocessError:
 468 |                 # Check if in virtual environment
 469 |                 in_venv = sys.prefix != sys.base_prefix
 470 |                 if in_venv:
 471 |                     print_warning("Failed to install setuptools with pip. If you're using an alternative package manager "
 472 |                                 "like uv, please install setuptools manually using that tool (e.g., 'uv pip install setuptools').")
 473 |                 else:
 474 |                     print_error("Failed to install setuptools. Please install it manually.")
 475 |                     return False
 476 |         else:
 477 |             # Should be unreachable since pip_installed would only be False if we returned earlier
 478 |             print_error("Cannot install setuptools without pip. Please install setuptools manually.")
 479 |             return False
 480 |     
 481 |     # Check for wheel
 482 |     try:
 483 |         import wheel
 484 |         print_info(f"wheel is installed: {wheel.__version__}")
 485 |     except ImportError:
 486 |         print_warning("wheel is not installed. Will attempt to install it.")
 487 |         # If pip is available, use it to install wheel
 488 |         if pip_installed:
 489 |             try:
 490 |                 subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'wheel'], 
 491 |                                     stdout=subprocess.DEVNULL)
 492 |                 print_success("wheel installed successfully")
 493 |             except subprocess.SubprocessError:
 494 |                 # Check if in virtual environment
 495 |                 in_venv = sys.prefix != sys.base_prefix
 496 |                 if in_venv:
 497 |                     print_warning("Failed to install wheel with pip. If you're using an alternative package manager "
 498 |                                 "like uv, please install wheel manually using that tool (e.g., 'uv pip install wheel').")
 499 |                 else:
 500 |                     print_error("Failed to install wheel. Please install it manually.")
 501 |                     return False
 502 |         else:
 503 |             # Should be unreachable since pip_installed would only be False if we returned earlier
 504 |             print_error("Cannot install wheel without pip. Please install wheel manually.")
 505 |             return False
 506 |     
 507 |     return True
 508 | 
 509 | def install_pytorch_platform_specific(system_info, gpu_info, args=None):
 510 |     """Install PyTorch with platform-specific configurations."""
 511 |     # Check if PyTorch installation should be skipped
 512 |     if args and args.skip_pytorch:
 513 |         print_info("Skipping PyTorch installation as requested")
 514 |         return True
 515 |         
 516 |     if system_info["is_windows"]:
 517 |         return install_pytorch_windows(gpu_info)
 518 |     elif system_info["is_macos"] and system_info["is_x86"]:
 519 |         return install_pytorch_macos_intel()
 520 |     elif system_info["is_macos"] and system_info["is_arm"]:
 521 |         return install_pytorch_macos_arm64()
 522 |     else:
 523 |         # For other platforms, let the regular installer handle it
 524 |         return True
 525 | 
 526 | def install_pytorch_macos_intel():
 527 |     """Install PyTorch specifically for macOS with Intel CPUs."""
 528 |     print_step("3a", "Installing PyTorch for macOS Intel CPU")
 529 |     
 530 |     # Use the versions known to work well on macOS Intel and with Python 3.13+
 531 |     try:
 532 |         # For Python 3.13+, we need newer PyTorch versions
 533 |         python_version = sys.version_info
 534 |         
 535 |         if python_version >= (3, 13):
 536 |             # For Python 3.13+, try to install latest compatible version
 537 |             print_info(f"Installing PyTorch for macOS Intel (Python {python_version.major}.{python_version.minor})...")
 538 |             print_info("Attempting to install latest PyTorch compatible with Python 3.13...")
 539 |             
 540 |             try:
 541 |                 # Try to install without version specifiers to get latest compatible version
 542 |                 cmd = [
 543 |                     sys.executable, '-m', 'pip', 'install',
 544 |                     "torch", "torchvision", "torchaudio"
 545 |                 ]
 546 |                 print_info(f"Running: {' '.join(cmd)}")
 547 |                 subprocess.check_call(cmd)
 548 |                 st_version = "3.0.0"  # Newer sentence-transformers for newer PyTorch
 549 |             except subprocess.SubprocessError as e:
 550 |                 print_warning(f"Failed to install latest PyTorch: {e}")
 551 |                 # Fallback to a specific version
 552 |                 torch_version = "2.1.0"
 553 |                 torch_vision_version = "0.16.0"
 554 |                 torch_audio_version = "2.1.0"
 555 |                 st_version = "3.0.0"
 556 |                 
 557 |                 print_info(f"Trying fallback to PyTorch {torch_version}...")
 558 |                 
 559 |                 cmd = [
 560 |                     sys.executable, '-m', 'pip', 'install',
 561 |                     f"torch=={torch_version}",
 562 |                     f"torchvision=={torch_vision_version}",
 563 |                     f"torchaudio=={torch_audio_version}"
 564 |                 ]
 565 |                 print_info(f"Running: {' '.join(cmd)}")
 566 |                 subprocess.check_call(cmd)
 567 |         else:
 568 |             # Use traditional versions for older Python
 569 |             torch_version = "1.13.1"
 570 |             torch_vision_version = "0.14.1"
 571 |             torch_audio_version = "0.13.1"
 572 |             st_version = "2.2.2"
 573 |             
 574 |             print_info(f"Installing PyTorch {torch_version} for macOS Intel (Python {python_version.major}.{python_version.minor})...")
 575 |             
 576 |             # Install PyTorch first with compatible version
 577 |             cmd = [
 578 |                 sys.executable, '-m', 'pip', 'install',
 579 |                 f"torch=={torch_version}",
 580 |                 f"torchvision=={torch_vision_version}",
 581 |                 f"torchaudio=={torch_audio_version}"
 582 |             ]
 583 |             
 584 |             print_info(f"Running: {' '.join(cmd)}")
 585 |             subprocess.check_call(cmd)
 586 |         
 587 |         # Install a compatible version of sentence-transformers
 588 |         print_info(f"Installing sentence-transformers {st_version}...")
 589 |         
 590 |         cmd = [
 591 |             sys.executable, '-m', 'pip', 'install',
 592 |             f"sentence-transformers=={st_version}"
 593 |         ]
 594 |         
 595 |         print_info(f"Running: {' '.join(cmd)}")
 596 |         subprocess.check_call(cmd)
 597 |         
 598 |         print_success(f"PyTorch {torch_version} and sentence-transformers {st_version} installed successfully for macOS Intel")
 599 |         return True
 600 |     except subprocess.SubprocessError as e:
 601 |         print_error(f"Failed to install PyTorch for macOS Intel: {e}")
 602 |         
 603 |         # Provide fallback instructions
 604 |         if python_version >= (3, 13):
 605 |             print_warning("You may need to manually install compatible versions for Python 3.13+ on Intel macOS:")
 606 |             print_info("pip install torch==2.3.0 torchvision==0.18.0 torchaudio==2.3.0")
 607 |             print_info("pip install sentence-transformers==3.0.0")
 608 |         else:
 609 |             print_warning("You may need to manually install compatible versions for Intel macOS:")
 610 |             print_info("pip install torch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1")
 611 |             print_info("pip install sentence-transformers==2.2.2")
 612 |         
 613 |         return False
 614 | 
 615 | def install_pytorch_macos_arm64():
 616 |     """Install PyTorch specifically for macOS with ARM64 (Apple Silicon)."""
 617 |     print_step("3a", "Installing PyTorch for macOS ARM64 (Apple Silicon)")
 618 |     
 619 |     try:
 620 |         # For Apple Silicon, we can use the latest PyTorch with MPS support
 621 |         print_info("Installing PyTorch with Metal Performance Shaders (MPS) support...")
 622 |         
 623 |         # Install PyTorch with MPS support - let pip choose the best compatible version
 624 |         cmd = [
 625 |             sys.executable, '-m', 'pip', 'install',
 626 |             'torch>=2.0.0',
 627 |             'torchvision',
 628 |             'torchaudio'
 629 |         ]
 630 |         
 631 |         print_info(f"Running: {' '.join(cmd)}")
 632 |         subprocess.check_call(cmd)
 633 |         
 634 |         # Install sentence-transformers
 635 |         print_info("Installing sentence-transformers (for embedding generation)...")
 636 |         print_info("Note: Models will be downloaded on first use (~25MB)")
 637 |         cmd = [
 638 |             sys.executable, '-m', 'pip', 'install',
 639 |             'sentence-transformers>=2.2.2'
 640 |         ]
 641 |         
 642 |         print_info(f"Running: {' '.join(cmd)}")
 643 |         subprocess.check_call(cmd)
 644 |         
 645 |         print_success("PyTorch and sentence-transformers installed successfully for macOS ARM64")
 646 |         print_info("MPS (Metal Performance Shaders) acceleration is available for GPU compute")
 647 |         
 648 |         return True
 649 |     except subprocess.SubprocessError as e:
 650 |         print_error(f"Failed to install PyTorch for macOS ARM64: {e}")
 651 |         
 652 |         # Provide fallback instructions
 653 |         print_warning("You may need to manually install PyTorch for Apple Silicon:")
 654 |         print_info("pip install torch torchvision torchaudio")
 655 |         print_info("pip install sentence-transformers")
 656 |         print_info("")
 657 |         print_info("If you encounter issues, try:")
 658 |         print_info("pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cpu")
 659 |         
 660 |         return False
 661 | 
 662 | def install_pytorch_windows(gpu_info):
 663 |     """Install PyTorch on Windows using the appropriate index URL."""
 664 |     print_step("3a", "Installing PyTorch for Windows")
 665 |     
 666 |     # Check if PyTorch is already installed and compatible
 667 |     pytorch_installed = False
 668 |     torch_version_installed = None
 669 |     directml_compatible = False
 670 |     
 671 |     try:
 672 |         import torch
 673 |         torch_version_installed = torch.__version__
 674 |         pytorch_installed = True
 675 |         print_info(f"PyTorch {torch_version_installed} is already installed")
 676 |         
 677 |         # Check if version is compatible with DirectML (2.4.x works, 2.5.x doesn't)
 678 |         version_parts = torch_version_installed.split('.')
 679 |         major, minor = int(version_parts[0]), int(version_parts[1])
 680 |         
 681 |         if gpu_info["has_directml"]:
 682 |             if major == 2 and minor == 4:
 683 |                 directml_compatible = True
 684 |                 print_success(f"PyTorch {torch_version_installed} is compatible with DirectML")
 685 |                 
 686 |                 # Check if torch-directml is also installed
 687 |                 try:
 688 |                     import torch_directml
 689 |                     directml_version = getattr(torch_directml, '__version__', 'Unknown version')
 690 |                     print_success(f"torch-directml {directml_version} is already installed")
 691 |                     return True  # Everything is compatible, no need to reinstall
 692 |                 except ImportError:
 693 |                     print_info("torch-directml not found, will install it")
 694 |                     # Install torch-directml only
 695 |                     try:
 696 |                         subprocess.check_call([
 697 |                             sys.executable, '-m', 'pip', 'install', 'torch-directml==0.2.5.dev240914'
 698 |                         ])
 699 |                         print_success("torch-directml installed successfully")
 700 |                         return True
 701 |                     except subprocess.SubprocessError:
 702 |                         print_warning("Failed to install torch-directml - DirectML support will be limited")
 703 |                         return True  # Still return True since PyTorch works
 704 |                         
 705 |             elif major == 2 and minor >= 5:
 706 |                 print_warning(f"PyTorch {torch_version_installed} is not compatible with torch-directml")
 707 |                 print_info("torch-directml requires PyTorch 2.4.x, but 2.5.x is installed")
 708 |                 print_info("Keeping existing PyTorch installation - DirectML support will be limited")
 709 |                 return True  # Don't break existing installation
 710 |             else:
 711 |                 print_info(f"PyTorch {torch_version_installed} compatibility with DirectML is unknown")
 712 |         else:
 713 |             # No DirectML needed, check if current version is reasonable
 714 |             if major == 2 and minor >= 4:
 715 |                 print_success(f"PyTorch {torch_version_installed} is acceptable for CPU usage")
 716 |                 return True  # Keep existing installation
 717 |                 
 718 |     except ImportError:
 719 |         print_info("PyTorch not found, will install compatible version")
 720 |     
 721 |     # If we get here, we need to install PyTorch
 722 |     # Determine the appropriate PyTorch index URL based on GPU
 723 |     if gpu_info["has_cuda"]:
 724 |         # Get CUDA version and determine appropriate index URL
 725 |         cuda_version = gpu_info.get("cuda_version", "")
 726 |         
 727 |         # Extract major version from CUDA version string
 728 |         cuda_major = None
 729 |         if cuda_version:
 730 |             # Try to extract the major version (e.g., "11.8" -> "11")
 731 |             try:
 732 |                 cuda_major = cuda_version.split('.')[0]
 733 |             except (IndexError, AttributeError):
 734 |                 pass
 735 |         
 736 |         # Default to cu118 if we couldn't determine the version or it's not a common one
 737 |         if cuda_major == "12":
 738 |             cuda_suffix = "cu121"  # CUDA 12.x
 739 |             print_info(f"Detected CUDA {cuda_version}, using cu121 channel")
 740 |         elif cuda_major == "11":
 741 |             cuda_suffix = "cu118"  # CUDA 11.x
 742 |             print_info(f"Detected CUDA {cuda_version}, using cu118 channel")
 743 |         elif cuda_major == "10":
 744 |             cuda_suffix = "cu102"  # CUDA 10.x
 745 |             print_info(f"Detected CUDA {cuda_version}, using cu102 channel")
 746 |         else:
 747 |             # Default to cu118 as a safe choice for newer NVIDIA GPUs
 748 |             cuda_suffix = "cu118"
 749 |             print_info(f"Using default cu118 channel for CUDA {cuda_version}")
 750 |             
 751 |         index_url = f"https://download.pytorch.org/whl/{cuda_suffix}"
 752 |     else:
 753 |         # CPU-only version
 754 |         index_url = "https://download.pytorch.org/whl/cpu"
 755 |         print_info("Using CPU-only PyTorch for Windows")
 756 |     
 757 |     # Install PyTorch with the appropriate index URL
 758 |     try:
 759 |         # Use versions compatible with DirectML if needed
 760 |         if gpu_info["has_directml"]:
 761 |             # Use PyTorch 2.4.x which is compatible with torch-directml
 762 |             torch_version = "2.4.1"
 763 |             torchvision_version = "0.19.1"  # Compatible with torch 2.4.1
 764 |             torchaudio_version = "2.4.1"
 765 |             print_info("Using PyTorch 2.4.1 for DirectML compatibility")
 766 |         else:
 767 |             # Use latest version for non-DirectML systems
 768 |             torch_version = "2.5.1"
 769 |             torchvision_version = "0.20.1"  # Compatible with torch 2.5.1
 770 |             torchaudio_version = "2.5.1"
 771 |             print_info("Using PyTorch 2.5.1 for optimal performance")
 772 |         
 773 |         cmd = [
 774 |             sys.executable, '-m', 'pip', 'install',
 775 |             f"torch=={torch_version}",
 776 |             f"torchvision=={torchvision_version}",
 777 |             f"torchaudio=={torchaudio_version}",
 778 |             f"--index-url={index_url}"
 779 |         ]
 780 |         
 781 |         print_info(f"Running: {' '.join(cmd)}")
 782 |         subprocess.check_call(cmd)
 783 |         
 784 |         # Check if DirectML is needed
 785 |         if gpu_info["has_directml"]:
 786 |             print_info("Installing torch-directml for DirectML support")
 787 |             try:
 788 |                 # Try the latest dev version since stable versions aren't available
 789 |                 subprocess.check_call([
 790 |                     sys.executable, '-m', 'pip', 'install', 'torch-directml==0.2.5.dev240914'
 791 |                 ])
 792 |             except subprocess.SubprocessError:
 793 |                 print_warning("Failed to install torch-directml - DirectML support will be limited")
 794 |                 print_info("You can install manually later with: pip install torch-directml==0.2.5.dev240914")
 795 |             
 796 |         print_success("PyTorch installed successfully for Windows")
 797 |         return True
 798 |     except subprocess.SubprocessError as e:
 799 |         print_error(f"Failed to install PyTorch for Windows: {e}")
 800 |         print_warning("You may need to manually install PyTorch using instructions from https://pytorch.org/get-started/locally/")
 801 |         return False
 802 | 
 803 | def detect_storage_backend_compatibility(system_info, gpu_info):
 804 |     """Detect which storage backends are compatible with the current environment."""
 805 |     print_step("3a", "Analyzing storage backend compatibility")
 806 |     
 807 |     compatibility = {
 808 |         "chromadb": {"supported": True, "issues": [], "recommendation": "legacy"},
 809 |         "sqlite_vec": {"supported": True, "issues": [], "recommendation": "default"}
 810 |     }
 811 |     
 812 |     # Check ChromaDB compatibility issues
 813 |     chromadb_issues = []
 814 |     
 815 |     # macOS Intel compatibility issues
 816 |     if system_info["is_macos"] and system_info["is_x86"]:
 817 |         chromadb_issues.append("ChromaDB has known installation issues on older macOS Intel systems")
 818 |         chromadb_issues.append("May require specific dependency versions")
 819 |         compatibility["chromadb"]["recommendation"] = "problematic"
 820 |         compatibility["sqlite_vec"]["recommendation"] = "recommended"
 821 |     
 822 |     # Memory constraints
 823 |     total_memory_gb = 0
 824 |     try:
 825 |         import psutil
 826 |         total_memory_gb = psutil.virtual_memory().total / (1024**3)
 827 |     except ImportError:
 828 |         # Fallback memory detection
 829 |         try:
 830 |             with open('/proc/meminfo', 'r') as f:
 831 |                 for line in f:
 832 |                     if line.startswith('MemTotal:'):
 833 |                         total_memory_gb = int(line.split()[1]) / (1024**2)
 834 |                         break
 835 |         except (FileNotFoundError, IOError):
 836 |             pass
 837 |     
 838 |     if total_memory_gb > 0 and total_memory_gb < 4:
 839 |         chromadb_issues.append(f"System has {total_memory_gb:.1f}GB RAM - ChromaDB may consume significant memory")
 840 |         compatibility["sqlite_vec"]["recommendation"] = "recommended"
 841 |     
 842 |     # Older Python versions
 843 |     python_version = f"{sys.version_info.major}.{sys.version_info.minor}"
 844 |     if sys.version_info < (3, 9):
 845 |         chromadb_issues.append(f"Python {python_version} may have ChromaDB compatibility issues")
 846 |     
 847 |     # ARM architecture considerations
 848 |     if system_info["is_arm"]:
 849 |         print_info("ARM architecture detected - both backends should work well")
 850 |     
 851 |     compatibility["chromadb"]["issues"] = chromadb_issues
 852 |     
 853 |     # Print compatibility analysis
 854 |     print_info("Storage Backend Compatibility Analysis:")
 855 |     
 856 |     for backend, info in compatibility.items():
 857 |         status = "[OK]" if info["supported"] else "[X]"
 858 |         rec_text = {
 859 |             "recommended": "[*] RECOMMENDED",
 860 |             "default": "[+] Standard",
 861 |             "problematic": "[!] May have issues",
 862 |             "lightweight": "[-] Lightweight"
 863 |         }.get(info["recommendation"], "")
 864 |         
 865 |         print_info(f"  {status} {backend.upper()}: {rec_text}")
 866 |         
 867 |         if info["issues"]:
 868 |             for issue in info["issues"]:
 869 |                 print_info(f"    • {issue}")
 870 |     
 871 |     return compatibility
 872 | 
 873 | def choose_storage_backend(system_info, gpu_info, args):
 874 |     """Choose storage backend based on environment and user preferences."""
 875 |     compatibility = detect_storage_backend_compatibility(system_info, gpu_info)
 876 |     
 877 |     # Check if user specified a backend via environment
 878 |     env_backend = os.environ.get('MCP_MEMORY_STORAGE_BACKEND')
 879 |     if env_backend:
 880 |         print_info(f"Using storage backend from environment: {env_backend}")
 881 |         return env_backend
 882 |     
 883 |     # Check for command line argument (we'll add this)
 884 |     if hasattr(args, 'storage_backend') and args.storage_backend:
 885 |         print_info(f"Using storage backend from command line: {args.storage_backend}")
 886 |         return args.storage_backend
 887 |     
 888 |     # Auto-select based on compatibility
 889 |     recommended_backend = None
 890 |     for backend, info in compatibility.items():
 891 |         if info["recommendation"] == "recommended":
 892 |             recommended_backend = backend
 893 |             break
 894 |     
 895 |     if not recommended_backend:
 896 |         recommended_backend = "sqlite_vec"  # Default fallback
 897 |     
 898 |     # Interactive selection if no auto-recommendation is clear
 899 |     if compatibility["chromadb"]["recommendation"] == "problematic":
 900 |         print_step("3b", "Storage Backend Selection")
 901 |         print_info("Based on your system, ChromaDB may have installation issues.")
 902 |         print_info("SQLite-vec is recommended as a lightweight, compatible alternative.")
 903 |         print_info("")
 904 |         print_info("Available options:")
 905 |         print_info("  1. SQLite-vec (Recommended) - Lightweight, fast, minimal dependencies")
 906 |         print_info("  2. ChromaDB (Standard) - Full-featured but may have issues on your system")
 907 |         print_info("  3. Auto-detect - Try ChromaDB first, fallback to SQLite-vec if it fails")
 908 |         print_info("")
 909 |         
 910 |         while True:
 911 |             try:
 912 |                 if args.non_interactive:
 913 |                     print_info("Non-interactive mode: using default storage backend (SQLite-vec)")
 914 |                     choice = "1"
 915 |                 else:
 916 |                     choice = prompt_user_input("Choose storage backend [1-3] (default: 1, press Enter for default): ", "1")
 917 |                 
 918 |                 if choice == "1":
 919 |                     return "sqlite_vec"
 920 |                 elif choice == "2":
 921 |                     return "chromadb"
 922 |                 elif choice == "3":
 923 |                     return "auto_detect"
 924 |                 else:
 925 |                     print_error("Please enter 1, 2, or 3")
 926 |             except (EOFError, KeyboardInterrupt):
 927 |                 print_info("\nUsing recommended backend: sqlite_vec")
 928 |                 return "sqlite_vec"
 929 |     
 930 |     return recommended_backend
 931 | 
 932 | def install_storage_backend(backend, system_info):
 933 |     """Install the chosen storage backend."""
 934 |     print_step("3c", f"Installing {backend} storage backend")
 935 |     
 936 |     if backend == "sqlite_vec":
 937 |         # Check extension support before attempting installation
 938 |         extension_supported, extension_message = check_sqlite_extension_support()
 939 |         if not extension_supported:
 940 |             print_warning(f"SQLite extension support not available: {extension_message}")
 941 |             
 942 |             # Provide platform-specific guidance
 943 |             if platform.system().lower() == "darwin":  # macOS
 944 |                 print_info("This is common on macOS with system Python.")
 945 |                 print_info("SOLUTIONS:")
 946 |                 print_info("  • Install Python via Homebrew: brew install python")
 947 |                 print_info("  • Use pyenv with extensions: PYTHON_CONFIGURE_OPTS='--enable-loadable-sqlite-extensions' pyenv install 3.12.0")
 948 |                 print_info("  • Switch to ChromaDB backend: --storage-backend chromadb")
 949 |                 
 950 |                 # Ask user what they want to do
 951 |                 if not system_info.get('non_interactive'):
 952 |                     print("\n" + "=" * 60)
 953 |                     print("⚠️  USER INPUT REQUIRED")
 954 |                     print("=" * 60)
 955 |                     print("sqlite-vec requires SQLite extension support, which is not available.")
 956 |                     response = input("Switch to ChromaDB backend instead? (y/N): ").strip().lower()
 957 |                     print("=" * 60 + "\n")
 958 |                     if response in ['y', 'yes']:
 959 |                         print_info("Switching to ChromaDB backend...")
 960 |                         return install_storage_backend("chromadb", system_info)
 961 |                     else:
 962 |                         print_info("Continuing with sqlite-vec installation (may fail at runtime)...")
 963 |                 else:
 964 |                     print_info("Non-interactive mode: attempting sqlite-vec installation anyway")
 965 |             else:
 966 |                 print_info("Consider switching to ChromaDB backend for better compatibility")
 967 |         
 968 |         # Special handling for Python 3.13
 969 |         if sys.version_info >= (3, 13):
 970 |             print_info("Detected Python 3.13+ - using special installation method for sqlite-vec")
 971 |             return install_sqlite_vec_python313(system_info)
 972 |         
 973 |         # Standard installation for older Python versions
 974 |         try:
 975 |             print_info("Installing SQLite-vec...")
 976 |             subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'sqlite-vec'])
 977 |             print_success("SQLite-vec installed successfully")
 978 |             return True
 979 |         except subprocess.SubprocessError as e:
 980 |             print_error(f"Failed to install SQLite-vec: {e}")
 981 |             return False
 982 |             
 983 |     elif backend == "chromadb":
 984 |         print_error("ChromaDB backend has been removed in v8.0.0")
 985 |         print_info("Please use one of the supported backends:")
 986 |         print_info("  - 'hybrid': Local speed + cloud persistence (recommended)")
 987 |         print_info("  - 'sqlite_vec': Fast local storage")
 988 |         print_info("  - 'cloudflare': Cloud storage only")
 989 |         print_info("\nTo migrate from ChromaDB, run: python scripts/migration/migrate_to_sqlite_vec.py")
 990 |         return False
 991 |             
 992 |     elif backend == "auto_detect":
 993 |         print_info("Attempting auto-detection...")
 994 |         
 995 |         # Try ChromaDB first
 996 |         print_info("Trying ChromaDB installation...")
 997 |         if install_storage_backend("chromadb", system_info):
 998 |             print_success("ChromaDB installed successfully")
 999 |             return "chromadb"
1000 |         
1001 |         print_warning("ChromaDB installation failed, falling back to SQLite-vec...")
1002 |         if install_storage_backend("sqlite_vec", system_info):
1003 |             print_success("SQLite-vec installed successfully as fallback")
1004 |             return "sqlite_vec"
1005 |         
1006 |         print_error("Both storage backends failed to install")
1007 |         return False
1008 |     
1009 |     return False
1010 | 
1011 | def initialize_sqlite_vec_database(storage_path):
1012 |     """Initialize SQLite-vec database during installation."""
1013 |     try:
1014 |         print_info("Initializing SQLite-vec database...")
1015 |         
1016 |         # Add src to path for imports
1017 |         src_path = str(Path(__file__).parent / "src")
1018 |         if src_path not in sys.path:
1019 |             sys.path.insert(0, src_path)
1020 |         
1021 |         # Import required modules
1022 |         from mcp_memory_service.storage.sqlite_vec import SqliteVecMemoryStorage
1023 |         from mcp_memory_service.models.memory import Memory
1024 |         from mcp_memory_service.utils.hashing import generate_content_hash
1025 |         import asyncio
1026 |         
1027 |         async def init_db():
1028 |             # Create storage instance
1029 |             storage = SqliteVecMemoryStorage(str(storage_path))
1030 |             
1031 |             # Initialize the database
1032 |             await storage.initialize()
1033 |             
1034 |             # Create a test memory to verify the database works
1035 |             test_content = "Database initialization successful"
1036 |             test_memory = Memory(
1037 |                 content=test_content,
1038 |                 content_hash=generate_content_hash(test_content),
1039 |                 tags=["init", "system"],
1040 |                 memory_type="system"
1041 |             )
1042 |             
1043 |             # Store test memory
1044 |             success, message = await storage.store(test_memory)
1045 |             return success, message
1046 |         
1047 |         # Run initialization
1048 |         success, message = asyncio.run(init_db())
1049 |         
1050 |         if success:
1051 |             print_success(f"SQLite-vec database initialized: {storage_path}")
1052 |             return True
1053 |         else:
1054 |             print_warning(f"Database initialization partially failed: {message}")
1055 |             return True  # Database exists even if test failed
1056 |             
1057 |     except ImportError as e:
1058 |         print_warning(f"Could not initialize database (dependencies missing): {e}")
1059 |         print_info("Database will be initialized on first use")
1060 |         return True  # Not a critical failure
1061 |     except Exception as e:
1062 |         print_warning(f"Database initialization failed: {e}")
1063 |         print_info("Database will be initialized on first use")
1064 |         return True  # Not a critical failure
1065 | 
1066 | def install_sqlite_vec_python313(system_info):
1067 |     """Special installation method for sqlite-vec on Python 3.13+."""
1068 |     print_info("Python 3.13+ detected - sqlite-vec may not have pre-built wheels yet")
1069 |     
1070 |     # Check if uv is available
1071 |     uv_path = shutil.which("uv")
1072 |     use_uv = uv_path is not None
1073 |     
1074 |     # Try multiple installation strategies
1075 |     strategies = []
1076 |     
1077 |     if use_uv:
1078 |         # Strategy 1: Try with uv pip
1079 |         strategies.append({
1080 |             'name': 'uv pip install',
1081 |             'cmd': [uv_path, 'pip', 'install', 'sqlite-vec'],
1082 |             'description': 'Installing with uv package manager'
1083 |         })
1084 |         
1085 |         # Strategy 2: Try with uv pip and no-binary flag
1086 |         strategies.append({
1087 |             'name': 'uv pip install (source build)',
1088 |             'cmd': [uv_path, 'pip', 'install', '--no-binary', ':all:', 'sqlite-vec'],
1089 |             'description': 'Building from source with uv'
1090 |         })
1091 |     
1092 |     # Strategy 3: Standard pip install
1093 |     strategies.append({
1094 |         'name': 'pip install',
1095 |         'cmd': [sys.executable, '-m', 'pip', 'install', 'sqlite-vec'],
1096 |         'description': 'Installing with pip'
1097 |     })
1098 |     
1099 |     # Strategy 4: pip with no-binary flag to force compilation
1100 |     strategies.append({
1101 |         'name': 'pip install (source build)',
1102 |         'cmd': [sys.executable, '-m', 'pip', 'install', '--no-binary', ':all:', 'sqlite-vec'],
1103 |         'description': 'Building from source with pip'
1104 |     })
1105 |     
1106 |     # Strategy 5: Install from GitHub directly
1107 |     strategies.append({
1108 |         'name': 'GitHub install',
1109 |         'cmd': [sys.executable, '-m', 'pip', 'install', 'git+https://github.com/asg017/sqlite-vec.git#subdirectory=python'],
1110 |         'description': 'Installing directly from GitHub'
1111 |     })
1112 |     
1113 |     # Try each strategy
1114 |     for i, strategy in enumerate(strategies, 1):
1115 |         try:
1116 |             print_info(f"Attempt {i}/{len(strategies)}: {strategy['description']}...")
1117 |             subprocess.check_call(strategy['cmd'], stderr=subprocess.PIPE)
1118 |             print_success(f"SQLite-vec installed successfully using {strategy['name']}")
1119 |             return True
1120 |         except subprocess.CalledProcessError as e:
1121 |             print_warning(f"{strategy['name']} failed: {e}")
1122 |             if i < len(strategies):
1123 |                 print_info("Trying next installation method...")
1124 |             continue
1125 |         except Exception as e:
1126 |             print_warning(f"{strategy['name']} failed with unexpected error: {e}")
1127 |             continue
1128 |     
1129 |     # All strategies failed - provide manual instructions
1130 |     print_error("Failed to install sqlite-vec with all automatic methods")
1131 |     print_info("")
1132 |     print_info("MANUAL INSTALLATION OPTIONS:")
1133 |     print_info("")
1134 |     print_info("Option 1: Use Python 3.12 (recommended)")
1135 |     print_info("  1. Install Python 3.12: brew install [email protected]")
1136 |     print_info("  2. Create venv: python3.12 -m venv .venv")
1137 |     print_info("  3. Activate: source .venv/bin/activate")
1138 |     print_info("  4. Re-run: python install.py")
1139 |     print_info("")
1140 |     print_info("Option 2: Install pysqlite3-binary (alternative)")
1141 |     print_info("  pip install pysqlite3-binary")
1142 |     print_info("")
1143 |     print_info("Option 3: Wait for sqlite-vec Python 3.13 support")
1144 |     print_info("  Check: https://github.com/asg017/sqlite-vec/issues")
1145 |     print_info("")
1146 |     print_info("Option 4: Use hybrid or cloudflare backend")
1147 |     print_info("  python install.py --storage-backend hybrid")
1148 |     print_info("")
1149 | 
1150 |     # Note: ChromaDB option removed in v8.0.0
1151 |     
1152 |     return False
1153 | 
1154 | def install_uv():
1155 |     """Install uv package manager if not already installed."""
1156 |     uv_path = shutil.which("uv")
1157 |     if uv_path:
1158 |         print_info(f"uv is already installed at: {uv_path}")
1159 |         return uv_path
1160 |     
1161 |     print_info("Installing uv package manager...")
1162 |     
1163 |     try:
1164 |         # Determine the installation directory
1165 |         if platform.system() == 'Windows':
1166 |             # On Windows, install to user's AppData/Local
1167 |             install_dir = os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'uv')
1168 |         else:
1169 |             # On Unix-like systems, install to ~/.local/bin
1170 |             install_dir = os.path.expanduser("~/.local/bin")
1171 |         
1172 |         # Create installation directory if it doesn't exist
1173 |         os.makedirs(install_dir, exist_ok=True)
1174 |         
1175 |         # Download and install uv
1176 |         if platform.system() == 'Windows':
1177 |             # Windows installation
1178 |             install_script = "powershell -c \"irm https://astral.sh/uv/install.ps1 | iex\""
1179 |             subprocess.check_call(install_script, shell=True)
1180 |         else:
1181 |             # Unix-like installation
1182 |             install_script = "curl -LsSf https://astral.sh/uv/install.sh | sh"
1183 |             subprocess.check_call(install_script, shell=True)
1184 |         
1185 |         # Check if uv was installed successfully
1186 |         uv_path = shutil.which("uv")
1187 |         if not uv_path:
1188 |             # Try common installation paths
1189 |             if platform.system() == 'Windows':
1190 |                 possible_paths = [
1191 |                     os.path.join(install_dir, 'uv.exe'),
1192 |                     os.path.join(os.environ.get('USERPROFILE', ''), '.cargo', 'bin', 'uv.exe')
1193 |                 ]
1194 |             else:
1195 |                 possible_paths = [
1196 |                     os.path.join(install_dir, 'uv'),
1197 |                     os.path.expanduser("~/.cargo/bin/uv")
1198 |                 ]
1199 |             
1200 |             for path in possible_paths:
1201 |                 if os.path.exists(path):
1202 |                     uv_path = path
1203 |                     break
1204 |         
1205 |         if uv_path:
1206 |             print_success(f"uv installed successfully at: {uv_path}")
1207 |             return uv_path
1208 |         else:
1209 |             print_error("uv installation completed but executable not found in PATH")
1210 |             print_info("You may need to add the installation directory to your PATH")
1211 |             return None
1212 |             
1213 |     except subprocess.CalledProcessError as e:
1214 |         print_error(f"Failed to install uv: {e}")
1215 |         return None
1216 |     except Exception as e:
1217 |         print_error(f"Unexpected error installing uv: {e}")
1218 |         return None
1219 | 
1220 | def _setup_installer_command():
1221 |     """Set up the installer command prefix (pip or uv).
1222 |     
1223 |     Returns:
1224 |         tuple: (installer_cmd: list, uv_path: str or None)
1225 |     """
1226 |     # Detect if pip is available
1227 |     pip_available = False
1228 |     try:
1229 |         subprocess.check_call([sys.executable, '-m', 'pip', '--version'],
1230 |                               stdout=subprocess.DEVNULL,
1231 |                               stderr=subprocess.DEVNULL)
1232 |         pip_available = True
1233 |     except subprocess.SubprocessError:
1234 |         pip_available = False
1235 | 
1236 |     # Try to install uv if pip is not available
1237 |     if not pip_available:
1238 |         print_info("pip not found, attempting to install uv package manager...")
1239 |         uv_path = install_uv()
1240 |     else:
1241 |         # Check if uv is already available
1242 |         uv_path = shutil.which("uv")
1243 |         if uv_path:
1244 |             print_info(f"uv package manager found at: {uv_path}")
1245 |         else:
1246 |             print_info("uv package manager not found (will use pip for installation)")
1247 |     
1248 |     # Store the uv path globally for config generation
1249 |     global UV_EXECUTABLE_PATH
1250 |     UV_EXECUTABLE_PATH = uv_path
1251 | 
1252 |     # Decide installer command prefix
1253 |     if pip_available:
1254 |         installer_cmd = [sys.executable, '-m', 'pip']
1255 |     elif uv_path:
1256 |         installer_cmd = [uv_path, 'pip']
1257 |         print_info(f"Using uv for installation: {uv_path}")
1258 |     else:
1259 |         print_error("Neither pip nor uv could be found or installed. Cannot install packages.")
1260 |         return None, None
1261 | 
1262 |     return installer_cmd, uv_path
1263 | 
1264 | 
1265 | def _configure_storage_and_gpu(args):
1266 |     """Configure storage backend and GPU environment variables.
1267 |     
1268 |     Args:
1269 |         args: Parsed command line arguments
1270 |         
1271 |     Returns:
1272 |         tuple: (env: dict, system_info: dict, gpu_info: dict, chosen_backend: str)
1273 |     """
1274 |     env = os.environ.copy()
1275 |     
1276 |     # Get system and GPU info
1277 |     system_info = detect_system()
1278 |     gpu_info = detect_gpu()
1279 | 
1280 |     # Choose and install storage backend
1281 |     chosen_backend = choose_storage_backend(system_info, gpu_info, args)
1282 |     if chosen_backend == "auto_detect":
1283 |         # Handle auto-detection case
1284 |         actual_backend = install_storage_backend(chosen_backend, system_info)
1285 |         if not actual_backend:
1286 |             print_error("Failed to install any storage backend")
1287 |             return None, None, None, None
1288 |         chosen_backend = actual_backend
1289 |     else:
1290 |         # Install the chosen backend
1291 |         if not install_storage_backend(chosen_backend, system_info):
1292 |             print_error(f"Failed to install {chosen_backend} storage backend")
1293 |             return None, None, None, None
1294 | 
1295 |     # Set environment variable for chosen backend
1296 |     if chosen_backend == "sqlite_vec":
1297 |         env['MCP_MEMORY_STORAGE_BACKEND'] = 'sqlite_vec'
1298 |         os.environ['MCP_MEMORY_STORAGE_BACKEND'] = 'sqlite_vec'
1299 |         print_info("Configured to use SQLite-vec storage backend")
1300 |     else:
1301 |         env['MCP_MEMORY_STORAGE_BACKEND'] = 'chromadb'
1302 |         os.environ['MCP_MEMORY_STORAGE_BACKEND'] = 'chromadb'
1303 |         print_info("Configured to use ChromaDB storage backend")
1304 | 
1305 |     # Set environment variables based on detected GPU
1306 |     if gpu_info.get("has_cuda"):
1307 |         print_info("Configuring for CUDA installation")
1308 |     elif gpu_info.get("has_rocm"):
1309 |         print_info("Configuring for ROCm installation")
1310 |         env['MCP_MEMORY_USE_ROCM'] = '1'
1311 |     elif gpu_info.get("has_mps"):
1312 |         print_info("Configuring for Apple Silicon MPS installation")
1313 |         env['PYTORCH_ENABLE_MPS_FALLBACK'] = '1'
1314 |     elif gpu_info.get("has_directml"):
1315 |         print_info("Configuring for DirectML installation")
1316 |         env['MCP_MEMORY_USE_DIRECTML'] = '1'
1317 |     else:
1318 |         print_info("Configuring for CPU-only installation")
1319 |         env['MCP_MEMORY_USE_ONNX'] = '1'
1320 | 
1321 |     return env, system_info, gpu_info, chosen_backend
1322 | 
1323 | 
1324 | def _handle_pytorch_setup(args, system_info, gpu_info, env):
1325 |     """Handle PyTorch installation logic.
1326 |     
1327 |     Args:
1328 |         args: Parsed command line arguments
1329 |         system_info: System information dict
1330 |         gpu_info: GPU information dict
1331 |         env: Environment variables dict
1332 |         
1333 |     Returns:
1334 |         tuple: (using_homebrew_pytorch: bool, pytorch_installed: bool, env: dict)
1335 |     """
1336 |     # Check for Homebrew PyTorch installation
1337 |     using_homebrew_pytorch = False
1338 |     if system_info.get("has_homebrew_pytorch"):
1339 |         print_info(f"Using existing Homebrew PyTorch installation (version: {system_info.get('homebrew_pytorch_version')})")
1340 |         using_homebrew_pytorch = True
1341 |         # Set the environment variable to use ONNX for embeddings
1342 |         env['MCP_MEMORY_USE_ONNX'] = '1'
1343 |         pytorch_installed = True
1344 |     else:
1345 |         # Handle platform-specific PyTorch installation
1346 |         pytorch_installed = install_pytorch_platform_specific(system_info, gpu_info, args)
1347 |         if not pytorch_installed:
1348 |             print_warning("Platform-specific PyTorch installation failed, but will continue with package installation")
1349 | 
1350 |     return using_homebrew_pytorch, pytorch_installed, env
1351 | 
1352 | 
1353 | def _should_use_onnx_installation(system_info, args, using_homebrew_pytorch):
1354 |     """Determine if ONNX installation path should be used.
1355 |     
1356 |     Args:
1357 |         system_info: System information dict
1358 |         args: Parsed command line arguments
1359 |         using_homebrew_pytorch: Whether Homebrew PyTorch is being used
1360 |         
1361 |     Returns:
1362 |         bool: True if ONNX installation path should be used
1363 |     """
1364 |     return (system_info["is_macos"] and system_info["is_x86"] and 
1365 |             (sys.version_info >= (3, 13) or using_homebrew_pytorch or args.skip_pytorch))
1366 | 
1367 | 
1368 | def _install_with_onnx(installer_cmd, install_mode, chosen_backend, env, using_homebrew_pytorch):
1369 |     """Install using SQLite-vec + ONNX configuration.
1370 |     
1371 |     Args:
1372 |         installer_cmd: Command prefix for installer
1373 |         install_mode: Installation mode flags (-e for dev mode)
1374 |         chosen_backend: Storage backend name
1375 |         env: Environment variables
1376 |         using_homebrew_pytorch: Whether using Homebrew PyTorch
1377 |         
1378 |     Returns:
1379 |         bool: True if installation succeeded, False otherwise
1380 |     """
1381 |     try:
1382 |         # Print installation context
1383 |         if using_homebrew_pytorch:
1384 |             print_info("Using Homebrew PyTorch - installing with SQLite-vec + ONNX configuration")
1385 |         elif install_mode:
1386 |             print_info("Skipping PyTorch installation - using SQLite-vec + ONNX configuration")
1387 |         else:
1388 |             print_info("Using Python 3.13+ on macOS Intel - using SQLite-vec + ONNX configuration")
1389 |         
1390 |         # Install without ML dependencies
1391 |         cmd = installer_cmd + ['install', '--no-deps'] + install_mode + ['.']
1392 |         print_info(f"Running: {' '.join(cmd)}")
1393 |         subprocess.check_call(cmd, env=env)
1394 |         
1395 |         # Install core dependencies except torch/sentence-transformers
1396 |         print_info("Installing core dependencies (without ML libraries for compatibility)...")
1397 |         print_info("Note: First run will download embedding models automatically (~25MB)")
1398 |         
1399 |         # Build dependency list
1400 |         dependencies = [
1401 |             "mcp>=1.0.0,<2.0.0",
1402 |             "onnxruntime>=1.14.1",  # ONNX runtime for embeddings
1403 |             "tokenizers>=0.20.0",  # Required for ONNX tokenization
1404 |             "httpx>=0.24.0",  # For downloading ONNX models
1405 |             "aiohttp>=3.8.0"  # Required for MCP server functionality
1406 |         ]
1407 |         
1408 |         # Add backend-specific dependencies
1409 |         if chosen_backend == "sqlite_vec":
1410 |             dependencies.append("sqlite-vec>=0.1.0")
1411 |         else:
1412 |             dependencies.append("chromadb==0.5.23")
1413 |             dependencies.append("tokenizers==0.20.3")
1414 |         
1415 |         # Install dependencies
1416 |         subprocess.check_call([sys.executable, '-m', 'pip', 'install'] + dependencies)
1417 |         
1418 |         # Configure ONNX runtime
1419 |         print_info("Configuring to use ONNX runtime for inference without PyTorch...")
1420 |         env['MCP_MEMORY_USE_ONNX'] = '1'
1421 |         os.environ['MCP_MEMORY_USE_ONNX'] = '1'
1422 |         
1423 |         # Switch to SQLite-vec if needed
1424 |         if chosen_backend != "sqlite_vec":
1425 |             print_info("Switching to SQLite-vec backend for better compatibility")
1426 |             env['MCP_MEMORY_STORAGE_BACKEND'] = 'sqlite_vec'
1427 |             os.environ['MCP_MEMORY_STORAGE_BACKEND'] = 'sqlite_vec'
1428 |         
1429 |         print_success("MCP Memory Service installed successfully (SQLite-vec + ONNX)")
1430 |         
1431 |         if using_homebrew_pytorch:
1432 |             print_info("Using Homebrew PyTorch installation for embedding generation")
1433 |             print_info("Environment configured to use SQLite-vec backend and ONNX runtime")
1434 |         else:
1435 |             print_warning("ML libraries (PyTorch/sentence-transformers) were not installed due to compatibility issues")
1436 |             print_info("The service will use ONNX runtime for inference instead")
1437 |         
1438 |         return True
1439 |     except subprocess.SubprocessError as e:
1440 |         print_error(f"Failed to install with ONNX approach: {e}")
1441 |         return False
1442 | 
1443 | 
1444 | def _install_standard(installer_cmd, install_mode, env):
1445 |     """Perform standard pip/uv installation.
1446 |     
1447 |     Args:
1448 |         installer_cmd: Command prefix for installer
1449 |         install_mode: Installation mode flags (-e for dev mode)
1450 |         env: Environment variables
1451 |         
1452 |     Returns:
1453 |         bool: True if installation succeeded, False otherwise
1454 |     """
1455 |     try:
1456 |         cmd = installer_cmd + ['install'] + install_mode + ['.']
1457 |         print_info(f"Running: {' '.join(cmd)}")
1458 |         subprocess.check_call(cmd, env=env)
1459 |         print_success("MCP Memory Service installed successfully")
1460 |         return True
1461 |     except subprocess.SubprocessError as e:
1462 |         print_error(f"Failed to install MCP Memory Service: {e}")
1463 |         return False
1464 | 
1465 | 
1466 | def _handle_installation_failure(system_info):
1467 |     """Provide helpful guidance when installation fails.
1468 |     
1469 |     Args:
1470 |         system_info: System information dict
1471 |     """
1472 |     # Special handling for macOS with compatibility issues
1473 |     if system_info["is_macos"] and system_info["is_x86"]:
1474 |         print_warning("Installation on macOS Intel is challenging")
1475 |         print_info("Try manually installing with:")
1476 |         print_info("1. pip install --no-deps .")
1477 |         print_info("2. pip install sqlite-vec>=0.1.0 mcp>=1.0.0,<2.0.0 onnxruntime>=1.14.1 aiohttp>=3.8.0")
1478 |         print_info("3. export MCP_MEMORY_USE_ONNX=1")
1479 |         print_info("4. export MCP_MEMORY_STORAGE_BACKEND=sqlite_vec")
1480 |         
1481 |         if system_info.get("has_homebrew_pytorch"):
1482 |             print_info("Homebrew PyTorch was detected but installation still failed.")
1483 |             print_info("Try running: python install.py --storage-backend sqlite_vec --skip-pytorch")
1484 | 
1485 | 
1486 | def install_package(args):
1487 |     """Install the package with the appropriate dependencies, supporting pip or uv."""
1488 |     print_step("3", "Installing MCP Memory Service")
1489 | 
1490 |     # Determine installation mode
1491 |     install_mode = []
1492 |     if args.dev:
1493 |         install_mode = ['-e']
1494 |         print_info("Installing in development mode")
1495 | 
1496 |     # Setup installer command (pip or uv)
1497 |     installer_cmd, uv_path = _setup_installer_command()
1498 |     if installer_cmd is None:
1499 |         return False
1500 | 
1501 |     # Configure storage backend and GPU
1502 |     env, system_info, gpu_info, chosen_backend = _configure_storage_and_gpu(args)
1503 |     if env is None:
1504 |         return False
1505 | 
1506 |     # Handle PyTorch setup
1507 |     using_homebrew_pytorch, pytorch_installed, env = _handle_pytorch_setup(
1508 |         args, system_info, gpu_info, env
1509 |     )
1510 | 
1511 |     # Determine installation path
1512 |     if _should_use_onnx_installation(system_info, args, using_homebrew_pytorch):
1513 |         # Use ONNX-based installation for macOS Intel with Python 3.13+ or Homebrew PyTorch
1514 |         success = _install_with_onnx(installer_cmd, install_mode, chosen_backend, env, using_homebrew_pytorch)
1515 |         if success:
1516 |             return True
1517 |         # Fall through to standard installation if ONNX approach fails
1518 |     
1519 |     # Standard installation path
1520 |     success = _install_standard(installer_cmd, install_mode, env)
1521 |     if not success:
1522 |         _handle_installation_failure(system_info)
1523 |     
1524 |     return success
1525 | 
1526 | def configure_paths(args):
1527 |     """Configure paths for the MCP Memory Service."""
1528 |     print_step("4", "Configuring paths")
1529 |     
1530 |     # Get system info
1531 |     system_info = detect_system()
1532 |     
1533 |     # Determine home directory
1534 |     home_dir = Path.home()
1535 |     
1536 |     # Determine base directory based on platform
1537 |     if platform.system() == 'Darwin':  # macOS
1538 |         base_dir = home_dir / 'Library' / 'Application Support' / 'mcp-memory'
1539 |     elif platform.system() == 'Windows':  # Windows
1540 |         base_dir = Path(os.environ.get('LOCALAPPDATA', '')) / 'mcp-memory'
1541 |     else:  # Linux and others
1542 |         base_dir = home_dir / '.local' / 'share' / 'mcp-memory'
1543 |     
1544 |     # Create directories based on storage backend
1545 |     storage_backend = args.storage_backend or os.environ.get('MCP_MEMORY_STORAGE_BACKEND', 'sqlite_vec')
1546 |     
1547 |     if storage_backend == 'sqlite_vec':
1548 |         # For sqlite-vec, we need a database file path
1549 |         storage_path = args.chroma_path or (base_dir / 'sqlite_vec.db')
1550 |         storage_dir = storage_path.parent if storage_path.name.endswith('.db') else storage_path
1551 |         backups_path = args.backups_path or (base_dir / 'backups')
1552 |         
1553 |         try:
1554 |             os.makedirs(storage_dir, exist_ok=True)
1555 |             os.makedirs(backups_path, exist_ok=True)
1556 |             print_info(f"SQLite-vec database: {storage_path}")
1557 |             print_info(f"Backups path: {backups_path}")
1558 |             
1559 |             # Test if directory is writable
1560 |             test_file = os.path.join(storage_dir, '.write_test')
1561 |             with open(test_file, 'w') as f:
1562 |                 f.write('test')
1563 |             os.remove(test_file)
1564 |             
1565 |             # Initialize the SQLite-vec database
1566 |             if not initialize_sqlite_vec_database(storage_path):
1567 |                 print_warning("SQLite-vec database initialization failed, but continuing...")
1568 |                 
1569 |         except Exception as e:
1570 |             print_error(f"Failed to configure SQLite-vec paths: {e}")
1571 |             return False
1572 |     else:
1573 |         # ChromaDB configuration
1574 |         chroma_path = args.chroma_path or (base_dir / 'chroma_db')
1575 |         backups_path = args.backups_path or (base_dir / 'backups')
1576 |         storage_path = chroma_path
1577 |         
1578 |         try:
1579 |             os.makedirs(chroma_path, exist_ok=True)
1580 |             os.makedirs(backups_path, exist_ok=True)
1581 |             print_info(f"ChromaDB path: {chroma_path}")
1582 |             print_info(f"Backups path: {backups_path}")
1583 |             
1584 |             # Test if directories are writable
1585 |             test_file = os.path.join(chroma_path, '.write_test')
1586 |             with open(test_file, 'w') as f:
1587 |                 f.write('test')
1588 |             os.remove(test_file)
1589 |         except Exception as e:
1590 |             print_error(f"Failed to configure ChromaDB paths: {e}")
1591 |             return False
1592 |     
1593 |     # Test backups directory for both backends
1594 |     try:
1595 |         test_file = os.path.join(backups_path, '.write_test')
1596 |         with open(test_file, 'w') as f:
1597 |             f.write('test')
1598 |         os.remove(test_file)
1599 |         print_success("Storage directories created and are writable")
1600 |     except Exception as e:
1601 |         print_error(f"Failed to test backups directory: {e}")
1602 |         return False
1603 |     
1604 |     # Configure Claude Desktop if available
1605 |     claude_config_paths = [
1606 |             home_dir / 'Library' / 'Application Support' / 'Claude' / 'claude_desktop_config.json',
1607 |             home_dir / '.config' / 'Claude' / 'claude_desktop_config.json',
1608 |             Path('claude_config') / 'claude_desktop_config.json'
1609 |         ]
1610 |     
1611 |     for config_path in claude_config_paths:
1612 |         if config_path.exists():
1613 |             print_info(f"Found Claude Desktop config at {config_path}")
1614 |             try:
1615 |                 import json
1616 |                 with open(config_path, 'r') as f:
1617 |                     config = json.load(f)
1618 |                 
1619 |                 # Update or add MCP Memory configuration
1620 |                 if 'mcpServers' not in config:
1621 |                     config['mcpServers'] = {}
1622 |                 
1623 |                 # Create environment configuration based on storage backend
1624 |                 env_config = {
1625 |                     "MCP_MEMORY_BACKUPS_PATH": str(backups_path),
1626 |                     "MCP_MEMORY_STORAGE_BACKEND": storage_backend
1627 |                 }
1628 |                 
1629 |                 if storage_backend == 'sqlite_vec':
1630 |                     env_config["MCP_MEMORY_SQLITE_PATH"] = str(storage_path)
1631 |                 else:
1632 |                     env_config["MCP_MEMORY_CHROMA_PATH"] = str(storage_path)
1633 |                 
1634 |                 # Create or update the memory server configuration
1635 |                 if system_info["is_windows"]:
1636 |                     # Use the memory_wrapper.py script for Windows
1637 |                     script_path = os.path.abspath("memory_wrapper.py")
1638 |                     config['mcpServers']['memory'] = {
1639 |                         "command": "python",
1640 |                         "args": [script_path],
1641 |                         "env": env_config
1642 |                     }
1643 |                     print_info("Configured Claude Desktop to use memory_wrapper.py for Windows")
1644 |                 else:
1645 |                     # Use the standard configuration for other platforms
1646 |                     config['mcpServers']['memory'] = {
1647 |                         "command": UV_EXECUTABLE_PATH or "uv",
1648 |                         "args": [
1649 |                             "--directory",
1650 |                             os.path.abspath("."),
1651 |                             "run",
1652 |                             "memory"
1653 |                         ],
1654 |                         "env": env_config
1655 |                     }
1656 |                 
1657 |                 with open(config_path, 'w') as f:
1658 |                     json.dump(config, f, indent=2)
1659 |                 
1660 |                 print_success("Updated Claude Desktop configuration")
1661 |             except Exception as e:
1662 |                 print_warning(f"Failed to update Claude Desktop configuration: {e}")
1663 |             break
1664 |     
1665 |     return True
1666 | 
1667 | def verify_installation():
1668 |     """Verify the installation."""
1669 |     print_step("5", "Verifying installation")
1670 |     
1671 |     # Get system info
1672 |     system_info = detect_system()
1673 |     
1674 |     # Check if the package is installed
1675 |     try:
1676 |         import mcp_memory_service
1677 |         print_success(f"MCP Memory Service is installed: {mcp_memory_service.__file__}")
1678 |     except ImportError:
1679 |         print_error("MCP Memory Service is not installed correctly")
1680 |         return False
1681 |     
1682 |     # Check if the entry point is available
1683 |     memory_script = shutil.which('memory')
1684 |     if memory_script:
1685 |         print_success(f"Memory command is available: {memory_script}")
1686 |     else:
1687 |         print_warning("Memory command is not available in PATH")
1688 |     
1689 |     # Check storage backend installation
1690 |     storage_backend = os.environ.get('MCP_MEMORY_STORAGE_BACKEND', 'sqlite_vec')
1691 |     
1692 |     if storage_backend == 'sqlite_vec':
1693 |         try:
1694 |             import sqlite_vec
1695 |             print_success(f"SQLite-vec is installed: {sqlite_vec.__version__}")
1696 |         except ImportError:
1697 |             print_error("SQLite-vec is not installed correctly")
1698 |             return False
1699 |     elif storage_backend == 'chromadb':
1700 |         try:
1701 |             import chromadb
1702 |             print_success(f"ChromaDB is installed: {chromadb.__version__}")
1703 |         except ImportError:
1704 |             print_error("ChromaDB is not installed correctly")
1705 |             return False
1706 |     
1707 |     # Check for ONNX runtime
1708 |     try:
1709 |         import onnxruntime
1710 |         print_success(f"ONNX Runtime is installed: {onnxruntime.__version__}")
1711 |         use_onnx = os.environ.get('MCP_MEMORY_USE_ONNX', '').lower() in ('1', 'true', 'yes')
1712 |         if use_onnx:
1713 |             print_info("Environment configured to use ONNX runtime for embeddings")
1714 |             # Check for tokenizers (required for ONNX)
1715 |             try:
1716 |                 import tokenizers
1717 |                 print_success(f"Tokenizers is installed: {tokenizers.__version__}")
1718 |             except ImportError:
1719 |                 print_warning("Tokenizers not installed but required for ONNX embeddings")
1720 |                 print_info("Install with: pip install tokenizers>=0.20.0")
1721 |     except ImportError:
1722 |         print_warning("ONNX Runtime is not installed. This is recommended for PyTorch-free operation.")
1723 |         print_info("Install with: pip install onnxruntime>=1.14.1 tokenizers>=0.20.0")
1724 |     
1725 |     # Check for Homebrew PyTorch
1726 |     homebrew_pytorch = False
1727 |     if system_info.get("has_homebrew_pytorch"):
1728 |         homebrew_pytorch = True
1729 |         print_success(f"Homebrew PyTorch detected: {system_info.get('homebrew_pytorch_version')}")
1730 |         print_info("Using system-installed PyTorch instead of pip version")
1731 |     
1732 |     # Check ML dependencies as optional
1733 |     pytorch_installed = False
1734 |     try:
1735 |         import torch
1736 |         pytorch_installed = True
1737 |         print_info(f"PyTorch is installed: {torch.__version__}")
1738 |         
1739 |         # Check for CUDA
1740 |         if torch.cuda.is_available():
1741 |             print_success(f"CUDA is available: {torch.version.cuda}")
1742 |             print_info(f"GPU: {torch.cuda.get_device_name(0)}")
1743 |         # Check for MPS (Apple Silicon)
1744 |         elif hasattr(torch.backends, 'mps') and torch.backends.mps.is_available():
1745 |             print_success("MPS (Metal Performance Shaders) is available")
1746 |         # Check for DirectML
1747 |         else:
1748 |             try:
1749 |                 import torch_directml
1750 |                 version = getattr(torch_directml, '__version__', 'Unknown version')
1751 |                 print_success(f"DirectML is available: {version}")
1752 |             except ImportError:
1753 |                 print_info("Using CPU-only PyTorch")
1754 |         
1755 |         # For macOS Intel, verify compatibility with sentence-transformers
1756 |         if system_info["is_macos"] and system_info["is_x86"]:
1757 |             torch_version = torch.__version__.split('.')
1758 |             major, minor = int(torch_version[0]), int(torch_version[1])
1759 |             
1760 |             print_info(f"Verifying torch compatibility on macOS Intel (v{major}.{minor})")
1761 |             if major < 1 or (major == 1 and minor < 6):
1762 |                 print_warning(f"PyTorch version {torch.__version__} may be too old for sentence-transformers")
1763 |             elif major > 2 or (major == 2 and minor > 1):
1764 |                 print_warning(f"PyTorch version {torch.__version__} may be too new for sentence-transformers 2.2.2")
1765 |                 print_info("If you encounter issues, try downgrading to torch 2.0.1")
1766 |             
1767 |     except ImportError:
1768 |         print_warning("PyTorch is not installed via pip. This is okay for basic operation with SQLite-vec backend.")
1769 |         if homebrew_pytorch:
1770 |             print_info("Using Homebrew PyTorch installation instead of pip version")
1771 |         else:
1772 |             print_info("For full functionality including embedding generation, install with: pip install 'mcp-memory-service[ml]'")
1773 |         pytorch_installed = False
1774 |     
1775 |     # Check if sentence-transformers is installed correctly (only if PyTorch is installed)
1776 |     if pytorch_installed or homebrew_pytorch:
1777 |         try:
1778 |             import sentence_transformers
1779 |             print_success(f"sentence-transformers is installed: {sentence_transformers.__version__}")
1780 |             
1781 |             if pytorch_installed:
1782 |                 # Verify compatibility between torch and sentence-transformers
1783 |                 st_version = sentence_transformers.__version__.split('.')
1784 |                 torch_version = torch.__version__.split('.')
1785 |                 
1786 |                 st_major, st_minor = int(st_version[0]), int(st_version[1])
1787 |                 torch_major, torch_minor = int(torch_version[0]), int(torch_version[1])
1788 |                 
1789 |                 # Specific compatibility check for macOS Intel
1790 |                 if system_info["is_macos"] and system_info["is_x86"]:
1791 |                     if st_major >= 3 and (torch_major < 1 or (torch_major == 1 and torch_minor < 11)):
1792 |                         print_warning(f"sentence-transformers {sentence_transformers.__version__} requires torch>=1.11.0")
1793 |                         print_info("This may cause runtime issues - consider downgrading sentence-transformers to 2.2.2")
1794 |             
1795 |             # Verify by trying to load a model (minimal test)
1796 |             try:
1797 |                 print_info("Testing sentence-transformers model loading...")
1798 |                 test_model = sentence_transformers.SentenceTransformer('paraphrase-MiniLM-L3-v2')
1799 |                 print_success("Successfully loaded test model")
1800 |             except Exception as e:
1801 |                 print_warning(f"Model loading test failed: {e}")
1802 |                 print_warning("There may be compatibility issues between PyTorch and sentence-transformers")
1803 |                 
1804 |         except ImportError:
1805 |             print_warning("sentence-transformers is not installed. This is okay for basic operation with SQLite-vec backend.")
1806 |             print_info("For full functionality including embedding generation, install with: pip install 'mcp-memory-service[ml]'")
1807 |     
1808 |     # Check for SQLite-vec + ONNX configuration
1809 |     if storage_backend == 'sqlite_vec' and os.environ.get('MCP_MEMORY_USE_ONNX', '').lower() in ('1', 'true', 'yes'):
1810 |         print_success("SQLite-vec + ONNX configuration is set up correctly")
1811 |         print_info("This configuration can run without PyTorch dependency")
1812 |         
1813 |         try:
1814 |             # Import the key components to verify installation
1815 |             from mcp_memory_service.storage.sqlite_vec import SqliteVecMemoryStorage
1816 |             from mcp_memory_service.models.memory import Memory
1817 |             print_success("SQLite-vec + ONNX components loaded successfully")
1818 |             
1819 |             # Check paths
1820 |             sqlite_path = os.environ.get('MCP_MEMORY_SQLITE_PATH', '')
1821 |             if sqlite_path:
1822 |                 print_info(f"SQLite-vec database path: {sqlite_path}")
1823 |             else:
1824 |                 print_warning("MCP_MEMORY_SQLITE_PATH is not set")
1825 |             
1826 |             backups_path = os.environ.get('MCP_MEMORY_BACKUPS_PATH', '')
1827 |             if backups_path:
1828 |                 print_info(f"Backups path: {backups_path}")
1829 |             else:
1830 |                 print_warning("MCP_MEMORY_BACKUPS_PATH is not set")
1831 |             
1832 |         except ImportError as e:
1833 |             print_error(f"Failed to import SQLite-vec components: {e}")
1834 |             return False
1835 |             
1836 |     # Check if MCP Memory Service package is installed correctly
1837 |     try:
1838 |         import mcp_memory_service
1839 |         print_success(f"MCP Memory Service is installed correctly")
1840 |         return True
1841 |     except ImportError:
1842 |         print_error("MCP Memory Service is not installed correctly")
1843 |         return False
1844 | 
1845 | def is_legacy_hardware(system_info):
1846 |     """Detect legacy hardware that needs special handling."""
1847 |     if system_info["is_macos"] and system_info["is_x86"]:
1848 |         # Check if it's likely an older Intel Mac
1849 |         # This is a heuristic based on common patterns
1850 |         try:
1851 |             # Try to get more detailed system info
1852 |             print_info("Detecting hardware configuration (this may take a moment)...")
1853 |             result = subprocess.run(
1854 |                 ['system_profiler', 'SPHardwareDataType'],
1855 |                 capture_output=True, text=True, timeout=30
1856 |             )
1857 |             if result.returncode == 0:
1858 |                 output = result.stdout.lower()
1859 |                 # Look for indicators of older hardware
1860 |                 if any(year in output for year in ['2013', '2014', '2015', '2016', '2017']):
1861 |                     return True
1862 |         except (subprocess.SubprocessError, subprocess.TimeoutExpired):
1863 |             pass
1864 |     
1865 |     return False
1866 | 
1867 | def detect_memory_gb():
1868 |     """Detect available system memory in GB."""
1869 |     try:
1870 |         import psutil
1871 |         return psutil.virtual_memory().total / (1024**3)
1872 |     except ImportError:
1873 |         # Fallback detection methods
1874 |         try:
1875 |             if platform.system() == "Darwin":  # macOS
1876 |                 result = subprocess.run(
1877 |                     ['sysctl', '-n', 'hw.memsize'],
1878 |                     capture_output=True, text=True
1879 |                 )
1880 |                 if result.returncode == 0:
1881 |                     return int(result.stdout.strip()) / (1024**3)
1882 |             elif platform.system() == "Linux":
1883 |                 with open('/proc/meminfo', 'r') as f:
1884 |                     for line in f:
1885 |                         if line.startswith('MemTotal:'):
1886 |                             return int(line.split()[1]) / (1024**2)
1887 |         except (subprocess.SubprocessError, FileNotFoundError, IOError):
1888 |             pass
1889 |     
1890 |     return 0  # Unknown
1891 | 
1892 | def recommend_backend_intelligent(system_info, gpu_info, memory_gb, args):
1893 |     """Intelligent backend recommendation based on hardware analysis."""
1894 |     # User explicitly chose backend
1895 |     if hasattr(args, 'storage_backend') and args.storage_backend:
1896 |         return args.storage_backend
1897 |     
1898 |     # Legacy hardware mode
1899 |     if args.legacy_hardware or is_legacy_hardware(system_info):
1900 |         print_info("[DETECT] Legacy hardware detected - optimizing for compatibility")
1901 |         return "sqlite_vec"
1902 |     
1903 |     # Server mode
1904 |     if args.server_mode:
1905 |         print_info("[SERVER] Server mode - selecting lightweight backend")
1906 |         return "sqlite_vec"
1907 |     
1908 |     # Low memory systems
1909 |     if memory_gb > 0 and memory_gb < 4:
1910 |         print_info(f"[MEMORY] Limited memory detected ({memory_gb:.1f}GB) - using efficient backend")
1911 |         return "sqlite_vec"
1912 |     
1913 |     # macOS Intel with known ChromaDB issues
1914 |     if system_info["is_macos"] and system_info["is_x86"]:
1915 |         compatibility = detect_storage_backend_compatibility(system_info, gpu_info)
1916 |         if compatibility["chromadb"]["recommendation"] == "problematic":
1917 |             print_info("[WARNING] macOS Intel compatibility issues detected - using SQLite-vec")
1918 |             # Set environment variables for consistent backend selection
1919 |             os.environ['MCP_MEMORY_STORAGE_BACKEND'] = 'sqlite_vec'
1920 |             # For Intel Macs, also enable ONNX runtime for better compatibility
1921 |             if system_info.get("has_homebrew_pytorch") or sys.version_info >= (3, 13):
1922 |                 print_info("[CONFIG] Enabling ONNX runtime for better compatibility")
1923 |                 os.environ['MCP_MEMORY_USE_ONNX'] = '1'
1924 |             return "sqlite_vec"
1925 |     
1926 |     # Hardware with GPU acceleration - SQLite-vec still recommended for simplicity
1927 |     if gpu_info.get("has_cuda") or gpu_info.get("has_mps") or gpu_info.get("has_directml"):
1928 |         gpu_type = "CUDA" if gpu_info.get("has_cuda") else "MPS" if gpu_info.get("has_mps") else "DirectML"
1929 |         print_info(f"[GPU] {gpu_type} acceleration detected - SQLite-vec recommended for simplicity and speed")
1930 |         return "sqlite_vec"
1931 |     
1932 |     # High memory systems without GPU - explain the choice
1933 |     if memory_gb >= 16:
1934 |         print_info("[CHOICE] High-memory system without GPU detected")
1935 |         print_info("  -> SQLite-vec: Faster startup, simpler setup, no network dependencies")
1936 |         print_info("  -> ChromaDB: Legacy option, being deprecated in v6.0.0")
1937 |         print_info("  -> Defaulting to SQLite-vec (recommended for all users)")
1938 |         return "sqlite_vec"
1939 |     
1940 |     # Default recommendation for most users
1941 |     print_info("[DEFAULT] Recommending SQLite-vec for optimal user experience")
1942 |     return "sqlite_vec"
1943 | 
1944 | def show_detailed_help():
1945 |     """Show detailed hardware-specific installation help."""
1946 |     print_header("MCP Memory Service - Hardware-Specific Installation Guide")
1947 |     
1948 |     # Detect current system
1949 |     system_info = detect_system()
1950 |     gpu_info = detect_gpu()
1951 |     memory_gb = detect_memory_gb()
1952 |     
1953 |     # Check SQLite extension support
1954 |     extension_supported, extension_message = check_sqlite_extension_support()
1955 |     
1956 |     print_info("Your System Configuration:")
1957 |     print_info(f"  Platform: {platform.system()} {platform.release()}")
1958 |     print_info(f"  Architecture: {platform.machine()}")
1959 |     print_info(f"  Python: {sys.version_info.major}.{sys.version_info.minor}")
1960 |     if memory_gb > 0:
1961 |         print_info(f"  Memory: {memory_gb:.1f}GB")
1962 |     print_info(f"  SQLite Extensions: {'✅ Supported' if extension_supported else '❌ Not Supported'}")
1963 |     
1964 |     # Warn about potential sqlite-vec issues
1965 |     if not extension_supported and platform.system().lower() == "darwin":
1966 |         print_warning("SQLite extension support not available - this may cause issues with sqlite-vec backend")
1967 |         print_info("Consider using Homebrew Python: brew install python")
1968 |     
1969 |     # Hardware-specific recommendations
1970 |     print_step("Recommendations", "Based on your hardware")
1971 |     
1972 |     if is_legacy_hardware(system_info):
1973 |         print_success("Legacy Hardware Path (2013-2017 Intel Mac)")
1974 |         print_info("  Recommended: python install.py --legacy-hardware")
1975 |         print_info("  This will:")
1976 |         print_info("    • Use SQLite-vec backend (avoids ChromaDB compatibility issues)")
1977 |         print_info("    • Configure ONNX runtime for CPU-only inference")
1978 |         print_info("    • Use Homebrew PyTorch for better compatibility")
1979 |         print_info("    • Optimize resource usage for older hardware")
1980 |     elif system_info["is_macos"] and system_info["is_arm"]:
1981 |         print_success("Apple Silicon Mac - Modern Hardware Path")
1982 |         print_info("  Recommended: python install.py")
1983 |         print_info("  This will:")
1984 |         print_info("    • Use SQLite-vec backend (fast and efficient)")
1985 |         print_info("    • Enable MPS acceleration")
1986 |         print_info("    • Zero network dependencies")
1987 |     elif system_info["is_windows"] and gpu_info.get("has_cuda"):
1988 |         print_success("Windows with CUDA GPU - High Performance Path")
1989 |         print_info("  Recommended: python install.py")
1990 |         print_info("  This will:")
1991 |         print_info("    • Use SQLite-vec backend (fast and efficient)")
1992 |         print_info("    • Enable CUDA acceleration")
1993 |         print_info("    • Zero network dependencies")
1994 |     elif memory_gb > 0 and memory_gb < 4:
1995 |         print_success("Low-Memory System")
1996 |         print_info("  Recommended: python install.py --storage-backend sqlite_vec")
1997 |         print_info("  This will:")
1998 |         print_info("    • Use lightweight SQLite-vec backend")
1999 |         print_info("    • Minimize memory usage")
2000 |         print_info("    • Enable ONNX runtime for efficiency")
2001 |     elif memory_gb >= 16 and not (gpu_info.get("has_cuda") or gpu_info.get("has_mps") or gpu_info.get("has_directml")):
2002 |         print_success("High-Memory System (No GPU) - Choose Your Path")
2003 |         print_info("  Option 1 (Recommended): python install.py")
2004 |         print_info("    • SQLite-vec: Fast startup, simple setup, same features")
2005 |         print_info("  Option 2: python install.py --storage-backend chromadb")
2006 |         print_info("    • ChromaDB: Better for 10K+ memories, production deployments")
2007 |         print_info("  Most users benefit from SQLite-vec's simplicity")
2008 |     elif gpu_info.get("has_cuda") or gpu_info.get("has_mps") or gpu_info.get("has_directml"):
2009 |         gpu_type = "CUDA" if gpu_info.get("has_cuda") else "MPS" if gpu_info.get("has_mps") else "DirectML"
2010 |         print_success(f"GPU-Accelerated System ({gpu_type}) - High Performance Path")
2011 |         print_info("  Recommended: python install.py")
2012 |         print_info("  This will:")
2013 |         print_info(f"    • Use SQLite-vec backend (fast and efficient)")
2014 |         print_info(f"    • Enable {gpu_type} hardware acceleration")
2015 |         print_info("    • Zero network dependencies")
2016 |     else:
2017 |         print_success("Standard Installation")
2018 |         print_info("  Recommended: python install.py")
2019 |         print_info("  This will:")
2020 |         print_info("    • Use SQLite-vec backend (optimal for most users)")
2021 |         print_info("    • Fast startup and simple setup")
2022 |         print_info("    • Full semantic search capabilities")
2023 |     
2024 |     print_step("Available Options", "Command-line flags you can use")
2025 |     print_info("  --legacy-hardware     : Optimize for 2013-2017 Intel Macs")
2026 |     print_info("  --server-mode         : Headless server installation")
2027 |     print_info("  --storage-backend X   : Force backend (chromadb/sqlite_vec)")
2028 |     print_info("  --enable-http-api     : Enable HTTP/SSE web interface")
2029 |     print_info("  --use-homebrew-pytorch: Use existing Homebrew PyTorch")
2030 |     
2031 |     print_step("Documentation", "Hardware-specific guides")
2032 |     print_info("  Legacy Mac Guide: docs/platforms/macos-intel-legacy.md")
2033 |     print_info("  Backend Comparison: docs/guides/STORAGE_BACKENDS.md")
2034 |     print_info("  Master Guide: docs/guides/INSTALLATION_MASTER.md")
2035 | 
2036 | def generate_personalized_docs():
2037 |     """Generate personalized setup documentation."""
2038 |     print_header("Generating Personalized Setup Guide")
2039 |     
2040 |     # Detect system
2041 |     system_info = detect_system()
2042 |     gpu_info = detect_gpu()
2043 |     memory_gb = detect_memory_gb()
2044 |     
2045 |     # Create personalized guide
2046 |     guide_content = f"""# Your Personalized MCP Memory Service Setup Guide
2047 | 
2048 | Generated on: {platform.node()} at {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
2049 | 
2050 | ## Your System Configuration
2051 | 
2052 | - **Platform**: {platform.system()} {platform.release()}
2053 | - **Architecture**: {platform.machine()}
2054 | - **Python Version**: {sys.version_info.major}.{sys.version_info.minor}
2055 | - **Memory**: {memory_gb:.1f}GB (detected)
2056 | - **GPU**: {'Yes (' + ('CUDA' if gpu_info.get('has_cuda') else 'MPS' if gpu_info.get('has_mps') else 'DirectML' if gpu_info.get('has_directml') else 'Unknown') + ')' if gpu_info.get('has_cuda') or gpu_info.get('has_mps') or gpu_info.get('has_directml') else 'No'}
2057 | 
2058 | ## Recommended Installation Command
2059 | 
2060 | ```bash
2061 | """
2062 |     
2063 |     # Generate recommendation
2064 |     class Args:
2065 |         storage_backend = None
2066 |         legacy_hardware = False
2067 |         server_mode = False
2068 |     
2069 |     args = Args()
2070 |     recommended_backend = recommend_backend_intelligent(system_info, gpu_info, memory_gb, args)
2071 |     
2072 |     if is_legacy_hardware(system_info):
2073 |         guide_content += "python install.py --legacy-hardware\n"
2074 |     elif memory_gb < 4:
2075 |         guide_content += "python install.py --storage-backend sqlite_vec\n"
2076 |     else:
2077 |         guide_content += "python install.py\n"
2078 |     
2079 |     guide_content += f"""```
2080 | 
2081 | ## Why This Configuration?
2082 | 
2083 | Based on your {platform.system()} system with {memory_gb:.1f}GB RAM:
2084 | """
2085 |     
2086 |     if is_legacy_hardware(system_info):
2087 |         guide_content += """
2088 | - [OK] **Hardware Compatibility**: SQLite-vec avoids ChromaDB installation issues on older Intel Macs
2089 | - [OK] **Homebrew PyTorch**: Better compatibility with older systems and reduced dependencies
2090 | - [OK] **ONNX Runtime**: CPU-optimized inference for systems without GPU acceleration
2091 | - [OK] **Memory Efficient**: Optimized resource usage for systems with limited RAM
2092 | - [OK] **Full Feature Set**: Complete semantic search, tagging, and time-based recall capabilities
2093 | """
2094 |     elif recommended_backend == "sqlite_vec":
2095 |         if memory_gb >= 16 and not (gpu_info.get("has_cuda") or gpu_info.get("has_mps") or gpu_info.get("has_directml")):
2096 |             guide_content += """
2097 | - [OK] **Smart Choice**: SQLite-vec recommended for high-memory systems without GPU
2098 | - [OK] **No GPU Needed**: ChromaDB's advantages require GPU acceleration you don't have
2099 | - [OK] **Faster Startup**: Database ready in 2-3 seconds vs ChromaDB's 15-30 seconds
2100 | - [OK] **Simpler Setup**: Single-file database, no complex dependencies
2101 | - [OK] **Full Feature Set**: Complete semantic search, tagging, and time-based recall capabilities
2102 | - [INFO] **Alternative**: Use `--storage-backend chromadb` if you plan 10K+ memories
2103 | """
2104 |         else:
2105 |             guide_content += """
2106 | - [OK] **SQLite-vec Backend**: Lightweight with complete vector search capabilities
2107 | - [OK] **Low Memory Usage**: Optimized for systems with limited RAM
2108 | - [OK] **Quick Startup**: Database ready in seconds
2109 | - [OK] **Full Feature Set**: Semantic search, tagging, time-based recall
2110 | """
2111 |     else:
2112 |         guide_content += """
2113 | - [OK] **ChromaDB Backend**: Production-grade with advanced HNSW indexing and rich ecosystem
2114 | - [OK] **Hardware Acceleration**: Takes advantage of your GPU/MPS acceleration
2115 | - [OK] **Scalable Performance**: Optimized for large datasets (10K+ memories) and complex metadata queries
2116 | - [OK] **Full Feature Set**: Complete semantic search, tagging, and time-based recall capabilities
2117 | """
2118 |     
2119 |     guide_content += f"""
2120 | ## Next Steps
2121 | 
2122 | 1. **Run the installation**:
2123 |    ```bash
2124 |    cd mcp-memory-service
2125 |    {guide_content.split('```bash')[1].split('```')[0].strip()}
2126 |    ```
2127 | 
2128 | 2. **Test the installation**:
2129 |    ```bash
2130 |    python scripts/test_memory_simple.py
2131 |    ```
2132 | 
2133 | 3. **Configure Claude Desktop**:
2134 |    The installer will generate the optimal configuration for your system.
2135 | 
2136 | ## Troubleshooting
2137 | 
2138 | If you encounter issues, see the platform-specific guide:
2139 | - **Legacy Mac Issues**: docs/platforms/macos-intel-legacy.md
2140 | - **General Issues**: docs/guides/troubleshooting.md
2141 | - **Backend Selection**: docs/guides/STORAGE_BACKENDS.md
2142 | 
2143 | ## Support
2144 | 
2145 | Generated configuration ID: {hash(str(system_info) + str(gpu_info))}-{int(__import__('time').time())}
2146 | Include this ID when requesting support for faster assistance.
2147 | """
2148 |     
2149 |     # Write the guide
2150 |     guide_path = "YOUR_PERSONALIZED_SETUP_GUIDE.md"
2151 |     with open(guide_path, 'w') as f:
2152 |         f.write(guide_content)
2153 |     
2154 |     print_success(f"Personalized setup guide created: {guide_path}")
2155 |     print_info("This guide contains hardware-specific recommendations for your system")
2156 |     print_info("Keep this file for future reference and troubleshooting")
2157 | 
2158 | def configure_claude_code_integration(system_info):
2159 |     """Configure Claude Code MCP integration with optimized settings."""
2160 |     print_step("6", "Configuring Claude Code Integration")
2161 |     
2162 |     # Check if Claude Code is installed
2163 |     try:
2164 |         result = subprocess.run(['claude', '--version'], capture_output=True, text=True, timeout=5)
2165 |         if result.returncode != 0:
2166 |             print_warning("Claude Code CLI not found. Please install it first:")
2167 |             print_info("curl -fsSL https://claude.ai/install.sh | sh")
2168 |             return False
2169 |     except (subprocess.SubprocessError, FileNotFoundError, subprocess.TimeoutExpired):
2170 |         print_warning("Claude Code CLI not found. Please install it first:")
2171 |         print_info("curl -fsSL https://claude.ai/install.sh | sh")
2172 |         return False
2173 |     
2174 |     print_success("Claude Code CLI detected")
2175 |     
2176 |     # Load template and create personalized .mcp.json
2177 |     template_path = Path('.mcp.json.template')
2178 |     if not template_path.exists():
2179 |         print_error("Template file .mcp.json.template not found")
2180 |         return False
2181 |     
2182 |     try:
2183 |         import json
2184 |         with open(template_path, 'r') as f:
2185 |             template_content = f.read()
2186 |         
2187 |         # Replace placeholders with actual values
2188 |         user_home = str(Path.home())
2189 |         personalized_content = template_content.replace('{{USER_HOME}}', user_home)
2190 |         
2191 |         # Create .mcp.json
2192 |         mcp_config_path = Path('.mcp.json')
2193 |         with open(mcp_config_path, 'w') as f:
2194 |             f.write(personalized_content)
2195 |         
2196 |         print_success(f"Created personalized .mcp.json configuration")
2197 |         print_info(f"Configuration file: {mcp_config_path.absolute()}")
2198 |         
2199 |         # Add to .gitignore if it exists
2200 |         gitignore_path = Path('.gitignore')
2201 |         if gitignore_path.exists():
2202 |             with open(gitignore_path, 'r') as f:
2203 |                 gitignore_content = f.read()
2204 |             
2205 |             if '.mcp.json' not in gitignore_content:
2206 |                 with open(gitignore_path, 'a') as f:
2207 |                     f.write('\n# MCP configuration (contains personal paths)\n.mcp.json\n')
2208 |                 print_success("Added .mcp.json to .gitignore")
2209 |         
2210 |         # Verify Claude Code can see the configuration
2211 |         try:
2212 |             result = subprocess.run(['claude', 'mcp', 'list'], 
2213 |                                   capture_output=True, text=True, timeout=10, cwd='.')
2214 |             if 'memory-service' in result.stdout:
2215 |                 print_success("Claude Code MCP integration configured successfully!")
2216 |                 print_info("You can now use memory functions in Claude Code")
2217 |             else:
2218 |                 print_warning("Configuration created but memory-service not detected")
2219 |                 print_info("You may need to restart Claude Code or check the configuration")
2220 |         except (subprocess.SubprocessError, subprocess.TimeoutExpired):
2221 |             print_warning("Could not verify Claude Code configuration")
2222 |             print_info("Configuration file created - restart Claude Code to use memory functions")
2223 |         
2224 |         return True
2225 |         
2226 |     except Exception as e:
2227 |         print_error(f"Failed to configure Claude Code integration: {e}")
2228 |         return False
2229 | 
2230 | def detect_mcp_clients():
2231 |     """Detect installed MCP-compatible applications."""
2232 |     clients = {}
2233 |     
2234 |     # Check for Claude Desktop
2235 |     claude_config_paths = [
2236 |         Path.home() / "AppData" / "Roaming" / "Claude" / "claude_desktop_config.json",  # Windows
2237 |         Path.home() / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json",  # macOS
2238 |         Path.home() / ".config" / "Claude" / "claude_desktop_config.json"  # Linux
2239 |     ]
2240 |     for path in claude_config_paths:
2241 |         if path.exists():
2242 |             clients['claude_desktop'] = path
2243 |             break
2244 |     
2245 |     # Check for Claude Code CLI
2246 |     try:
2247 |         result = subprocess.run(['claude', '--version'], capture_output=True, text=True, timeout=5)
2248 |         if result.returncode == 0:
2249 |             clients['claude_code'] = True
2250 |     except (subprocess.SubprocessError, FileNotFoundError, subprocess.TimeoutExpired):
2251 |         pass
2252 |     
2253 |     # Check for VS Code with MCP extension
2254 |     vscode_settings_paths = [
2255 |         Path.home() / "AppData" / "Roaming" / "Code" / "User" / "settings.json",  # Windows
2256 |         Path.home() / "Library" / "Application Support" / "Code" / "User" / "settings.json",  # macOS
2257 |         Path.home() / ".config" / "Code" / "User" / "settings.json"  # Linux
2258 |     ]
2259 |     for path in vscode_settings_paths:
2260 |         if path.exists():
2261 |             try:
2262 |                 import json
2263 |                 with open(path, 'r') as f:
2264 |                     settings = json.load(f)
2265 |                 # Check for MCP-related extensions or configurations
2266 |                 if any('mcp' in str(key).lower() or 'model-context-protocol' in str(key).lower() 
2267 |                        for key in settings.keys()):
2268 |                     clients['vscode_mcp'] = path
2269 |                     break
2270 |             except (json.JSONDecodeError, IOError):
2271 |                 pass
2272 |     
2273 |     # Check for Continue IDE
2274 |     continue_paths = [
2275 |         Path.home() / ".continue" / "config.json",
2276 |         Path.home() / ".config" / "continue" / "config.json",
2277 |         Path.home() / "AppData" / "Roaming" / "continue" / "config.json"  # Windows
2278 |     ]
2279 |     for path in continue_paths:
2280 |         if path.exists():
2281 |             clients['continue'] = path
2282 |             break
2283 |     
2284 |     # Check for generic MCP configurations
2285 |     generic_mcp_paths = [
2286 |         Path.home() / ".mcp.json",
2287 |         Path.home() / ".config" / "mcp" / "config.json",
2288 |         Path.cwd() / ".mcp.json"
2289 |     ]
2290 |     for path in generic_mcp_paths:
2291 |         if path.exists():
2292 |             clients['generic_mcp'] = path
2293 |             break
2294 |     
2295 |     # Check for Cursor IDE (similar to VS Code)
2296 |     cursor_settings_paths = [
2297 |         Path.home() / "AppData" / "Roaming" / "Cursor" / "User" / "settings.json",  # Windows
2298 |         Path.home() / "Library" / "Application Support" / "Cursor" / "User" / "settings.json",  # macOS
2299 |         Path.home() / ".config" / "Cursor" / "User" / "settings.json"  # Linux
2300 |     ]
2301 |     for path in cursor_settings_paths:
2302 |         if path.exists():
2303 |             try:
2304 |                 import json
2305 |                 with open(path, 'r') as f:
2306 |                     settings = json.load(f)
2307 |                 # Check for MCP-related configurations
2308 |                 if any('mcp' in str(key).lower() or 'model-context-protocol' in str(key).lower() 
2309 |                        for key in settings.keys()):
2310 |                     clients['cursor'] = path
2311 |                     break
2312 |             except (json.JSONDecodeError, IOError):
2313 |                 pass
2314 |     
2315 |     return clients
2316 | 
2317 | def print_detected_clients(clients):
2318 |     """Print information about detected MCP clients."""
2319 |     if clients:
2320 |         print_info("Detected MCP Clients:")
2321 |         for client_type, config_path in clients.items():
2322 |             client_names = {
2323 |                 'claude_desktop': 'Claude Desktop',
2324 |                 'claude_code': 'Claude Code CLI',
2325 |                 'vscode_mcp': 'VS Code with MCP',
2326 |                 'continue': 'Continue IDE',
2327 |                 'cursor': 'Cursor IDE',
2328 |                 'generic_mcp': 'Generic MCP Client'
2329 |             }
2330 |             client_name = client_names.get(client_type, client_type.title())
2331 |             config_info = config_path if isinstance(config_path, (str, Path)) else "CLI detected"
2332 |             print_info(f"  [*] {client_name}: {config_info}")
2333 |     else:
2334 |         print_info("No MCP clients detected - configuration will work with any future MCP client")
2335 | 
2336 | def should_offer_multi_client_setup(args, final_backend):
2337 |     """Determine if multi-client setup should be offered."""
2338 |     # Only offer if using SQLite-vec backend (requirement for multi-client)
2339 |     if final_backend != "sqlite_vec":
2340 |         return False
2341 |     
2342 |     # Don't offer in pure server mode
2343 |     if args.server_mode:
2344 |         return False
2345 |     
2346 |     # Skip if user explicitly requested to skip
2347 |     if args.skip_multi_client_prompt:
2348 |         return False
2349 |     
2350 |     # Always beneficial for development environments - any future MCP client can benefit
2351 |     return True
2352 | 
2353 | def configure_detected_clients(clients, system_info, storage_backend="sqlite_vec"):
2354 |     """Configure each detected client for multi-client access."""
2355 |     success_count = 0
2356 |     
2357 |     for client_type, config_path in clients.items():
2358 |         try:
2359 |             if client_type == 'claude_desktop':
2360 |                 if configure_claude_desktop_multi_client(config_path, system_info, storage_backend):
2361 |                     success_count += 1
2362 |             elif client_type == 'vscode_mcp' or client_type == 'cursor':
2363 |                 if configure_vscode_like_multi_client(config_path, client_type, storage_backend):
2364 |                     success_count += 1
2365 |             elif client_type == 'continue':
2366 |                 if configure_continue_multi_client(config_path, storage_backend):
2367 |                     success_count += 1
2368 |             elif client_type == 'generic_mcp':
2369 |                 if configure_generic_mcp_multi_client(config_path, storage_backend):
2370 |                     success_count += 1
2371 |             elif client_type == 'claude_code':
2372 |                 # Claude Code uses project-level .mcp.json, handle separately
2373 |                 print_info(f"  -> Claude Code: Configure via project .mcp.json (see instructions below)")
2374 |                 success_count += 1
2375 |         except Exception as e:
2376 |             print_warning(f"  -> Failed to configure {client_type}: {e}")
2377 |     
2378 |     return success_count
2379 | 
2380 | def configure_claude_desktop_multi_client(config_path, system_info, storage_backend="sqlite_vec"):
2381 |     """Configure Claude Desktop for multi-client access."""
2382 |     try:
2383 |         import json
2384 |         
2385 |         # Read existing configuration
2386 |         with open(config_path, 'r') as f:
2387 |             config = json.load(f)
2388 |         
2389 |         # Ensure mcpServers section exists
2390 |         if 'mcpServers' not in config:
2391 |             config['mcpServers'] = {}
2392 |         
2393 |         # Update memory server configuration with multi-client settings
2394 |         repo_path = str(Path.cwd()).replace('\\', '\\\\')  # Escape backslashes for JSON
2395 |         config['mcpServers']['memory'] = build_mcp_server_config(storage_backend, repo_path)
2396 |         
2397 |         # Write updated configuration
2398 |         with open(config_path, 'w') as f:
2399 |             json.dump(config, f, indent=2)
2400 |         
2401 |         print_info(f"  [OK] Claude Desktop: Updated configuration for multi-client access")
2402 |         return True
2403 |         
2404 |     except Exception as e:
2405 |         print_warning(f"  -> Claude Desktop configuration failed: {e}")
2406 |         return False
2407 | 
2408 | def configure_vscode_like_multi_client(config_path, client_type, storage_backend="sqlite_vec"):
2409 |     """Configure VS Code or Cursor for multi-client access."""
2410 |     try:
2411 |         import json
2412 |         
2413 |         # For VS Code/Cursor, we provide instructions rather than modifying settings directly
2414 |         # since MCP configuration varies by extension
2415 |         
2416 |         client_name = "VS Code" if client_type == 'vscode_mcp' else "Cursor"
2417 |         print_info(f"  -> {client_name}: MCP extension detected")
2418 |         print_info(f"    Add memory server to your MCP extension with these settings:")
2419 |         print_info(f"    - Backend: {storage_backend}")
2420 |         if storage_backend == "sqlite_vec":
2421 |             print_info(f"    - Database: shared SQLite-vec database")
2422 |         else:
2423 |             print_info(f"    - Database: shared ChromaDB database")
2424 |         print_info(f"    - See generic configuration below for details")
2425 |         return True
2426 |         
2427 |     except Exception as e:
2428 |         print_warning(f"  -> {client_type} configuration failed: {e}")
2429 |         return False
2430 | 
2431 | def configure_continue_multi_client(config_path, storage_backend="sqlite_vec"):
2432 |     """Configure Continue IDE for multi-client access."""
2433 |     try:
2434 |         import json
2435 |         
2436 |         # Read existing Continue configuration
2437 |         with open(config_path, 'r') as f:
2438 |             config = json.load(f)
2439 |         
2440 |         # Add or update MCP server configuration for Continue
2441 |         if 'mcpServers' not in config:
2442 |             config['mcpServers'] = {}
2443 |         
2444 |         config['mcpServers']['memory'] = build_mcp_server_config(storage_backend)
2445 |         
2446 |         # Write updated configuration
2447 |         with open(config_path, 'w') as f:
2448 |             json.dump(config, f, indent=2)
2449 |         
2450 |         print_info(f"  [OK] Continue IDE: Updated configuration for multi-client access")
2451 |         return True
2452 |         
2453 |     except Exception as e:
2454 |         print_warning(f"  -> Continue IDE configuration failed: {e}")
2455 |         return False
2456 | 
2457 | def configure_generic_mcp_multi_client(config_path, storage_backend="sqlite_vec"):
2458 |     """Configure generic MCP client for multi-client access."""
2459 |     try:
2460 |         import json
2461 |         
2462 |         # Read existing configuration
2463 |         with open(config_path, 'r') as f:
2464 |             config = json.load(f)
2465 |         
2466 |         # Add memory server if not present
2467 |         if 'mcpServers' not in config:
2468 |             config['mcpServers'] = {}
2469 |         
2470 |         config['mcpServers']['memory'] = build_mcp_server_config(storage_backend)
2471 |         
2472 |         # Write updated configuration
2473 |         with open(config_path, 'w') as f:
2474 |             json.dump(config, f, indent=2)
2475 |         
2476 |         print_info(f"  [OK] Generic MCP Client: Updated configuration")
2477 |         return True
2478 |         
2479 |     except Exception as e:
2480 |         print_warning(f"  -> Generic MCP client configuration failed: {e}")
2481 |         return False
2482 | 
2483 | async def test_wal_mode_coordination():
2484 |     """Test WAL mode storage coordination for multi-client access."""
2485 |     try:
2486 |         # Add src to path for import
2487 |         sys.path.insert(0, str(Path(__file__).parent / "src"))
2488 |         
2489 |         from mcp_memory_service.storage.sqlite_vec import SqliteVecMemoryStorage
2490 |         from mcp_memory_service.models.memory import Memory
2491 |         from mcp_memory_service.utils.hashing import generate_content_hash
2492 |         
2493 |         import tempfile
2494 |         import asyncio
2495 |         
2496 |         # Create a temporary database for testing
2497 |         with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp:
2498 |             test_db_path = tmp.name
2499 |         
2500 |         try:
2501 |             # Test direct SQLite-vec storage with WAL mode
2502 |             print_info("  -> Testing WAL mode coordination...")
2503 |             storage = SqliteVecMemoryStorage(test_db_path)
2504 |             await storage.initialize()
2505 |             
2506 |             # Test storing a memory
2507 |             content = "Multi-client setup test - WAL mode verification"
2508 |             test_memory = Memory(
2509 |                 content=content,
2510 |                 content_hash=generate_content_hash(content),
2511 |                 tags=["setup", "wal-test", "multi-client"],
2512 |                 memory_type="test"
2513 |             )
2514 |             
2515 |             # Store memory
2516 |             success, message = await storage.store(test_memory)
2517 |             if not success:
2518 |                 print_warning(f"  -> Memory storage failed: {message}")
2519 |                 return False
2520 |             
2521 |             # Test concurrent access simulation
2522 |             storage2 = SqliteVecMemoryStorage(test_db_path)
2523 |             await storage2.initialize()
2524 |             
2525 |             # Both should be able to read
2526 |             results1 = await storage.search_by_tag(["setup"])
2527 |             results2 = await storage2.search_by_tag(["setup"])
2528 |             
2529 |             if len(results1) != len(results2) or len(results1) == 0:
2530 |                 print_warning("  -> Concurrent read access test failed")
2531 |                 return False
2532 |             
2533 |             # Test concurrent write
2534 |             content2 = "Second client test memory"
2535 |             memory2 = Memory(
2536 |                 content=content2,
2537 |                 content_hash=generate_content_hash(content2),
2538 |                 tags=["setup", "client2"],
2539 |                 memory_type="test"
2540 |             )
2541 |             
2542 |             success2, _ = await storage2.store(memory2)
2543 |             if not success2:
2544 |                 print_warning("  -> Concurrent write access test failed")
2545 |                 return False
2546 |             
2547 |             # Verify both clients can see both memories
2548 |             all_results = await storage.search_by_tag(["setup"])
2549 |             if len(all_results) < 2:
2550 |                 print_warning("  -> Multi-client data sharing test failed")
2551 |                 return False
2552 |             
2553 |             storage.close()
2554 |             storage2.close()
2555 |             
2556 |             print_info("  [OK] WAL mode coordination test passed")
2557 |             return True
2558 |             
2559 |         finally:
2560 |             # Cleanup test files
2561 |             try:
2562 |                 os.unlink(test_db_path)
2563 |                 for ext in ["-wal", "-shm"]:
2564 |                     try:
2565 |                         os.unlink(test_db_path + ext)
2566 |                     except:
2567 |                         pass
2568 |             except:
2569 |                 pass
2570 |                 
2571 |     except Exception as e:
2572 |         print_warning(f"  -> WAL mode test failed: {e}")
2573 |         return False
2574 | 
2575 | def setup_shared_environment():
2576 |     """Set up shared environment variables for multi-client access."""
2577 |     try:
2578 |         print_info("  -> Configuring shared environment variables...")
2579 |         
2580 |         # Set environment variables in current process (for testing)
2581 |         os.environ['MCP_MEMORY_STORAGE_BACKEND'] = 'sqlite_vec'
2582 |         os.environ['MCP_MEMORY_SQLITE_PRAGMAS'] = 'busy_timeout=15000,cache_size=20000'
2583 |         os.environ['LOG_LEVEL'] = 'INFO'
2584 |         
2585 |         print_info("  [OK] Environment variables configured")
2586 |         
2587 |         # Provide instructions for permanent setup
2588 |         system_info = detect_system()
2589 |         if system_info["is_windows"]:
2590 |             print_info("  -> For permanent setup, run these PowerShell commands as Administrator:")
2591 |             print_info("    [System.Environment]::SetEnvironmentVariable('MCP_MEMORY_STORAGE_BACKEND', 'sqlite_vec', [System.EnvironmentVariableTarget]::User)")
2592 |             print_info("    [System.Environment]::SetEnvironmentVariable('MCP_MEMORY_SQLITE_PRAGMAS', 'busy_timeout=15000,cache_size=20000', [System.EnvironmentVariableTarget]::User)")
2593 |             print_info("    [System.Environment]::SetEnvironmentVariable('LOG_LEVEL', 'INFO', [System.EnvironmentVariableTarget]::User)")
2594 |         else:
2595 |             print_info("  -> For permanent setup, add to your shell profile:")
2596 |             print_info("    export MCP_MEMORY_STORAGE_BACKEND=sqlite_vec")
2597 |             print_info("    export MCP_MEMORY_SQLITE_PRAGMAS='busy_timeout=15000,cache_size=20000'")
2598 |             print_info("    export LOG_LEVEL=INFO")
2599 |         
2600 |         return True
2601 |         
2602 |     except Exception as e:
2603 |         print_warning(f"  -> Environment setup failed: {e}")
2604 |         return False
2605 | 
2606 | def provide_generic_configuration(storage_backend="sqlite_vec"):
2607 |     """Provide configuration instructions for any MCP client."""
2608 |     print_info("")
2609 |     print_info("Universal MCP Client Configuration:")
2610 |     print_info("=" * 50)
2611 |     print_info("For any MCP-compatible client, use these settings:")
2612 |     print_info("")
2613 |     print_info("MCP Server Configuration:")
2614 |     
2615 |     repo_path = str(Path.cwd())
2616 |     
2617 |     # Windows-style path
2618 |     uv_cmd = UV_EXECUTABLE_PATH or "uv"
2619 |     if platform.system() == 'Windows':
2620 |         print_info(f"  Command: {uv_cmd} --directory \"{repo_path}\" run memory")
2621 |         print_info(f"  Alternative: python -m mcp_memory_service.server")
2622 |     else:
2623 |         print_info(f"  Command: {uv_cmd} --directory {repo_path} run memory")
2624 |         print_info(f"  Alternative: python -m mcp_memory_service.server")
2625 |     
2626 |     print_info("")
2627 |     print_info("Environment Variables:")
2628 |     print_info(f"  MCP_MEMORY_STORAGE_BACKEND={storage_backend}")
2629 |     if storage_backend == "sqlite_vec":
2630 |         print_info("  MCP_MEMORY_SQLITE_PRAGMAS=busy_timeout=15000,cache_size=20000")
2631 |     print_info("  LOG_LEVEL=INFO")
2632 |     
2633 |     print_info("")
2634 |     print_info("Shared Database Location:")
2635 |     if storage_backend == "sqlite_vec":
2636 |         if platform.system() == 'Windows':
2637 |             print_info("  %LOCALAPPDATA%\\mcp-memory\\sqlite_vec.db")
2638 |         elif platform.system() == 'Darwin':
2639 |             print_info("  ~/Library/Application Support/mcp-memory/sqlite_vec.db")
2640 |         else:
2641 |             print_info("  ~/.local/share/mcp-memory/sqlite_vec.db")
2642 |     else:  # chromadb
2643 |         if platform.system() == 'Windows':
2644 |             print_info("  %LOCALAPPDATA%\\mcp-memory\\chroma_db")
2645 |         elif platform.system() == 'Darwin':
2646 |             print_info("  ~/Library/Application Support/mcp-memory/chroma_db")
2647 |         else:
2648 |             print_info("  ~/.local/share/mcp-memory/chroma_db")
2649 |     
2650 |     print_info("")
2651 |     print_info("Claude Code Project Configuration (.mcp.json):")
2652 |     print_info("  {")
2653 |     print_info("    \"mcpServers\": {")
2654 |     print_info("      \"memory\": {")
2655 |     print_info(f"        \"command\": \"{UV_EXECUTABLE_PATH or 'uv'}\",")
2656 |     print_info(f"        \"args\": [\"--directory\", \"{repo_path}\", \"run\", \"memory\"],")
2657 |     print_info("        \"env\": {")
2658 |     print_info(f"          \"MCP_MEMORY_STORAGE_BACKEND\": \"{storage_backend}\",")
2659 |     if storage_backend == "sqlite_vec":
2660 |         print_info("          \"MCP_MEMORY_SQLITE_PRAGMAS\": \"busy_timeout=15000,cache_size=20000\",")
2661 |     print_info("          \"LOG_LEVEL\": \"INFO\"")
2662 |     print_info("        }")
2663 |     print_info("      }")
2664 |     print_info("    }")
2665 |     print_info("  }")
2666 | 
2667 | def setup_universal_multi_client_access(system_info, args, storage_backend="sqlite_vec"):
2668 |     """Configure multi-client access for any MCP-compatible clients."""
2669 |     print_step("7", "Configuring Universal Multi-Client Access")
2670 |     
2671 |     print_info("Setting up multi-client coordination for all MCP applications...")
2672 |     print_info("Benefits:")
2673 |     print_info("  • Share memories between Claude Desktop, VS Code, Continue, and other MCP clients")
2674 |     print_info("  • Seamless context sharing across development environments")
2675 |     print_info("  • Single source of truth for all your project memories")
2676 |     print_info("")
2677 |     
2678 |     # Test WAL mode coordination only for sqlite_vec
2679 |     if storage_backend == "sqlite_vec":
2680 |         try:
2681 |             import asyncio
2682 |             wal_success = asyncio.run(test_wal_mode_coordination())
2683 |             if not wal_success:
2684 |                 print_error("WAL mode coordination test failed")
2685 |                 return False
2686 |         except Exception as e:
2687 |             print_error(f"Failed to test WAL mode coordination: {e}")
2688 |             return False
2689 |     
2690 |     # Detect available MCP clients
2691 |     detected_clients = detect_mcp_clients()
2692 |     print_detected_clients(detected_clients)
2693 |     print_info("")
2694 |     
2695 |     # Configure each detected client
2696 |     print_info("Configuring detected clients...")
2697 |     success_count = configure_detected_clients(detected_clients, system_info, storage_backend)
2698 |     
2699 |     # Set up shared environment variables
2700 |     setup_shared_environment()
2701 |     
2702 |     # Provide generic configuration for manual setup
2703 |     provide_generic_configuration(storage_backend)
2704 |     
2705 |     print_info("")
2706 |     print_success(f"Multi-client setup complete! {success_count} clients configured automatically.")
2707 |     print_info("")
2708 |     print_info("Next Steps:")
2709 |     print_info("  1. Restart your applications (Claude Desktop, VS Code, etc.)")
2710 |     print_info("  2. All clients will share the same memory database")
2711 |     print_info("  3. Test: Store memory in one app, access from another")
2712 |     print_info("  4. For Claude Code: Create .mcp.json in your project directory")
2713 |     
2714 |     return True
2715 | 
2716 | def _parse_arguments():
2717 |     """Parse command-line arguments."""
2718 |     parser = argparse.ArgumentParser(description="Install MCP Memory Service")
2719 |     parser.add_argument('--dev', action='store_true', help='Install in development mode')
2720 |     parser.add_argument('--chroma-path', type=str, help='Path to ChromaDB storage')
2721 |     parser.add_argument('--backups-path', type=str, help='Path to backups storage')
2722 |     parser.add_argument('--force-compatible-deps', action='store_true', 
2723 |                         help='Force compatible versions of PyTorch (2.0.1) and sentence-transformers (2.2.2)')
2724 |     parser.add_argument('--fallback-deps', action='store_true',
2725 |                         help='Use fallback versions of PyTorch (1.13.1) and sentence-transformers (2.2.2)')
2726 |     parser.add_argument('--storage-backend', choices=['chromadb', 'sqlite_vec', 'auto_detect'],
2727 |                         help='Choose storage backend: chromadb (default), sqlite_vec (lightweight), or auto_detect (try chromadb, fallback to sqlite_vec)')
2728 |     parser.add_argument('--skip-pytorch', action='store_true',
2729 |                         help='Skip PyTorch installation and use ONNX runtime with SQLite-vec backend instead')
2730 |     parser.add_argument('--use-homebrew-pytorch', action='store_true',
2731 |                         help='Use existing Homebrew PyTorch installation instead of pip version')
2732 |     parser.add_argument('--force-pytorch', action='store_true',
2733 |                         help='Force PyTorch installation even when using SQLite-vec (overrides auto-skip)')
2734 |     
2735 |     # New intelligent installer options
2736 |     parser.add_argument('--legacy-hardware', action='store_true',
2737 |                         help='Optimize installation for legacy hardware (2013-2017 Intel Macs)')
2738 |     parser.add_argument('--server-mode', action='store_true',
2739 |                         help='Install for server/headless deployment (minimal UI dependencies)')
2740 |     parser.add_argument('--enable-http-api', action='store_true',
2741 |                         help='Enable HTTP/SSE API functionality')
2742 |     parser.add_argument('--migrate-from-chromadb', action='store_true',
2743 |                         help='Migrate existing ChromaDB installation to selected backend')
2744 |     parser.add_argument('--configure-claude-code', action='store_true',
2745 |                         help='Automatically configure Claude Code MCP integration with optimized settings')
2746 |     parser.add_argument('--help-detailed', action='store_true',
2747 |                         help='Show detailed hardware-specific installation recommendations')
2748 |     parser.add_argument('--generate-docs', action='store_true',
2749 |                         help='Generate personalized setup documentation for your hardware')
2750 |     parser.add_argument('--setup-multi-client', action='store_true',
2751 |                         help='Configure multi-client access for any MCP-compatible applications (Claude, VS Code, Continue, etc.)')
2752 |     parser.add_argument('--skip-multi-client-prompt', action='store_true',
2753 |                         help='Skip the interactive prompt for multi-client setup')
2754 |     parser.add_argument('--install-claude-commands', action='store_true',
2755 |                         help='Install Claude Code commands for memory operations')
2756 |     parser.add_argument('--skip-claude-commands-prompt', action='store_true',
2757 |                         help='Skip the interactive prompt for Claude Code commands')
2758 |     parser.add_argument('--non-interactive', action='store_true',
2759 |                         help='Run in non-interactive mode using default values for all prompts')
2760 |     
2761 |     return parser.parse_args()
2762 | 
2763 | def _handle_special_modes(args):
2764 |     """Handle special help and documentation modes that exit early."""
2765 |     if args.help_detailed:
2766 |         show_detailed_help()
2767 |         sys.exit(0)
2768 |     
2769 |     if args.generate_docs:
2770 |         generate_personalized_docs()
2771 |         sys.exit(0)
2772 |     
2773 | def _detect_system_and_environment(args):
2774 |     """Detect system configuration and return system info dict."""
2775 |     print_header("MCP Memory Service Installation")
2776 |     
2777 |     print_step("1", "Detecting system")
2778 |     system_info = detect_system()
2779 |     gpu_info = detect_gpu()
2780 |     memory_gb = detect_memory_gb()
2781 |     
2782 |     if memory_gb > 0:
2783 |         print_info(f"System memory: {memory_gb:.1f}GB")
2784 |     
2785 |     return system_info, gpu_info, memory_gb
2786 | 
2787 | def _recommend_backend(args, system_info, gpu_info, memory_gb):
2788 |     """Recommend and set storage backend based on system configuration."""
2789 |     if not args.storage_backend:
2790 |         recommended_backend = recommend_backend_intelligent(system_info, gpu_info, memory_gb, args)
2791 |         args.storage_backend = recommended_backend
2792 |         print_info(f"Recommended backend: {recommended_backend}")
2793 | 
2794 | def _configure_legacy_hardware(args, system_info):
2795 |     """Configure installation for legacy hardware."""
2796 |     if args.legacy_hardware or is_legacy_hardware(system_info):
2797 |         print_step("1a", "Legacy Hardware Optimization")
2798 |         args.storage_backend = "sqlite_vec"
2799 |         args.use_homebrew_pytorch = True
2800 |         print_success("Configuring for legacy hardware compatibility")
2801 |         print_info("• SQLite-vec backend selected")
2802 |         print_info("• Homebrew PyTorch integration enabled")
2803 |         print_info("• ONNX runtime will be configured")
2804 | 
2805 | def _configure_server_mode(args):
2806 |     """Configure installation for server mode."""
2807 |     if args.server_mode:
2808 |         print_step("1b", "Server Mode Configuration")
2809 |         args.storage_backend = "sqlite_vec"
2810 |         print_success("Configuring for server deployment")
2811 |         print_info("• Lightweight SQLite-vec backend")
2812 |         print_info("• Minimal UI dependencies")
2813 | 
2814 | def _configure_http_api(args):
2815 |     """Configure HTTP/SSE API settings."""
2816 |     if args.enable_http_api:
2817 |         print_step("1c", "HTTP/SSE API Configuration")
2818 |         if args.storage_backend == "chromadb":
2819 |             print_warning("HTTP/SSE API works best with SQLite-vec backend")
2820 |             if args.non_interactive:
2821 |                 print_info("Non-interactive mode: switching to SQLite-vec for HTTP API compatibility")
2822 |                 args.storage_backend = "sqlite_vec"
2823 |             else:
2824 |                 response = prompt_user_input("Switch to SQLite-vec for optimal HTTP API experience? (y/N, press Enter for N): ", "")
2825 |                 if response.lower().startswith('y'):
2826 |                     args.storage_backend = "sqlite_vec"
2827 | 
2828 | def _setup_chromadb_migration(args):
2829 |     """Set up ChromaDB migration if requested."""
2830 |     if not args.migrate_from_chromadb:
2831 |         return
2832 |     
2833 |     print_step("1d", "Migration Setup")
2834 |     print_info("Preparing to migrate from existing ChromaDB installation")
2835 |     
2836 |     chromadb_paths = [
2837 |         os.path.expanduser("~/.mcp_memory_chroma"),
2838 |         os.path.expanduser("~/Library/Application Support/mcp-memory/chroma_db"),
2839 |         os.path.expanduser("~/.local/share/mcp-memory/chroma_db")
2840 |     ]
2841 |     
2842 |     chromadb_found = None
2843 |     for path in chromadb_paths:
2844 |         if os.path.exists(path):
2845 |             chromadb_found = path
2846 |             break
2847 |     
2848 |     if chromadb_found:
2849 |         print_success(f"Found ChromaDB data at: {chromadb_found}")
2850 |         args.storage_backend = "sqlite_vec"
2851 |         args.chromadb_found = chromadb_found
2852 |         print_info("Migration will run after installation completes")
2853 |     else:
2854 |         print_warning("No ChromaDB data found at standard locations")
2855 |         if args.non_interactive:
2856 |             print_info("Non-interactive mode: skipping ChromaDB migration")
2857 |             args.migrate_from_chromadb = False
2858 |         else:
2859 |             manual_path = prompt_user_input("Enter ChromaDB path manually (or press Enter to skip): ", "")
2860 |             if manual_path and os.path.exists(manual_path):
2861 |                 args.storage_backend = "sqlite_vec"
2862 |                 args.chromadb_found = manual_path
2863 |             else:
2864 |                 print_info("Skipping migration - no valid ChromaDB path provided")
2865 |                 args.migrate_from_chromadb = False
2866 | 
2867 | def _install_compatible_dependencies(args, system_info):
2868 |     """Install compatible PyTorch/transformers versions for macOS Intel."""
2869 |     if not args.force_compatible_deps:
2870 |         return
2871 |     
2872 |     if not (system_info["is_macos"] and system_info["is_x86"]):
2873 |         print_warning("--force-compatible-deps is only applicable for macOS with Intel CPUs")
2874 |         return
2875 |     
2876 |     print_info("Installing compatible dependencies as requested...")
2877 |     python_version = sys.version_info
2878 |     
2879 |     if python_version >= (3, 13):
2880 |         torch_version, torch_vision_version = "2.3.0", "0.18.0"
2881 |         torch_audio_version, st_version = "2.3.0", "3.0.0"
2882 |     else:
2883 |         torch_version, torch_vision_version = "2.0.1", "2.0.1"
2884 |         torch_audio_version, st_version = "2.0.1", "2.2.2"
2885 |     
2886 |     try:
2887 |         subprocess.check_call([
2888 |             sys.executable, '-m', 'pip', 'install',
2889 |             f"torch=={torch_version}", f"torchvision=={torch_vision_version}", 
2890 |             f"torchaudio=={torch_audio_version}", f"sentence-transformers=={st_version}"
2891 |         ])
2892 |         print_success("Compatible dependencies installed successfully")
2893 |     except subprocess.SubprocessError as e:
2894 |         print_error(f"Failed to install compatible dependencies: {e}")
2895 | 
2896 | def _install_fallback_dependencies(args):
2897 |     """Install fallback PyTorch/transformers versions for troubleshooting."""
2898 |     if not args.fallback_deps:
2899 |         return
2900 |     
2901 |     print_info("Installing fallback dependencies as requested...")
2902 |     python_version = sys.version_info
2903 |     
2904 |     if python_version >= (3, 13):
2905 |         torch_version, torch_vision_version = "2.3.0", "0.18.0"
2906 |         torch_audio_version, st_version = "2.3.0", "3.0.0"
2907 |     else:
2908 |         torch_version, torch_vision_version = "1.13.1", "0.14.1"
2909 |         torch_audio_version, st_version = "0.13.1", "2.2.2"
2910 |     
2911 |     try:
2912 |         subprocess.check_call([
2913 |             sys.executable, '-m', 'pip', 'install',
2914 |             f"torch=={torch_version}", f"torchvision=={torch_vision_version}",
2915 |             f"torchaudio=={torch_audio_version}", f"sentence-transformers=={st_version}"
2916 |         ])
2917 |         print_success("Fallback dependencies installed successfully")
2918 |     except subprocess.SubprocessError as e:
2919 |         print_error(f"Failed to install fallback dependencies: {e}")
2920 | 
2921 | def _optimize_pytorch_for_backend(args):
2922 |     """Auto-skip PyTorch for sqlite_vec backend."""
2923 |     if (args.storage_backend == "sqlite_vec" and 
2924 |         not args.skip_pytorch and 
2925 |         not args.force_pytorch):
2926 |         print_step("1d", "Optimizing for SQLite-vec setup")
2927 |         args.skip_pytorch = True
2928 |         print_success("Auto-skipping PyTorch installation for SQLite-vec backend")
2929 |         print_info("• SQLite-vec uses SQLite for vector storage (lighter than ChromaDB)")
2930 |         print_info("• Note: Embedding models still require PyTorch/SentenceTransformers")
2931 |         print_info("• Add --force-pytorch if you want PyTorch installed here")
2932 |         print_warning("• You'll need PyTorch available for embedding functionality")
2933 | 
2934 | def _setup_logging_and_detect_system(args):
2935 |     """Initialize logging and detect system configuration."""
2936 |     try:
2937 |         log_file_path = setup_installer_logging()
2938 |     except Exception as e:
2939 |         print(f"Warning: Could not set up logging: {e}")
2940 |         log_file_path = None
2941 |     
2942 |     system_info, gpu_info, memory_gb = _detect_system_and_environment(args)
2943 |     _recommend_backend(args, system_info, gpu_info, memory_gb)
2944 |     _configure_legacy_hardware(args, system_info)
2945 |     _configure_server_mode(args)
2946 |     _configure_http_api(args)
2947 |     _setup_chromadb_migration(args)
2948 |     _install_compatible_dependencies(args, system_info)
2949 |     _install_fallback_dependencies(args)
2950 |     _optimize_pytorch_for_backend(args)
2951 |     
2952 |     return log_file_path, system_info
2953 |     
2954 | def _execute_core_installation(args, system_info):
2955 |     """Execute the core installation steps (dependencies, package, paths, verification)."""
2956 |     if not check_dependencies():
2957 |         sys.exit(1)
2958 |     
2959 |     if not install_package(args):
2960 |         if system_info["is_macos"] and system_info["is_x86"]:
2961 |             print_warning("Installation failed on macOS Intel.")
2962 |             print_info("Try running the script with '--force-compatible-deps' to force compatible versions:")
2963 |             print_info("python install.py --force-compatible-deps")
2964 |         sys.exit(1)
2965 |     
2966 |     if not configure_paths(args):
2967 |         print_warning("Path configuration failed, but installation may still work")
2968 |     
2969 |     _verify_installation_with_suggestions(system_info)
2970 | 
2971 | def _verify_installation_with_suggestions(system_info):
2972 |     """Verify installation and provide platform-specific troubleshooting suggestions."""
2973 |     if not verify_installation():
2974 |         print_warning("Installation verification failed, but installation may still work")
2975 |         if system_info["is_macos"] and system_info["is_x86"]:
2976 |             python_version = sys.version_info
2977 |             print_info("For macOS Intel compatibility issues, try these steps:")
2978 |             print_info("1. First uninstall current packages: pip uninstall -y torch torchvision torchaudio sentence-transformers")
2979 |             print_info("2. Then reinstall with compatible versions: python install.py --force-compatible-deps")
2980 |             
2981 |             if python_version >= (3, 13):
2982 |                 print_info("For Python 3.13+, you may need to manually install the following:")
2983 |                 print_info("pip install torch==2.3.0 torchvision==0.18.0 torchaudio==2.3.0")
2984 |                 print_info("pip install sentence-transformers==3.0.0")
2985 | 
2986 | def _execute_chromadb_migration(args):
2987 |     """Execute ChromaDB migration if requested."""
2988 |     if not (args.migrate_from_chromadb and hasattr(args, 'chromadb_found') and args.chromadb_found):
2989 |         return
2990 |     
2991 |     print_step("6", "Migrating from ChromaDB")
2992 |     try:
2993 |         migration_script = "scripts/migrate_chroma_to_sqlite.py"
2994 |         if os.path.exists(migration_script):
2995 |             print_info("Running migration script...")
2996 |             subprocess.check_call([sys.executable, migration_script, "--auto-confirm"])
2997 |             print_success("Migration completed successfully!")
2998 |         else:
2999 |             print_warning("Migration script not found - manual migration required")
3000 |             print_info("Run: python scripts/migrate_chroma_to_sqlite.py")
3001 |     except subprocess.SubprocessError as e:
3002 |         print_error(f"Migration failed: {e}")
3003 |         print_info("You can run migration manually later with:")
3004 |         print_info("python scripts/migrate_chroma_to_sqlite.py")
3005 | 
3006 | def _configure_claude_code_if_requested(args, system_info):
3007 |     """Configure Claude Code integration if requested."""
3008 |     if args.configure_claude_code:
3009 |         if not configure_claude_code_integration(system_info):
3010 |             print_warning("Claude Code integration configuration failed")
3011 |             print_info("You can configure it manually later using the documentation")
3012 | 
3013 | def _handle_claude_code_commands(args):
3014 |     """Handle Claude Code commands installation."""
3015 |     should_install_commands = args.install_claude_commands
3016 |     
3017 |     if not should_install_commands and not args.skip_claude_commands_prompt:
3018 |         if install_claude_commands is not None and check_claude_code_cli is not None:
3019 |             claude_available, _ = check_claude_code_cli()
3020 |             if claude_available:
3021 |                 should_install_commands = _prompt_for_claude_commands(args)
3022 |     
3023 |     if should_install_commands and install_claude_commands is not None:
3024 |         _install_claude_commands_internal()
3025 | 
3026 | def _prompt_for_claude_commands(args):
3027 |     """Prompt user for Claude Code commands installation."""
3028 |     print_step("7", "Optional Claude Code Commands")
3029 |     print_info("Claude Code CLI detected! You can install memory operation commands.")
3030 |     print_info("Commands would include: /memory-store, /memory-recall, /memory-search, /memory-health")
3031 |     
3032 |     if args.non_interactive:
3033 |         print_info("Non-interactive mode: skipping Claude Code commands installation")
3034 |         return False
3035 |     
3036 |     print("\n" + "=" * 60)
3037 |     print("⚠️  USER INPUT REQUIRED")
3038 |     print("=" * 60)
3039 |     response = input("Install Claude Code memory commands? (y/N, press Enter for N): ")
3040 |     print("=" * 60 + "\n")
3041 |     return response.lower().startswith('y')
3042 | 
3043 | def _install_claude_commands_internal():
3044 |     """Install Claude Code commands."""
3045 |     print_step("7", "Installing Claude Code Commands")
3046 |     try:
3047 |         if install_claude_commands(verbose=True):
3048 |             print_success("Claude Code commands installed successfully!")
3049 |         else:
3050 |             print_warning("Claude Code commands installation had issues")
3051 |             print_info("You can install them manually later with:")
3052 |             print_info("python scripts/claude_commands_utils.py")
3053 |     except Exception as e:
3054 |         print_error(f"Failed to install Claude Code commands: {str(e)}")
3055 |         print_info("You can install them manually later with:")
3056 |         print_info("python scripts/claude_commands_utils.py")
3057 |     
3058 | def _print_final_setup_notices():
3059 |     """Print first-time setup expectations."""
3060 |     print_header("Installation Complete")
3061 |     print_info("")
3062 |     print_info("⚠️  FIRST-TIME SETUP EXPECTATIONS:")
3063 |     print_info("On first run, you may see these NORMAL warnings:")
3064 |     print_info("  • 'No snapshots directory' - Model will download automatically (~25MB)")
3065 |     print_info("  • 'TRANSFORMERS_CACHE deprecated' - Informational, doesn't affect operation")
3066 |     print_info("  • Model download progress - One-time download (1-2 minutes)")
3067 |     print_info("")
3068 |     print_info("These warnings disappear after the first successful run.")
3069 |     print_info("See docs/first-time-setup.md for details.")
3070 |     print_info("")
3071 | 
3072 | def _determine_final_backend(system_info):
3073 |     """Determine final storage backend based on system configuration."""
3074 |     if system_info["is_macos"] and system_info["is_x86"] and system_info.get("has_homebrew_pytorch"):
3075 |         os.environ['MCP_MEMORY_STORAGE_BACKEND'] = 'sqlite_vec'
3076 |         return 'sqlite_vec'
3077 |     return os.environ.get('MCP_MEMORY_STORAGE_BACKEND', 'chromadb')
3078 | 
3079 | def _setup_multi_client_access(args, system_info, final_backend):
3080 |     """Set up multi-client access if requested or offered."""
3081 |     if args.setup_multi_client:
3082 |         _execute_explicit_multi_client_setup(system_info, args, final_backend)
3083 |     elif should_offer_multi_client_setup(args, final_backend):
3084 |         _handle_interactive_multi_client_setup(args, system_info, final_backend)
3085 | 
3086 | def _execute_explicit_multi_client_setup(system_info, args, final_backend):
3087 |     """Execute multi-client setup when explicitly requested."""
3088 |     try:
3089 |         setup_universal_multi_client_access(system_info, args, final_backend)
3090 |     except Exception as e:
3091 |         print_error(f"Multi-client setup failed: {e}")
3092 |         print_info("You can set up multi-client access manually using:")
3093 |         print_info("python setup_multi_client_complete.py")
3094 | 
3095 | def _handle_interactive_multi_client_setup(args, system_info, final_backend):
3096 |     """Handle interactive multi-client setup prompt."""
3097 |     print_info("")
3098 |     print_info("Multi-Client Access Available!")
3099 |     print_info("")
3100 |     print_info("The MCP Memory Service can be configured for multi-client access, allowing")
3101 |     print_info("multiple applications and IDEs to share the same memory database.")
3102 |     print_info("")
3103 |     print_info("Benefits:")
3104 |     print_info("  • Share memories between Claude Desktop, VS Code, Continue, and other MCP clients")
3105 |     print_info("  • Seamless context sharing across development environments")
3106 |     print_info("  • Single source of truth for all your project memories")
3107 |     print_info("")
3108 |     
3109 |     try:
3110 |         if args.non_interactive:
3111 |             print_info("Non-interactive mode: skipping multi-client configuration")
3112 |             response = 'n'
3113 |         else:
3114 |             print("\n" + "=" * 60)
3115 |             print("⚠️  USER INPUT REQUIRED")
3116 |             print("=" * 60)
3117 |             response = input("Would you like to configure multi-client access? (y/N, press Enter for N): ").strip().lower()
3118 |             print("=" * 60 + "\n")
3119 |         
3120 |         if response in ['y', 'yes']:
3121 |             print_info("")
3122 |             _execute_explicit_multi_client_setup(system_info, args, final_backend)
3123 |         else:
3124 |             print_info("Skipping multi-client setup. You can configure it later using:")
3125 |             print_info("python setup_multi_client_complete.py")
3126 |     except (EOFError, KeyboardInterrupt):
3127 |         print_info("\nSkipping multi-client setup. You can configure it later using:")
3128 |         print_info("python setup_multi_client_complete.py")
3129 |     
3130 |     print_info("")
3131 | 
3132 | def _print_backend_configuration(final_backend, system_info):
3133 |     """Print final backend configuration and recommendations."""
3134 |     use_onnx = os.environ.get('MCP_MEMORY_USE_ONNX', '').lower() in ('1', 'true', 'yes')
3135 |     
3136 |     print_info("You can now run the MCP Memory Service using the 'memory' command")
3137 |     print_info(f"Storage Backend: {final_backend.upper()}")
3138 |     
3139 |     if final_backend == 'sqlite_vec':
3140 |         print_success("Using SQLite-vec - lightweight, fast, minimal dependencies")
3141 |         print_info("   • No complex dependencies or build issues")
3142 |         print_info("   • Excellent performance for typical use cases")
3143 |     else:
3144 |         print_success("Using ChromaDB - full-featured vector database")
3145 |         print_info("   • Advanced features and extensive ecosystem")
3146 |     
3147 |     if use_onnx:
3148 |         print_info("[OK] Using ONNX Runtime for inference")
3149 |         print_info("   • Compatible with Homebrew PyTorch")
3150 |         print_info("   • Reduced dependencies for better compatibility")
3151 |     
3152 |     print_info("For more information, see:")
3153 |     print_info("  • Installation Guide: docs/guides/INSTALLATION_MASTER.md")
3154 |     print_info("  • Backend Comparison: docs/guides/STORAGE_BACKENDS.md")
3155 |     if system_info["is_macos"] and system_info["is_x86"] and is_legacy_hardware(system_info):
3156 |         print_info("  • Legacy Mac Guide: docs/platforms/macos-intel-legacy.md")
3157 |     print_info("  • Main README: README.md")
3158 | 
3159 | def _print_macos_intel_notes(system_info):
3160 |     """Print macOS Intel-specific notes and troubleshooting tips."""
3161 |     if not (system_info["is_macos"] and system_info["is_x86"]):
3162 |         return
3163 |     
3164 |     print_info("\nMacOS Intel Notes:")
3165 |     
3166 |     if system_info.get("has_homebrew_pytorch"):
3167 |         print_info("- Using Homebrew PyTorch installation: " + system_info.get("homebrew_pytorch_version", "Unknown"))
3168 |         print_info("- The MCP Memory Service is configured to use SQLite-vec + ONNX runtime")
3169 |         print_info("- To start the memory service, use:")
3170 |         print_info("  export MCP_MEMORY_USE_ONNX=1")
3171 |         print_info("  export MCP_MEMORY_STORAGE_BACKEND=sqlite_vec")
3172 |         print_info("  memory")
3173 |     else:
3174 |         print_info("- If you encounter issues, try the --force-compatible-deps option")
3175 |         python_version = sys.version_info
3176 |         if python_version >= (3, 13):
3177 |             print_info("- For optimal performance on Intel Macs with Python 3.13+, torch==2.3.0 and sentence-transformers==3.0.0 are recommended")
3178 |             print_info("- You can manually install these versions with:")
3179 |             print_info("  pip install torch==2.3.0 torchvision==0.18.0 torchaudio==2.3.0 sentence-transformers==3.0.0")
3180 |         else:
3181 |             print_info("- For optimal performance on Intel Macs, torch==2.0.1 and sentence-transformers==2.2.2 are recommended")
3182 |             print_info("- You can manually install these versions with:")
3183 |             print_info("  pip install torch==2.0.1 torchvision==2.0.1 torchaudio==2.0.1 sentence-transformers==2.2.2")
3184 |     
3185 |     print_info("\nTroubleshooting Tips:")
3186 |     print_info("- If you have a Homebrew PyTorch installation, use: --use-homebrew-pytorch")
3187 |     print_info("- To completely skip PyTorch installation, use: --skip-pytorch")
3188 |     print_info("- To force the SQLite-vec backend, use: --storage-backend sqlite_vec")
3189 |     print_info("- For a quick test, try running: python test_memory.py")
3190 | 
3191 | def _cleanup_and_exit(log_file_path):
3192 |     """Clean up logging system and exit."""
3193 |     try:
3194 |         cleanup_installer_logging()
3195 |         if log_file_path:
3196 |             print(f"\nInstallation log saved to: {log_file_path}")
3197 |     except Exception:
3198 |         pass  # Silently ignore cleanup errors
3199 | 
3200 | def main():
3201 |     """Main installation function."""
3202 |     args = _parse_arguments()
3203 |     _handle_special_modes(args)
3204 |     
3205 |     log_file_path, system_info = _setup_logging_and_detect_system(args)
3206 |     _execute_core_installation(args, system_info)
3207 |     _execute_chromadb_migration(args)
3208 |     _configure_claude_code_if_requested(args, system_info)
3209 |     _handle_claude_code_commands(args)
3210 |     
3211 |     _print_final_setup_notices()
3212 |     final_backend = _determine_final_backend(system_info)
3213 |     _setup_multi_client_access(args, system_info, final_backend)
3214 |     _print_backend_configuration(final_backend, system_info)
3215 |     _print_macos_intel_notes(system_info)
3216 |     _cleanup_and_exit(log_file_path)
3217 | 
3218 | if __name__ == "__main__":
3219 |     try:
3220 |         main()
3221 |     except KeyboardInterrupt:
3222 |         print("\nInstallation interrupted by user")
3223 |         cleanup_installer_logging()
3224 |         sys.exit(1)
3225 |     except Exception as e:
3226 |         print(f"\nInstallation failed with error: {e}")
3227 |         cleanup_installer_logging()
3228 |         sys.exit(1)
```
Page 44/47FirstPrevNextLast