mcp-sqlite-memory-bank 1.4.3__py3-none-any.whl → 1.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -50,6 +50,7 @@ from typing import Dict, Optional, List, cast, Any
50
50
  from fastmcp import FastMCP
51
51
 
52
52
  from .database import get_database
53
+ from .semantic import is_semantic_search_available
53
54
  from .types import (
54
55
  ToolResponse,
55
56
  CreateTableResponse,
@@ -68,6 +69,9 @@ from .utils import catch_errors
68
69
  from .resources import setup_mcp_resources
69
70
  from .prompts import setup_mcp_prompts
70
71
 
72
+ # Import modular tool implementations (for aliases only)
73
+ from .tools import basic, search, analytics
74
+
71
75
  # Initialize FastMCP app with explicit name
72
76
  mcp: FastMCP = FastMCP("SQLite Memory Bank for Copilot/AI Agents")
73
77
 
@@ -86,6 +90,9 @@ setup_mcp_resources(mcp, DB_PATH)
86
90
  # Set up MCP Prompts for enhanced workflow support
87
91
  setup_mcp_prompts(mcp, DB_PATH)
88
92
 
93
+ # All tools are registered via @mcp.tool decorators below
94
+ # No explicit registration needed - decorators handle this automatically
95
+
89
96
 
90
97
  # --- Schema Management Tools for SQLite Memory Bank ---
91
98
 
@@ -392,12 +399,25 @@ def list_all_columns() -> ToolResponse:
392
399
  return cast(ListAllColumnsResponse, get_database(DB_PATH).list_all_columns())
393
400
 
394
401
 
395
- # --- Content Search and Exploration Tools ---
402
+ # Import the implementation functions from tools modules
403
+ from .tools.search import (
404
+ search_content as search_content_impl,
405
+ explore_tables as explore_tables_impl,
406
+ add_embeddings as add_embeddings_impl,
407
+ auto_semantic_search as auto_semantic_search_impl,
408
+ auto_smart_search as auto_smart_search_impl,
409
+ embedding_stats as embedding_stats_impl,
410
+ )
396
411
 
412
+ # --- MCP Tool Definitions (Required in main server.py for FastMCP) ---
397
413
 
398
414
  @mcp.tool
399
415
  @catch_errors
400
- def search_content(query: str, tables: Optional[List[str]] = None, limit: int = 50) -> ToolResponse:
416
+ def search_content(
417
+ query: str,
418
+ tables: Optional[List[str]] = None,
419
+ limit: int = 50,
420
+ ) -> ToolResponse:
401
421
  """
402
422
  Perform full-text search across table content using natural language queries.
403
423
 
@@ -424,12 +444,15 @@ def search_content(query: str, tables: Optional[List[str]] = None, limit: int =
424
444
  - Supports phrase search with quotes: "exact phrase"
425
445
  - Supports boolean operators: AND, OR, NOT
426
446
  """
427
- return cast(ToolResponse, get_database(DB_PATH).search_content(query, tables, limit))
447
+ return search_content_impl(query, tables, limit)
428
448
 
429
449
 
430
450
  @mcp.tool
431
- @catch_errors
432
- def explore_tables(pattern: Optional[str] = None, include_row_counts: bool = True) -> ToolResponse:
451
+ @catch_errors
452
+ def explore_tables(
453
+ pattern: Optional[str] = None,
454
+ include_row_counts: bool = True,
455
+ ) -> ToolResponse:
433
456
  """
434
457
  Explore and discover table structures and content for better searchability.
435
458
 
@@ -458,22 +481,22 @@ def explore_tables(pattern: Optional[str] = None, include_row_counts: bool = Tru
458
481
  - Helps understand what data is available for searching
459
482
  - Useful for exploratory data analysis
460
483
  """
461
- return cast(ToolResponse, get_database(DB_PATH).explore_tables(pattern, include_row_counts))
462
-
463
-
464
- # --- Semantic Search and AI-Enhanced Discovery Tools ---
484
+ return explore_tables_impl(pattern, include_row_counts)
465
485
 
466
486
 
467
487
  @mcp.tool
468
488
  @catch_errors
469
489
  def add_embeddings(
470
- table_name: str, text_columns: List[str], embedding_column: str = "embedding", model_name: str = "all-MiniLM-L6-v2"
490
+ table_name: str,
491
+ text_columns: List[str],
492
+ embedding_column: str = "embedding",
493
+ model_name: str = "all-MiniLM-L6-v2",
471
494
  ) -> ToolResponse:
472
495
  """
473
496
  ⚠️ **ADVANCED TOOL** - Most agents should use auto_smart_search() instead!
474
-
497
+
475
498
  Generate and store vector embeddings for semantic search on table content.
476
-
499
+
477
500
  **RECOMMENDATION**: Use auto_smart_search() or auto_semantic_search() for automatic setup.
478
501
  This tool is for advanced users who need manual control over embedding generation.
479
502
 
@@ -501,14 +524,12 @@ def add_embeddings(
501
524
  - Uses efficient batch processing for large datasets
502
525
  - Supports various sentence-transformer models for different use cases
503
526
  """
504
- return cast(
505
- ToolResponse, get_database(DB_PATH).generate_embeddings(table_name, text_columns, embedding_column, model_name)
506
- )
527
+ return add_embeddings_impl(table_name, text_columns, embedding_column, model_name)
507
528
 
508
529
 
509
530
  @mcp.tool
510
531
  @catch_errors
511
- def semantic_search(
532
+ def auto_semantic_search(
512
533
  query: str,
513
534
  tables: Optional[List[str]] = None,
514
535
  similarity_threshold: float = 0.5,
@@ -516,102 +537,48 @@ def semantic_search(
516
537
  model_name: str = "all-MiniLM-L6-v2",
517
538
  ) -> ToolResponse:
518
539
  """
519
- ⚠️ **ADVANCED TOOL** - Most agents should use auto_smart_search() instead!
520
-
521
- Find content using natural language semantic similarity rather than exact keyword matching.
522
-
523
- **RECOMMENDATION**: Use auto_smart_search() for automatic setup and hybrid search capabilities.
524
- This tool requires manual embedding setup via add_embeddings() first.
540
+ 🚀 **ZERO-SETUP SEMANTIC SEARCH** - Just search, embeddings are handled automatically!
525
541
 
526
- This enables intelligent knowledge discovery - find related concepts even when
527
- they use different terminology or phrasing.
542
+ Find content using natural language semantic similarity. If embeddings don't exist,
543
+ they will be automatically generated for text columns. This is the easiest way to
544
+ do semantic search - no manual setup required!
528
545
 
529
546
  Args:
530
547
  query (str): Natural language search query
531
- tables (Optional[List[str]]): Specific tables to search (default: all tables with embeddings)
548
+ tables (Optional[List[str]]): Specific tables to search (default: all tables)
532
549
  similarity_threshold (float): Minimum similarity score (0.0-1.0, default: 0.5)
533
550
  limit (int): Maximum number of results to return (default: 10)
534
- model_name (str): Model to use for query embedding (default: "all-MiniLM-L6-v2")
551
+ model_name (str): Model to use for embeddings (default: "all-MiniLM-L6-v2")
535
552
 
536
553
  Returns:
537
- ToolResponse: On success: {"success": True, "results": List[...], "total_results": int}
554
+ ToolResponse: On success: {"success": True, "results": List[...], "auto_embedded_tables": List[str]}
538
555
  On error: {"success": False, "error": str, "category": str, "details": dict}
539
556
 
540
557
  Examples:
541
- >>> semantic_search("API design patterns")
558
+ >>> auto_semantic_search("API design patterns")
542
559
  {"success": True, "results": [
543
- {"table_name": "technical_decisions", "similarity_score": 0.87, "decision_name": "REST API Structure", ...},
544
- {"table_name": "project_structure", "similarity_score": 0.72, "component": "API Gateway", ...}
545
- ]}
560
+ {"table_name": "technical_decisions", "similarity_score": 0.87, "decision_name": "REST API Structure", ...}
561
+ ], "auto_embedded_tables": ["technical_decisions"]}
546
562
 
547
- >>> semantic_search("machine learning", tables=["technical_decisions"], similarity_threshold=0.7)
563
+ >>> auto_semantic_search("machine learning concepts")
548
564
  # Finds content about "ML", "AI", "neural networks", etc.
565
+ # Automatically creates embeddings if they don't exist!
549
566
 
550
567
  FastMCP Tool Info:
568
+ - **COMPLETELY AUTOMATIC**: No manual embedding setup required
569
+ - Auto-detects text columns and creates embeddings as needed
551
570
  - Works across multiple tables simultaneously
552
571
  - Finds conceptually similar content regardless of exact wording
553
572
  - Returns relevance scores for ranking results
554
573
  - Supports fuzzy matching and concept discovery
555
- - Much more powerful than keyword-based search for knowledge discovery
556
- """
557
- return cast(
558
- ToolResponse,
559
- get_database(DB_PATH).semantic_search(
560
- query, tables, "embedding", None, similarity_threshold, limit, model_name
561
- ),
562
- )
563
-
564
-
565
- @mcp.tool
566
- @catch_errors
567
- def find_related(
568
- table_name: str,
569
- row_id: int,
570
- similarity_threshold: float = 0.5,
571
- limit: int = 5,
572
- model_name: str = "all-MiniLM-L6-v2",
573
- ) -> ToolResponse:
574
- """
575
- Find content related to a specific row by semantic similarity.
576
-
577
- Discover connections and related information that might not be obvious
578
- from direct references or tags.
579
-
580
- Args:
581
- table_name (str): Table containing the reference row
582
- row_id (int): ID of the row to find related content for
583
- similarity_threshold (float): Minimum similarity score (default: 0.5)
584
- limit (int): Maximum number of related items to return (default: 5)
585
- model_name (str): Model for similarity comparison (default: "all-MiniLM-L6-v2")
586
-
587
- Returns:
588
- ToolResponse: On success: {"success": True, "results": List[...], "target_row": Dict}
589
- On error: {"success": False, "error": str, "category": str, "details": dict}
590
-
591
- Examples:
592
- >>> find_related("technical_decisions", 5)
593
- {"success": True, "results": [
594
- {"id": 12, "similarity_score": 0.84, "decision_name": "Related Architecture Choice", ...},
595
- {"id": 3, "similarity_score": 0.71, "decision_name": "Similar Technology Decision", ...}
596
- ], "target_row": {"id": 5, "decision_name": "API Framework Selection", ...}}
597
-
598
- FastMCP Tool Info:
599
- - Helps discover hidden relationships between data
600
- - Useful for finding similar decisions, related problems, or connected concepts
601
- - Can reveal patterns and themes across your knowledge base
602
- - Enables serendipitous discovery of relevant information
574
+ - Perfect for agents - just search and it works!
603
575
  """
604
- return cast(
605
- ToolResponse,
606
- get_database(DB_PATH).find_related_content(
607
- table_name, row_id, "embedding", similarity_threshold, limit, model_name
608
- ),
609
- )
576
+ return auto_semantic_search_impl(query, tables, similarity_threshold, limit, model_name)
610
577
 
611
578
 
612
579
  @mcp.tool
613
580
  @catch_errors
614
- def smart_search(
581
+ def auto_smart_search(
615
582
  query: str,
616
583
  tables: Optional[List[str]] = None,
617
584
  semantic_weight: float = 0.7,
@@ -620,15 +587,11 @@ def smart_search(
620
587
  model_name: str = "all-MiniLM-L6-v2",
621
588
  ) -> ToolResponse:
622
589
  """
623
- ⚠️ **ADVANCED TOOL** - Most agents should use auto_smart_search() instead!
624
-
625
- Intelligent hybrid search combining semantic understanding with keyword matching.
626
-
627
- **RECOMMENDATION**: Use auto_smart_search() for the same functionality with automatic setup.
628
- This tool requires manual embedding setup via add_embeddings() first.
590
+ 🚀 **ZERO-SETUP HYBRID SEARCH** - Best of both worlds with automatic embedding!
629
591
 
630
- Provides the best of both worlds - semantic similarity for concept discovery
631
- plus exact text matching for precise searches.
592
+ Intelligent hybrid search combining semantic understanding with keyword matching.
593
+ Automatically generates embeddings for text columns when needed. This is the
594
+ ultimate search tool - no manual setup required!
632
595
 
633
596
  Args:
634
597
  query (str): Search query (natural language or keywords)
@@ -639,37 +602,63 @@ def smart_search(
639
602
  model_name (str): Semantic model to use (default: "all-MiniLM-L6-v2")
640
603
 
641
604
  Returns:
642
- ToolResponse: On success: {"success": True, "results": List[...], "search_type": "hybrid"}
605
+ ToolResponse: On success: {"success": True, "results": List[...], "search_type": "auto_hybrid"}
643
606
  On error: {"success": False, "error": str, "category": str, "details": dict}
644
607
 
645
608
  Examples:
646
- >>> smart_search("user authentication security")
609
+ >>> auto_smart_search("user authentication security")
647
610
  {"success": True, "results": [
648
- {"combined_score": 0.89, "semantic_score": 0.92, "text_score": 0.82, ...},
649
- {"combined_score": 0.76, "semantic_score": 0.71, "text_score": 0.85, ...}
650
- ], "search_type": "hybrid"}
611
+ {"combined_score": 0.89, "semantic_score": 0.92, "text_score": 0.82, ...}
612
+ ], "search_type": "auto_hybrid", "auto_embedded_tables": ["user_data"]}
651
613
 
652
614
  FastMCP Tool Info:
615
+ - **COMPLETELY AUTOMATIC**: No manual embedding setup required
653
616
  - Automatically balances semantic and keyword search
617
+ - Auto-detects text columns and creates embeddings as needed
654
618
  - Provides separate scores for transparency
655
619
  - Falls back gracefully if semantic search unavailable
656
620
  - Optimal for both exploratory and precise searches
657
621
  - Perfect for agents - ultimate search tool that just works!
658
622
  """
659
- return cast(
660
- ToolResponse,
661
- get_database(DB_PATH).hybrid_search(
662
- query, tables, None, "embedding", semantic_weight, text_weight, limit, model_name
663
- ),
664
- )
623
+ return auto_smart_search_impl(query, tables, semantic_weight, text_weight, limit, model_name)
624
+
625
+
626
+ @mcp.tool
627
+ @catch_errors
628
+ def embedding_stats(
629
+ table_name: str,
630
+ embedding_column: str = "embedding",
631
+ ) -> ToolResponse:
632
+ """
633
+ Get statistics about semantic search readiness for a table.
634
+
635
+ Check which content has embeddings and can be searched semantically.
636
+
637
+ Args:
638
+ table_name (str): Table to analyze
639
+ embedding_column (str): Embedding column to check (default: "embedding")
640
+
641
+ Returns:
642
+ ToolResponse: On success: {"success": True, "coverage_percent": float, "total_rows": int}
643
+ On error: {"success": False, "error": str, "category": str, "details": dict}
665
644
 
645
+ Examples:
646
+ >>> embedding_stats("technical_decisions")
647
+ {"success": True, "total_rows": 25, "embedded_rows": 25, "coverage_percent": 100.0,
648
+ "embedding_dimensions": 384}
666
649
 
667
- # --- Auto-Embedding Semantic Search Tools ---
650
+ FastMCP Tool Info:
651
+ - Shows how much content is ready for semantic search
652
+ - Helps identify tables that need embedding generation
653
+ - Provides embedding dimension info for debugging
654
+ - Useful for monitoring semantic search capabilities
655
+ """
656
+ return embedding_stats_impl(table_name, embedding_column)
668
657
 
669
658
 
670
659
  @mcp.tool
671
660
  @catch_errors
672
- def auto_semantic_search(
661
+ def semantic_search(
673
662
  query: str,
674
663
  tables: Optional[List[str]] = None,
675
664
  similarity_threshold: float = 0.5,
@@ -677,117 +666,50 @@ def auto_semantic_search(
677
666
  model_name: str = "all-MiniLM-L6-v2",
678
667
  ) -> ToolResponse:
679
668
  """
680
- 🚀 **ZERO-SETUP SEMANTIC SEARCH** - Just search, embeddings are handled automatically!
669
+ ⚠️ **ADVANCED TOOL** - Most agents should use auto_smart_search() instead!
681
670
 
682
- Find content using natural language semantic similarity. If embeddings don't exist,
683
- they will be automatically generated for text columns. This is the easiest way to
684
- do semantic search - no manual setup required!
671
+ Find content using natural language semantic similarity rather than exact keyword matching.
672
+
673
+ **RECOMMENDATION**: Use auto_smart_search() for the same functionality with automatic setup.
674
+ This tool requires manual embedding setup via add_embeddings() first.
675
+
676
+ This enables intelligent knowledge discovery - find related concepts even when
677
+ they use different terminology or phrasing.
685
678
 
686
679
  Args:
687
680
  query (str): Natural language search query
688
- tables (Optional[List[str]]): Specific tables to search (default: all tables)
681
+ tables (Optional[List[str]]): Specific tables to search (default: all tables with embeddings)
689
682
  similarity_threshold (float): Minimum similarity score (0.0-1.0, default: 0.5)
690
683
  limit (int): Maximum number of results to return (default: 10)
691
- model_name (str): Model to use for embeddings (default: "all-MiniLM-L6-v2")
684
+ model_name (str): Model to use for query embedding (default: "all-MiniLM-L6-v2")
692
685
 
693
686
  Returns:
694
- ToolResponse: On success: {"success": True, "results": List[...], "auto_embedded_tables": List[str]}
687
+ ToolResponse: On success: {"success": True, "results": List[...], "total_results": int}
695
688
  On error: {"success": False, "error": str, "category": str, "details": dict}
696
689
 
697
690
  Examples:
698
- >>> auto_semantic_search("API design patterns")
691
+ >>> semantic_search("API design patterns")
699
692
  {"success": True, "results": [
700
- {"table_name": "technical_decisions", "similarity_score": 0.87, "decision_name": "REST API Structure", ...}
701
- ], "auto_embedded_tables": ["technical_decisions"]}
693
+ {"table_name": "technical_decisions", "similarity_score": 0.87, "decision_name": "REST API Structure", ...},
694
+ {"table_name": "project_structure", "similarity_score": 0.72, "component": "API Gateway", ...}
695
+ ]}
702
696
 
703
- >>> auto_semantic_search("machine learning concepts")
697
+ >>> semantic_search("machine learning", tables=["technical_decisions"], similarity_threshold=0.7)
704
698
  # Finds content about "ML", "AI", "neural networks", etc.
705
- # Automatically creates embeddings if they don't exist!
706
699
 
707
700
  FastMCP Tool Info:
708
- - **COMPLETELY AUTOMATIC**: No manual embedding setup required
709
- - Auto-detects text columns and creates embeddings as needed
710
701
  - Works across multiple tables simultaneously
711
702
  - Finds conceptually similar content regardless of exact wording
712
703
  - Returns relevance scores for ranking results
713
704
  - Supports fuzzy matching and concept discovery
714
- - Perfect for agents - just search and it works!
705
+ - Much more powerful than keyword-based search for knowledge discovery
715
706
  """
716
- try:
717
- db = get_database(DB_PATH)
718
- auto_embedded_tables: List[str] = []
719
-
720
- # Get tables to search
721
- search_tables: List[str]
722
- if tables:
723
- search_tables = tables
724
- else:
725
- tables_result = db.list_tables()
726
- if not tables_result.get("success"):
727
- return cast(ToolResponse, tables_result)
728
- all_tables = tables_result.get("tables", [])
729
- if isinstance(all_tables, list):
730
- search_tables = all_tables
731
- else:
732
- search_tables = []
733
-
734
- # Auto-embed text columns in tables that don't have embeddings
735
- for table_name in search_tables:
736
- try:
737
- # Check if table has embeddings
738
- stats_result = db.get_embedding_stats(table_name, "embedding")
739
- coverage_percent = stats_result.get("coverage_percent", 0)
740
- if stats_result.get("success") and isinstance(coverage_percent, (int, float)) and coverage_percent > 0:
741
- continue # Table already has embeddings
742
-
743
- # Get table schema to find text columns
744
- schema_result = db.describe_table(table_name)
745
- if not schema_result.get("success"):
746
- continue
747
-
748
- # Find text columns
749
- text_columns = []
750
- columns = schema_result.get("columns", [])
751
- if isinstance(columns, list):
752
- for col in columns:
753
- if isinstance(col, dict) and "TEXT" in col.get("type", "").upper():
754
- text_columns.append(col["name"])
755
-
756
- # Auto-embed text columns
757
- if text_columns:
758
- embed_result = db.generate_embeddings(table_name, text_columns, "embedding", model_name)
759
- if embed_result.get("success"):
760
- auto_embedded_tables.append(table_name)
761
-
762
- except Exception:
763
- # If auto-embedding fails, continue without it
764
- continue
765
-
766
- # Perform semantic search
767
- search_result = db.semantic_search(
768
- query, search_tables, "embedding", None, similarity_threshold, limit, model_name
769
- )
770
-
771
- # Add auto-embedding info to result
772
- if isinstance(search_result, dict):
773
- search_result["auto_embedded_tables"] = auto_embedded_tables
774
- if auto_embedded_tables:
775
- search_result["auto_embedding_note"] = f"Automatically generated embeddings for {len(auto_embedded_tables)} table(s)"
776
-
777
- return cast(ToolResponse, search_result)
778
-
779
- except Exception as e:
780
- return cast(ToolResponse, {
781
- "success": False,
782
- "error": f"Auto semantic search failed: {str(e)}",
783
- "category": "SEMANTIC_SEARCH_ERROR",
784
- "details": {"query": query, "tables": tables}
785
- })
707
+ return _semantic_search_impl(query, tables, similarity_threshold, limit, model_name)
786
708
 
787
709
 
788
710
  @mcp.tool
789
711
  @catch_errors
790
- def auto_smart_search(
712
+ def smart_search(
791
713
  query: str,
792
714
  tables: Optional[List[str]] = None,
793
715
  semantic_weight: float = 0.7,
@@ -796,11 +718,15 @@ def auto_smart_search(
796
718
  model_name: str = "all-MiniLM-L6-v2",
797
719
  ) -> ToolResponse:
798
720
  """
799
- 🚀 **ZERO-SETUP HYBRID SEARCH** - Best of both worlds with automatic embedding!
721
+ ⚠️ **ADVANCED TOOL** - Most agents should use auto_smart_search() instead!
800
722
 
801
723
  Intelligent hybrid search combining semantic understanding with keyword matching.
802
- Automatically generates embeddings for text columns when needed. This is the
803
- ultimate search tool - no manual setup required!
724
+
725
+ **RECOMMENDATION**: Use auto_smart_search() for the same functionality with automatic setup.
726
+ This tool requires manual embedding setup via add_embeddings() first.
727
+
728
+ Provides the best of both worlds - semantic similarity for concept discovery
729
+ plus exact text matching for precise searches.
804
730
 
805
731
  Args:
806
732
  query (str): Search query (natural language or keywords)
@@ -811,242 +737,66 @@ def auto_smart_search(
811
737
  model_name (str): Semantic model to use (default: "all-MiniLM-L6-v2")
812
738
 
813
739
  Returns:
814
- ToolResponse: On success: {"success": True, "results": List[...], "search_type": "auto_hybrid"}
740
+ ToolResponse: On success: {"success": True, "results": List[...], "search_type": "hybrid"}
815
741
  On error: {"success": False, "error": str, "category": str, "details": dict}
816
742
 
817
743
  Examples:
818
- >>> auto_smart_search("user authentication security")
744
+ >>> smart_search("user authentication security")
819
745
  {"success": True, "results": [
820
- {"combined_score": 0.89, "semantic_score": 0.92, "text_score": 0.82, ...}
821
- ], "search_type": "auto_hybrid", "auto_embedded_tables": ["user_data"]}
746
+ {"combined_score": 0.89, "semantic_score": 0.92, "text_score": 0.82, ...},
747
+ {"combined_score": 0.76, "semantic_score": 0.71, "text_score": 0.85, ...}
748
+ ], "search_type": "hybrid"}
822
749
 
823
750
  FastMCP Tool Info:
824
- - **COMPLETELY AUTOMATIC**: No manual embedding setup required
825
751
  - Automatically balances semantic and keyword search
826
- - Auto-detects text columns and creates embeddings as needed
827
752
  - Provides separate scores for transparency
828
753
  - Falls back gracefully if semantic search unavailable
829
754
  - Optimal for both exploratory and precise searches
830
755
  - Perfect for agents - ultimate search tool that just works!
831
756
  """
832
- try:
833
- db = get_database(DB_PATH)
834
- auto_embedded_tables: List[str] = []
835
-
836
- # Get tables to search
837
- search_tables: List[str]
838
- if tables:
839
- search_tables = tables
840
- else:
841
- tables_result = db.list_tables()
842
- if not tables_result.get("success"):
843
- return cast(ToolResponse, tables_result)
844
- all_tables = tables_result.get("tables", [])
845
- if isinstance(all_tables, list):
846
- search_tables = all_tables
847
- else:
848
- search_tables = []
849
-
850
- # Auto-embed text columns in tables that don't have embeddings
851
- for table_name in search_tables:
852
- try:
853
- # Check if table has embeddings
854
- stats_result = db.get_embedding_stats(table_name, "embedding")
855
- coverage_percent = stats_result.get("coverage_percent", 0)
856
- if stats_result.get("success") and isinstance(coverage_percent, (int, float)) and coverage_percent > 0:
857
- continue # Table already has embeddings
858
-
859
- # Get table schema to find text columns
860
- schema_result = db.describe_table(table_name)
861
- if not schema_result.get("success"):
862
- continue
863
-
864
- # Find text columns
865
- text_columns = []
866
- columns = schema_result.get("columns", [])
867
- if isinstance(columns, list):
868
- for col in columns:
869
- if isinstance(col, dict) and "TEXT" in col.get("type", "").upper():
870
- text_columns.append(col["name"])
871
-
872
- # Auto-embed text columns
873
- if text_columns:
874
- embed_result = db.generate_embeddings(table_name, text_columns, "embedding", model_name)
875
- if embed_result.get("success"):
876
- auto_embedded_tables.append(table_name)
877
-
878
- except Exception:
879
- # If auto-embedding fails, continue without it
880
- continue
881
-
882
- # Now perform hybrid search
883
- db = get_database(DB_PATH)
884
- hybrid_result = db.hybrid_search(
885
- query, tables, None, "embedding", semantic_weight, text_weight, limit, model_name
886
- )
887
-
888
- # Add auto-embedding info to result
889
- if isinstance(hybrid_result, dict) and hybrid_result.get("success"):
890
- # Convert to mutable dict to add extra fields
891
- final_result = dict(hybrid_result)
892
- final_result["search_type"] = "auto_hybrid"
893
- final_result["auto_embedded_tables"] = auto_embedded_tables
894
- if auto_embedded_tables:
895
- final_result["auto_embedding_note"] = f"Automatically generated embeddings for {len(auto_embedded_tables)} table(s)"
896
- return cast(ToolResponse, final_result)
897
- else:
898
- return cast(ToolResponse, hybrid_result)
899
-
900
- except Exception as e:
901
- return cast(ToolResponse, {
902
- "success": False,
903
- "error": f"Auto smart search failed: {str(e)}",
904
- "category": "HYBRID_SEARCH_ERROR",
905
- "details": {"query": query, "tables": tables}
906
- })
757
+ return _smart_search_impl(query, tables, semantic_weight, text_weight, limit, model_name)
907
758
 
908
759
 
909
760
  @mcp.tool
910
- @catch_errors
911
- def embedding_stats(table_name: str, embedding_column: str = "embedding") -> ToolResponse:
761
+ @catch_errors
762
+ def find_related(
763
+ table_name: str,
764
+ row_id: int,
765
+ similarity_threshold: float = 0.5,
766
+ limit: int = 5,
767
+ model_name: str = "all-MiniLM-L6-v2",
768
+ ) -> ToolResponse:
912
769
  """
913
- Get statistics about semantic search readiness for a table.
770
+ Find content related to a specific row by semantic similarity.
914
771
 
915
- Check which content has embeddings and can be searched semantically.
772
+ Discover connections and related information that might not be obvious
773
+ from direct references or tags.
916
774
 
917
775
  Args:
918
- table_name (str): Table to analyze
919
- embedding_column (str): Embedding column to check (default: "embedding")
776
+ table_name (str): Table containing the reference row
777
+ row_id (int): ID of the row to find related content for
778
+ similarity_threshold (float): Minimum similarity score (default: 0.5)
779
+ limit (int): Maximum number of related items to return (default: 5)
780
+ model_name (str): Model for similarity comparison (default: "all-MiniLM-L6-v2")
920
781
 
921
782
  Returns:
922
- ToolResponse: On success: {"success": True, "coverage_percent": float, "total_rows": int}
783
+ ToolResponse: On success: {"success": True, "results": List[...], "target_row": Dict}
923
784
  On error: {"success": False, "error": str, "category": str, "details": dict}
924
785
 
925
786
  Examples:
926
- >>> embedding_stats("technical_decisions")
927
- {"success": True, "total_rows": 25, "embedded_rows": 25, "coverage_percent": 100.0,
928
- "embedding_dimensions": 384}
787
+ >>> find_related("technical_decisions", 5)
788
+ {"success": True, "results": [
789
+ {"id": 12, "similarity_score": 0.84, "decision_name": "Related Architecture Choice", ...},
790
+ {"id": 3, "similarity_score": 0.71, "decision_name": "Similar Technology Decision", ...}
791
+ ], "target_row": {"id": 5, "decision_name": "API Framework Selection", ...}}
929
792
 
930
793
  FastMCP Tool Info:
931
- - Shows how much content is ready for semantic search
932
- - Helps identify tables that need embedding generation
933
- - Provides embedding dimension info for debugging
934
- - Useful for monitoring semantic search capabilities
935
- """
936
- return cast(ToolResponse, get_database(DB_PATH).get_embedding_stats(table_name, embedding_column))
937
-
938
-
939
- # --- Enhanced Tool Discovery and Categorization ---
940
-
941
-
942
- @mcp.tool
943
- @catch_errors
944
- def list_tool_categories() -> ToolResponse:
945
- """
946
- List all available tool categories for better organization and discovery.
947
-
948
- Returns organized view of available functionality for LLMs and agents.
949
-
950
- Returns:
951
- ToolResponse: {"success": True, "categories": {category: [tool_names]}}
952
- """
953
- categories = {
954
- "schema_management": [
955
- "create_table", "list_tables", "describe_table",
956
- "drop_table", "rename_table", "list_all_columns"
957
- ],
958
- "data_operations": [
959
- "create_row", "read_rows", "update_rows",
960
- "delete_rows", "run_select_query"
961
- ],
962
- "search_discovery": [
963
- "search_content", "explore_tables"
964
- ],
965
- "semantic_search": [
966
- "add_embeddings", "semantic_search", "find_related",
967
- "smart_search", "embedding_stats"
968
- ],
969
- "workflow_shortcuts": [
970
- "quick_note", "remember_decision", "store_context"
971
- ],
972
- "analytics_insights": [
973
- "memory_usage_stats", "content_analytics"
974
- ]
975
- }
976
-
977
- return cast(ToolResponse, {
978
- "success": True,
979
- "categories": categories,
980
- "total_tools": sum(len(tools) for tools in categories.values()),
981
- "description": "Organized view of all available memory bank capabilities"
982
- })
983
-
984
-
985
- @mcp.tool
986
- @catch_errors
987
- def get_tools_by_category(category: str) -> ToolResponse:
988
- """
989
- Get detailed information about tools in a specific category.
990
-
991
- Args:
992
- category (str): Category name (schema_management, data_operations,
993
- search_discovery, semantic_search, workflow_shortcuts, analytics_insights)
994
-
995
- Returns:
996
- ToolResponse: {"success": True, "tools": [{"name": str, "description": str, "usage": str}]}
794
+ - Helps discover hidden relationships between data
795
+ - Useful for finding similar decisions, related problems, or connected concepts
796
+ - Can reveal patterns and themes across your knowledge base
797
+ - Enables serendipitous discovery of relevant information
997
798
  """
998
- tool_details = {
999
- "schema_management": [
1000
- {"name": "create_table", "description": "Create new tables with custom schemas", "usage": "create_table('table_name', [{'name': 'col', 'type': 'TEXT'}])"},
1001
- {"name": "list_tables", "description": "List all available tables", "usage": "list_tables()"},
1002
- {"name": "describe_table", "description": "Get detailed schema for a table", "usage": "describe_table('table_name')"},
1003
- {"name": "drop_table", "description": "Delete a table permanently", "usage": "drop_table('table_name')"},
1004
- {"name": "rename_table", "description": "Rename an existing table", "usage": "rename_table('old_name', 'new_name')"},
1005
- {"name": "list_all_columns", "description": "Get all columns across all tables", "usage": "list_all_columns()"},
1006
- ],
1007
- "data_operations": [
1008
- {"name": "create_row", "description": "Insert new data into any table", "usage": "create_row('table', {'col': 'value'})"},
1009
- {"name": "read_rows", "description": "Query data with optional filtering", "usage": "read_rows('table', {'filter_col': 'value'})"},
1010
- {"name": "update_rows", "description": "Modify existing data", "usage": "update_rows('table', {'new_data': 'value'}, {'where_col': 'value'})"},
1011
- {"name": "delete_rows", "description": "Remove data from tables", "usage": "delete_rows('table', {'filter_col': 'value'})"},
1012
- {"name": "run_select_query", "description": "Execute safe SELECT queries", "usage": "run_select_query('table', ['col1', 'col2'], {'filter': 'value'})"},
1013
- ],
1014
- "search_discovery": [
1015
- {"name": "search_content", "description": "Full-text search across all content", "usage": "search_content('search query', ['table1', 'table2'])"},
1016
- {"name": "explore_tables", "description": "Discover table structures and sample data", "usage": "explore_tables('pattern*')"},
1017
- ],
1018
- "semantic_search": [
1019
- {"name": "add_embeddings", "description": "Enable semantic search on tables", "usage": "add_embeddings('table', ['text_col1', 'text_col2'])"},
1020
- {"name": "semantic_search", "description": "Natural language content discovery", "usage": "semantic_search('find ML algorithms')"},
1021
- {"name": "find_related", "description": "Discover similar content", "usage": "find_related('table', row_id, 0.5)"},
1022
- {"name": "smart_search", "description": "Hybrid keyword + semantic search", "usage": "smart_search('search query')"},
1023
- {"name": "embedding_stats", "description": "Check semantic search readiness", "usage": "embedding_stats('table')"},
1024
- ],
1025
- "workflow_shortcuts": [
1026
- {"name": "quick_note", "description": "Rapidly store notes and observations", "usage": "quick_note('content', 'category')"},
1027
- {"name": "remember_decision", "description": "Store technical decisions with context", "usage": "remember_decision('decision', 'approach', 'rationale')"},
1028
- {"name": "store_context", "description": "Save session context and progress", "usage": "store_context('topic', 'current_state', 'next_steps')"},
1029
- ],
1030
- "analytics_insights": [
1031
- {"name": "memory_usage_stats", "description": "Analyze memory bank usage patterns", "usage": "memory_usage_stats()"},
1032
- {"name": "content_analytics", "description": "Get insights on stored content", "usage": "content_analytics('table_name')"},
1033
- ],
1034
- }
1035
-
1036
- if category not in tool_details:
1037
- return cast(ToolResponse, {
1038
- "success": False,
1039
- "error": f"Unknown category '{category}'. Available: {list(tool_details.keys())}",
1040
- "category": "VALIDATION",
1041
- "details": {"available_categories": list(tool_details.keys())},
1042
- })
1043
-
1044
- return cast(ToolResponse, {
1045
- "success": True,
1046
- "category": category,
1047
- "tools": tool_details[category],
1048
- "tool_count": len(tool_details[category]),
1049
- })
799
+ return _find_related_impl(table_name, row_id, similarity_threshold, limit, model_name)
1050
800
 
1051
801
 
1052
802
  # Export the FastMCP app for use in other modules and server runners
@@ -1073,108 +823,19 @@ Available tools:
1073
823
  - run_select_query: Run a safe SELECT query (no arbitrary SQL)
1074
824
  - search_content: Perform full-text search across table content
1075
825
  - explore_tables: Discover table structures and content for better searchability
826
+ - auto_semantic_search: Zero-setup semantic search with automatic embeddings
827
+ - auto_smart_search: Zero-setup hybrid search combining semantic and keyword search
828
+ - add_embeddings: Manual embedding generation for advanced users
829
+ - embedding_stats: Check semantic search readiness
1076
830
  """
1077
831
 
1078
832
 
1079
- # Legacy implementation functions for backwards compatibility with tests
1080
- def _create_row_impl(table_name: str, data: Dict[str, Any]) -> Dict[str, Any]:
1081
- """Legacy implementation function for tests."""
1082
- try:
1083
- # Handle test-specific table creation for legacy compatibility
1084
- if not re.match(r"^[A-Za-z_][A-Za-z0-9_]*$", table_name):
1085
- return {"success": False, "error": f"Invalid table name: {table_name}"}
1086
-
1087
- # Auto-create test tables for compatibility
1088
- current_db = get_database(DB_PATH)
1089
- if table_name == "nodes":
1090
- try:
1091
- current_db.create_table(
1092
- "nodes",
1093
- [
1094
- {"name": "id", "type": "INTEGER PRIMARY KEY AUTOINCREMENT"},
1095
- {"name": "label", "type": "TEXT NOT NULL"},
1096
- ],
1097
- )
1098
- except Exception:
1099
- pass # Table might already exist
1100
- elif table_name == "edges":
1101
- try:
1102
- current_db.create_table(
1103
- "edges",
1104
- [
1105
- {"name": "id", "type": "INTEGER PRIMARY KEY AUTOINCREMENT"},
1106
- {"name": "source", "type": "INTEGER NOT NULL"},
1107
- {"name": "target", "type": "INTEGER NOT NULL"},
1108
- {"name": "type", "type": "TEXT NOT NULL"},
1109
- ],
1110
- )
1111
- except Exception:
1112
- pass # Table might already exist
1113
-
1114
- result = current_db.insert_row(table_name, data)
1115
- # Ensure we return Dict[str, Any] for legacy compatibility
1116
- return dict(result) if isinstance(result, dict) else {"success": False, "error": "Unknown error"}
1117
-
1118
- except Exception as e:
1119
- logging.error(f"_create_row_impl error: {e}")
1120
- return {"success": False, "error": str(e)}
1121
-
1122
-
1123
- def _read_rows_impl(table_name: str, where: Optional[Dict[str, Any]] = None, limit: int = 100) -> Dict[str, Any]:
1124
- """Legacy implementation function for tests."""
1125
- try:
1126
- result = get_database(DB_PATH).read_rows(table_name, where, limit)
1127
- # Ensure we return Dict[str, Any] for legacy compatibility
1128
- return dict(result) if isinstance(result, dict) else {"success": False, "error": "Unknown error"}
1129
- except Exception as e:
1130
- logging.error(f"_read_rows_impl error: {e}")
1131
- return {"success": False, "error": str(e)}
1132
-
1133
-
1134
- def _update_rows_impl(table_name: str, data: Dict[str, Any], where: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
1135
- """Legacy implementation function for tests."""
1136
- try:
1137
- # Auto-create test tables for compatibility
1138
- if table_name == "edges":
1139
- try:
1140
- current_db = get_database(DB_PATH)
1141
- current_db.create_table(
1142
- "edges",
1143
- [
1144
- {"name": "id", "type": "INTEGER PRIMARY KEY AUTOINCREMENT"},
1145
- {"name": "source", "type": "INTEGER NOT NULL"},
1146
- {"name": "target", "type": "INTEGER NOT NULL"},
1147
- {"name": "type", "type": "TEXT NOT NULL"},
1148
- ],
1149
- )
1150
- except Exception:
1151
- pass # Table might already exist
1152
-
1153
- result = get_database(DB_PATH).update_rows(table_name, data, where)
1154
- # Ensure we return Dict[str, Any] for legacy compatibility
1155
- return dict(result) if isinstance(result, dict) else {"success": False, "error": "Unknown error"}
1156
- except Exception as e:
1157
- logging.error(f"_update_rows_impl error: {e}")
1158
- return {"success": False, "error": str(e)}
1159
-
1160
-
1161
- def _delete_rows_impl(table_name: str, where: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
1162
- """Legacy implementation function for tests."""
1163
- try:
1164
- result = get_database(DB_PATH).delete_rows(table_name, where)
1165
- # Ensure we return Dict[str, Any] for legacy compatibility
1166
- return dict(result) if isinstance(result, dict) else {"success": False, "error": "Unknown error"}
1167
- except Exception as e:
1168
- logging.error(f"_delete_rows_impl error: {e}")
1169
- return {"success": False, "error": str(e)}
1170
-
1171
-
1172
833
  # Public API - these functions are available for direct Python use and as MCP tools
1173
834
  __all__ = [
1174
835
  "app",
1175
836
  "mcp",
1176
837
  "create_table",
1177
- "drop_table",
838
+ "drop_table",
1178
839
  "rename_table",
1179
840
  "list_tables",
1180
841
  "describe_table",
@@ -1186,10 +847,10 @@ __all__ = [
1186
847
  "run_select_query",
1187
848
  "search_content",
1188
849
  "explore_tables",
1189
- "_create_row_impl",
1190
- "_read_rows_impl",
1191
- "_update_rows_impl",
1192
- "_delete_rows_impl",
850
+ "add_embeddings",
851
+ "auto_semantic_search",
852
+ "auto_smart_search",
853
+ "embedding_stats",
1193
854
  ]
1194
855
 
1195
856
 
@@ -1240,3 +901,31 @@ if __name__ == "__main__":
1240
901
 
1241
902
  # Run the FastMCP app in stdio mode for MCP clients
1242
903
  app.run()
904
+
905
+
906
+ # Compatibility aliases for tests that expect _impl functions
907
+ # Import modules already imported above for tool implementations
908
+
909
+ # Basic CRUD operation aliases
910
+ _create_row_impl = basic.create_row
911
+ _read_rows_impl = basic.read_rows
912
+ _update_rows_impl = basic.update_rows
913
+ _delete_rows_impl = basic.delete_rows
914
+ _list_tables_impl = basic.list_tables
915
+ _describe_table_impl = basic.describe_table
916
+ _drop_table_impl = basic.drop_table
917
+ _create_table_impl = basic.create_table
918
+
919
+ # Search operation aliases
920
+ _search_content_impl = search.search_content
921
+ _explore_tables_impl = search.explore_tables
922
+ _add_embeddings_impl = search.add_embeddings
923
+ _semantic_search_impl = search.semantic_search
924
+ _smart_search_impl = search.smart_search
925
+ _find_related_impl = search.find_related
926
+ _auto_semantic_search_impl = search.auto_semantic_search
927
+ _auto_smart_search_impl = search.auto_smart_search
928
+
929
+ # Analytics operation aliases
930
+ _analyze_memory_patterns_impl = analytics.analyze_memory_patterns
931
+ _get_content_health_score_impl = analytics.get_content_health_score