mcp-sqlite-memory-bank 1.4.2__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)
665
624
 
666
625
 
667
- # --- Auto-Embedding Semantic Search Tools ---
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}
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}
649
+
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,109 +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 = []
719
-
720
- # Get tables to search
721
- if tables:
722
- search_tables = tables
723
- else:
724
- tables_result = db.list_tables()
725
- if not tables_result.get("success"):
726
- return cast(ToolResponse, tables_result)
727
- search_tables = tables_result.get("tables", [])
728
-
729
- # Auto-embed text columns in tables that don't have embeddings
730
- for table_name in search_tables:
731
- try:
732
- # Check if table has embeddings
733
- stats_result = db.get_embedding_stats(table_name, "embedding")
734
- if stats_result.get("success") and stats_result.get("coverage_percent", 0) > 0:
735
- continue # Table already has embeddings
736
-
737
- # Get table schema to find text columns
738
- schema_result = db.describe_table(table_name)
739
- if not schema_result.get("success"):
740
- continue
741
-
742
- # Find text columns
743
- text_columns = []
744
- for col in schema_result.get("columns", []):
745
- if "TEXT" in col.get("type", "").upper():
746
- text_columns.append(col["name"])
747
-
748
- # Auto-embed text columns
749
- if text_columns:
750
- embed_result = db.generate_embeddings(table_name, text_columns, "embedding", model_name)
751
- if embed_result.get("success"):
752
- auto_embedded_tables.append(table_name)
753
-
754
- except Exception:
755
- # If auto-embedding fails, continue without it
756
- continue
757
-
758
- # Perform semantic search
759
- search_result = db.semantic_search(
760
- query, search_tables, "embedding", None, similarity_threshold, limit, model_name
761
- )
762
-
763
- # Add auto-embedding info to result
764
- if isinstance(search_result, dict):
765
- search_result["auto_embedded_tables"] = auto_embedded_tables
766
- if auto_embedded_tables:
767
- search_result["auto_embedding_note"] = f"Automatically generated embeddings for {len(auto_embedded_tables)} table(s)"
768
-
769
- return cast(ToolResponse, search_result)
770
-
771
- except Exception as e:
772
- return cast(ToolResponse, {
773
- "success": False,
774
- "error": f"Auto semantic search failed: {str(e)}",
775
- "category": "SEMANTIC_SEARCH_ERROR",
776
- "details": {"query": query, "tables": tables}
777
- })
707
+ return _semantic_search_impl(query, tables, similarity_threshold, limit, model_name)
778
708
 
779
709
 
780
710
  @mcp.tool
781
711
  @catch_errors
