Coverage for src / qdrant_loader_mcp_server / mcp / formatters / basic.py: 96%

67 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-10 09:41 +0000

1""" 

2Basic Result Formatters - Core Search Result Formatting. 

3 

4This module handles basic formatting of search results, attachments, 

5and hierarchical results for display in the MCP interface. 

6""" 

7 

8from ...search.components.search_result_models import HybridSearchResult 

9 

10 

11class BasicResultFormatters: 

12 """Handles basic result formatting operations.""" 

13 

14 @staticmethod 

15 def _format_common_fields( 

16 result: HybridSearchResult, is_attachment_view: bool = False 

17 ) -> str: 

18 """Build the base formatted string for a search result. 

19 

20 This consolidates shared formatting between standard search results and 

21 attachment-focused views while preserving the original output order and 

22 conditional branches. 

23 """ 

24 formatted_result = f"Score: {result.score}\n" 

25 formatted_result += f"Source: {result.source_type}" 

26 

27 text = result.text 

28 contextual_content = getattr(result, "contextual_content", None) 

29 if isinstance(contextual_content, str) and contextual_content: 

30 formatted_result += f"\nContext: {contextual_content}\n" 

31 if isinstance(text, str) and text.startswith(contextual_content): 

32 text = text[len(contextual_content) :].lstrip() 

33 

34 formatted_result += f"\nText: {text}" 

35 

36 if result.source_title: 

37 formatted_result += f" - {result.source_title}" 

38 

39 # Project information (only shown in non-attachment view to preserve behavior) 

40 if not is_attachment_view: 

41 project_info = result.get_project_info() 

42 if project_info: 

43 formatted_result += f"\n🏗️ {project_info}" 

44 

45 # Attachment info (shown if viewing attachments or the result itself is an attachment) 

46 if is_attachment_view or result.is_attachment: 

47 formatted_result += "\n📎 Attachment" 

48 if result.original_filename: 

49 formatted_result += f": {result.original_filename}" 

50 if result.attachment_context: 

51 formatted_result += f"\n📋 {result.attachment_context}" 

52 if result.parent_document_title: 

53 formatted_result += f"\n📄 Attached to: {result.parent_document_title}" 

54 

55 # Confluence breadcrumb path 

56 if result.source_type == "confluence" and result.breadcrumb_text: 

57 formatted_result += f"\n📍 Path: {result.breadcrumb_text}" 

58 

59 # Source URL appended inline 

60 if result.source_url: 

61 formatted_result += f" ({result.source_url})" 

62 

63 if result.file_path: 

64 formatted_result += f"\nFile: {result.file_path}" 

65 

66 if result.repo_name: 

67 formatted_result += f"\nRepo: {result.repo_name}" 

68 

69 # Additional hierarchy info for Confluence 

70 hierarchy_context = getattr(result, "hierarchy_context", None) 

71 if result.source_type == "confluence" and hierarchy_context: 

72 formatted_result += f"\n🏗️ {hierarchy_context}" 

73 

74 # Parent info (for hierarchy, not for attachment items themselves) 

75 if result.parent_title and not result.is_attachment: 

76 formatted_result += f"\n⬆️ Parent: {result.parent_title}" 

77 

78 # Children count 

79 if result.has_children(): 

80 formatted_result += f"\n⬇️ Children: {result.children_count}" 

81 

82 return formatted_result 

83 

84 @staticmethod 

85 def format_search_result(result: HybridSearchResult) -> str: 

86 """Format a search result for display.""" 

87 return BasicResultFormatters._format_common_fields( 

88 result, is_attachment_view=False 

89 ) 

90 

91 @staticmethod 

92 def format_attachment_search_result(result: HybridSearchResult) -> str: 

93 """Format an attachment search result for display.""" 

94 return BasicResultFormatters._format_common_fields( 

95 result, is_attachment_view=True 

96 ) 

97 

98 @staticmethod 

99 def format_hierarchical_results( 

100 organized_results: dict[str, list[HybridSearchResult]], 

101 ) -> str: 

102 """Format hierarchically organized results for display.""" 

103 formatted_sections = [] 

104 

105 for root_title, results in organized_results.items(): 

106 section = f"📁 **{root_title}** ({len(results)} results)\n" 

107 

108 for result in results: 

109 indent = " " * (getattr(result, "depth", 0) or 0) 

110 section += f"{indent}📄 {result.source_title}" 

111 if hasattr(result, "hierarchy_context") and result.hierarchy_context: 

112 section += f" | {result.hierarchy_context}" 

113 section += f" (Score: {result.score:.3f})\n" 

114 

115 # Add a snippet of the content 

116 content_snippet = ( 

117 result.text[:150] + "..." if len(result.text) > 150 else result.text 

118 ) 

119 section += f"{indent} {content_snippet}\n" 

120 

121 if result.source_url: 

122 section += f"{indent} 🔗 {result.source_url}\n" 

123 section += "\n" 

124 

125 formatted_sections.append(section) 

126 

127 return ( 

128 f"Found {sum(len(results) for results in organized_results.values())} results organized by hierarchy:\n\n" 

129 + "\n".join(formatted_sections) 

130 )