782
- def auto_smart_search(
712
+ def smart_search(
783
713
  query: str,
784
714
  tables: Optional[List[str]] = None,
785
715
  semantic_weight: float = 0.7,
@@ -788,11 +718,15 @@ def auto_smart_search(
788
718
  model_name: str = "all-MiniLM-L6-v2",
789
719
  ) -> ToolResponse:
790
720
  """
791
- 🚀 **ZERO-SETUP HYBRID SEARCH** - Best of both worlds with automatic embedding!
721
+ ⚠️ **ADVANCED TOOL** - Most agents should use auto_smart_search() instead!
792
722
 
793
723
  Intelligent hybrid search combining semantic understanding with keyword matching.
794
- Automatically generates embeddings for text columns when needed. This is the
795
- 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.
796
730
 
797
731
  Args:
798
732
  query (str): Search query (natural language or keywords)
@@ -803,167 +737,66 @@ def auto_smart_search(
803
737
  model_name (str): Semantic model to use (default: "all-MiniLM-L6-v2")
804
738
 
805
739
  Returns:
806
- ToolResponse: On success: {"success": True, "results": List[...], "search_type": "auto_hybrid"}
740
+ ToolResponse: On success: {"success": True, "results": List[...], "search_type": "hybrid"}
807
741
  On error: {"success": False, "error": str, "category": str, "details": dict}
808
742
 
809
743
  Examples:
810
- >>> auto_smart_search("user authentication security")
744
+ >>> smart_search("user authentication security")
811
745
  {"success": True, "results": [
812
- {"combined_score": 0.89, "semantic_score": 0.92, "text_score": 0.82, ...}
813
- ], "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"}
814
749
 
815
750
  FastMCP Tool Info:
816
- - **COMPLETELY AUTOMATIC**: No manual embedding setup required
817
751
  - Automatically balances semantic and keyword search
818
- - Auto-detects text columns and creates embeddings as needed
819
752
  - Provides separate scores for transparency
820
753
  - Falls back gracefully if semantic search unavailable
821
754
  - Optimal for both exploratory and precise searches
822
755
  - Perfect for agents - ultimate search tool that just works!
823
756
  """
824
- try:
825
- # First try auto semantic search to ensure embeddings exist
826
- auto_semantic_result = auto_semantic_search(query, tables, 0.3, limit, model_name)
827
- auto_embedded_tables = []
828
-
829
- if auto_semantic_result.get("success"):
830
- auto_embedded_tables = auto_semantic_result.get("auto_embedded_tables", [])
831
-
832
- # Now perform hybrid search
833
- db = get_database(DB_PATH)
834
- hybrid_result = db.hybrid_search(
835
- query, tables, None, "embedding", semantic_weight, text_weight, limit, model_name
836
- )
837
-
838
- # Add auto-embedding info to result
839
- if isinstance(hybrid_result, dict):
840
- hybrid_result["search_type"] = "auto_hybrid"
841
- hybrid_result["auto_embedded_tables"] = auto_embedded_tables
842
- if auto_embedded_tables:
843
- hybrid_result["auto_embedding_note"] = f"Automatically generated embeddings for {len(auto_embedded_tables)} table(s)"
844
-
845
- return cast(ToolResponse, hybrid_result)
846
-
847
- except Exception as e:
848
- return cast(ToolResponse, {
849
- "success": False,
850
- "error": f"Auto smart search failed: {str(e)}",
851
- "category": "HYBRID_SEARCH_ERROR",
852
- "details": {"query": query, "tables": tables}
853
- })
854
-
855
-
856
- # --- Enhanced Tool Discovery and Categorization ---
757
+ return _smart_search_impl(query, tables, semantic_weight, text_weight, limit, model_name)
857
758
 
858
759
 
859
760
  @mcp.tool
860
761
  @catch_errors
861
- def list_tool_categories() -> ToolResponse:
862
- """
863
- List all available tool categories for better organization and discovery.
864
-
865
- Returns organized view of available functionality for LLMs and agents.
866
-
867
- Returns:
868
- ToolResponse: {"success": True, "categories": {category: [tool_names]}}
869
- """
870
- categories = {
871
- "schema_management": [
872
- "create_table", "list_tables", "describe_table",
873
- "drop_table", "rename_table", "list_all_columns"
874
- ],
875
- "data_operations": [
876
- "create_row", "read_rows", "update_rows",
877
- "delete_rows", "run_select_query"
878
- ],
879
- "search_discovery": [
880
- "search_content", "explore_tables"
881
- ],
882
- "semantic_search": [
883
- "add_embeddings", "semantic_search", "find_related",
884
- "smart_search", "embedding_stats"
885
- ],
886
- "workflow_shortcuts": [
887
- "quick_note", "remember_decision", "store_context"
888
- ],
889
- "analytics_insights": [
890
- "memory_usage_stats", "content_analytics"
891
- ]
892
- }
893
-
894
- return cast(ToolResponse, {
895
- "success": True,
896
- "categories": categories,
897
- "total_tools": sum(len(tools) for tools in categories.values()),
898
- "description": "Organized view of all available memory bank capabilities"
899
- })
900
-
901
-
902
- @mcp.tool
903
- @catch_errors
904
- def get_tools_by_category(category: str) -> ToolResponse:
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:
905
769
  """
906
- Get detailed information about tools in a specific category.
907
-
770
+ Find content related to a specific row by semantic similarity.
771
+
772
+ Discover connections and related information that might not be obvious
773
+ from direct references or tags.
774
+
908
775
  Args:
909
- category (str): Category name (schema_management, data_operations,
910
- search_discovery, semantic_search, workflow_shortcuts, analytics_insights)
911
-
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")
781
+
912
782
  Returns:
913
- ToolResponse: {"success": True, "tools": [{"name": str, "description": str, "usage": str}]}
783
+ ToolResponse: On success: {"success": True, "results": List[...], "target_row": Dict}
784
+ On error: {"success": False, "error": str, "category": str, "details": dict}
785
+
786
+ Examples:
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", ...}}
792
+
793
+ FastMCP Tool Info:
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
914
798
  """
915
- tool_details = {
916
- "schema_management": [
917
- {"name": "create_table", "description": "Create new tables with custom schemas", "usage": "create_table('table_name', [{'name': 'col', 'type': 'TEXT'}])"},
918
- {"name": "list_tables", "description": "List all available tables", "usage": "list_tables()"},
919
- {"name": "describe_table", "description": "Get detailed schema for a table", "usage": "describe_table('table_name')"},
920
- {"name": "drop_table", "description": "Delete a table permanently", "usage": "drop_table('table_name')"},
921
- {"name": "rename_table", "description": "Rename an existing table", "usage": "rename_table('old_name', 'new_name')"},
922
- {"name": "list_all_columns", "description": "Get all columns across all tables", "usage": "list_all_columns()"},
923
- ],
924
- "data_operations": [
925
- {"name": "create_row", "description": "Insert new data into any table", "usage": "create_row('table', {'col': 'value'})"},
926
- {"name": "read_rows", "description": "Query data with optional filtering", "usage": "read_rows('table', {'filter_col': 'value'})"},
927
- {"name": "update_rows", "description": "Modify existing data", "usage": "update_rows('table', {'new_data': 'value'}, {'where_col': 'value'})"},
928
- {"name": "delete_rows", "description": "Remove data from tables", "usage": "delete_rows('table', {'filter_col': 'value'})"},
929
- {"name": "run_select_query", "description": "Execute safe SELECT queries", "usage": "run_select_query('table', ['col1', 'col2'], {'filter': 'value'})"},
930
- ],
931
- "search_discovery": [
932
- {"name": "search_content", "description": "Full-text search across all content", "usage": "search_content('search query', ['table1', 'table2'])"},
933
- {"name": "explore_tables", "description": "Discover table structures and sample data", "usage": "explore_tables('pattern*')"},
934
- ],
935
- "semantic_search": [
936
- {"name": "add_embeddings", "description": "Enable semantic search on tables", "usage": "add_embeddings('table', ['text_col1', 'text_col2'])"},
937
- {"name": "semantic_search", "description": "Natural language content discovery", "usage": "semantic_search('find ML algorithms')"},
938
- {"name": "find_related", "description": "Discover similar content", "usage": "find_related('table', row_id, 0.5)"},
939
- {"name": "smart_search", "description": "Hybrid keyword + semantic search", "usage": "smart_search('search query')"},
940
- {"name": "embedding_stats", "description": "Check semantic search readiness", "usage": "embedding_stats('table')"},
941
- ],
942
- "workflow_shortcuts": [
943
- {"name": "quick_note", "description": "Rapidly store notes and observations", "usage": "quick_note('content', 'category')"},
944
- {"name": "remember_decision", "description": "Store technical decisions with context", "usage": "remember_decision('decision', 'approach', 'rationale')"},
945
- {"name": "store_context", "description": "Save session context and progress", "usage": "store_context('topic', 'current_state', 'next_steps')"},
946
- ],
947
- "analytics_insights": [
948
- {"name": "memory_usage_stats", "description": "Analyze memory bank usage patterns", "usage": "memory_usage_stats()"},
949
- {"name": "content_analytics", "description": "Get insights on stored content", "usage": "content_analytics('table_name')"},
950
- ],
951
- }
952
-
953
- if category not in tool_details:
954
- return cast(ToolResponse, {
955
- "success": False,
956
- "error": f"Unknown category '{category}'. Available: {list(tool_details.keys())}",
957
- "category": "VALIDATION",
958
- "details": {"available_categories": list(tool_details.keys())},
959
- })
960
-
961
- return cast(ToolResponse, {
962
- "success": True,
963
- "category": category,
964
- "tools": tool_details[category],
965
- "tool_count": len(tool_details[category]),
966
- })
799
+ return _find_related_impl(table_name, row_id, similarity_threshold, limit, model_name)
967
800
 
968
801
 
969
802
  # Export the FastMCP app for use in other modules and server runners
@@ -990,108 +823,19 @@ Available tools:
990
823
  - run_select_query: Run a safe SELECT query (no arbitrary SQL)
991
824
  - search_content: Perform full-text search across table content
992
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
993
830
  """
994
831
 
995
832
 
996
- # Legacy implementation functions for backwards compatibility with tests
997
- def _create_row_impl(table_name: str, data: Dict[str, Any]) -> Dict[str, Any]:
998
- """Legacy implementation function for tests."""
999
- try:
1000
- # Handle test-specific table creation for legacy compatibility
1001
- if not re.match(r"^[A-Za-z_][A-Za-z0-9_]*$", table_name):
1002
- return {"success": False, "error": f"Invalid table name: {table_name}"}
1003
-
1004
- # Auto-create test tables for compatibility
1005
- current_db = get_database(DB_PATH)
1006
- if table_name == "nodes":
1007
- try:
1008
- current_db.create_table(
1009
- "nodes",
1010
- [
1011
- {"name": "id", "type": "INTEGER PRIMARY KEY AUTOINCREMENT"},
1012
- {"name": "label", "type": "TEXT NOT NULL"},
1013
- ],
1014
- )
1015
- except Exception:
1016
- pass # Table might already exist
1017
- elif table_name == "edges":
1018
- try:
1019
- current_db.create_table(
1020
- "edges",
1021
- [
1022
- {"name": "id", "type": "INTEGER PRIMARY KEY AUTOINCREMENT"},
1023
- {"name": "source", "type": "INTEGER NOT NULL"},
1024
- {"name": "target", "type": "INTEGER NOT NULL"},
1025
- {"name": "type", "type": "TEXT NOT NULL"},
1026
- ],
1027
- )
1028
- except Exception:
1029
- pass # Table might already exist
1030
-
1031
- result = current_db.insert_row(table_name, data)
1032
- # Ensure we return Dict[str, Any] for legacy compatibility
1033
- return dict(result) if isinstance(result, dict) else {"success": False, "error": "Unknown error"}
1034
-
1035
- except Exception as e:
1036
- logging.error(f"_create_row_impl error: {e}")
1037
- return {"success": False, "error": str(e)}
1038
-
1039
-
1040
- def _read_rows_impl(table_name: str, where: Optional[Dict[str, Any]] = None, limit: int = 100) -> Dict[str, Any]:
1041
- """Legacy implementation function for tests."""
1042
- try:
1043
- result = get_database(DB_PATH).read_rows(table_name, where, limit)
1044
- # Ensure we return Dict[str, Any] for legacy compatibility
1045
- return dict(result) if isinstance(result, dict) else {"success": False, "error": "Unknown error"}
1046
- except Exception as e:
1047
- logging.error(f"_read_rows_impl error: {e}")
1048
- return {"success": False, "error": str(e)}
1049
-
1050
-
1051
- def _update_rows_impl(table_name: str, data: Dict[str, Any], where: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
1052
- """Legacy implementation function for tests."""
1053
- try:
1054
- # Auto-create test tables for compatibility
1055
- if table_name == "edges":
1056
- try:
1057
- current_db = get_database(DB_PATH)
1058
- current_db.create_table(
1059
- "edges",
1060
- [
1061
- {"name": "id", "type": "INTEGER PRIMARY KEY AUTOINCREMENT"},
1062
- {"name": "source", "type": "INTEGER NOT NULL"},
1063
- {"name": "target", "type": "INTEGER NOT NULL"},
1064
- {"name": "type", "type": "TEXT NOT NULL"},
1065
- ],
1066
- )
1067
- except Exception:
1068
- pass # Table might already exist
1069
-
1070
- result = get_database(DB_PATH).update_rows(table_name, data, where)
1071
- # Ensure we return Dict[str, Any] for legacy compatibility
1072
- return dict(result) if isinstance(result, dict) else {"success": False, "error": "Unknown error"}
1073
- except Exception as e:
1074
- logging.error(f"_update_rows_impl error: {e}")
1075
- return {"success": False, "error": str(e)}
1076
-
1077
-
1078
- def _delete_rows_impl(table_name: str, where: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
1079
- """Legacy implementation function for tests."""
1080
- try:
1081
- result = get_database(DB_PATH).delete_rows(table_name, where)
1082
- # Ensure we return Dict[str, Any] for legacy compatibility
1083
- return dict(result) if isinstance(result, dict) else {"success": False, "error": "Unknown error"}
1084
- except Exception as e:
1085
- logging.error(f"_delete_rows_impl error: {e}")
1086
- return {"success": False, "error": str(e)}
1087
-
1088
-
1089
833
  # Public API - these functions are available for direct Python use and as MCP tools
1090
834
  __all__ = [
1091
835
  "app",
1092
836
  "mcp",
1093
837
  "create_table",
1094
- "drop_table",
838
+ "drop_table",
1095
839
  "rename_table",
1096
840
  "list_tables",
1097
841
  "describe_table",
@@ -1103,10 +847,10 @@ __all__ = [
1103
847
  "run_select_query",
1104
848
  "search_content",
1105
849
  "explore_tables",
1106
- "_create_row_impl",
1107
- "_read_rows_impl",
1108
- "_update_rows_impl",
1109
- "_delete_rows_impl",
850
+ "add_embeddings",
851
+ "auto_semantic_search",
852
+ "auto_smart_search",
853
+ "embedding_stats",
1110
854
  ]
1111
855
 
1112
856
 
@@ -1157,3 +901,31 @@ if __name__ == "__main__":
1157
901
 
1158
902
  # Run the FastMCP app in stdio mode for MCP clients
1159
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