search
Search for content across LogSeq pages, blocks, and files to find specific information within your knowledge base.
Instructions
Search for content across LogSeq pages, blocks, and files
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query text | |
| limit | No | Maximum number of results to return | |
| include_blocks | No | Include block content results | |
| include_pages | No | Include page name results | |
| include_files | No | Include file name results |
Implementation Reference
- src/mcp_logseq/tools.py:396-489 (handler)The run_tool method implements the core logic of the 'search' tool: it validates input arguments, calls the LogSeq API's search_content method, processes and formats the results into categorized sections (blocks, snippets, pages, files), handles pagination info, and returns formatted TextContent.
def run_tool(self, args: dict) -> list[TextContent]: """Execute search and format results.""" logger.info(f"Searching with args: {args}") if "query" not in args: raise RuntimeError("query argument required") query = args["query"] limit = args.get("limit", 20) include_blocks = args.get("include_blocks", True) include_pages = args.get("include_pages", True) include_files = args.get("include_files", False) try: # Prepare search options search_options = {"limit": limit} api = logseq.LogSeq(api_key=api_key) result = api.search_content(query, search_options) if not result: return [TextContent( type="text", text=f"No search results found for '{query}'" )] # Format results content_parts = [] content_parts.append(f"# Search Results for '{query}'\n") # Block results if include_blocks and result.get("blocks"): blocks = result["blocks"] content_parts.append(f"## 📄 Content Blocks ({len(blocks)} found)") for i, block in enumerate(blocks[:limit]): # LogSeq returns blocks with 'block/content' key content = block.get("block/content", "").strip() if content: # Truncate long content if len(content) > 150: content = content[:150] + "..." content_parts.append(f"{i+1}. {content}") content_parts.append("") # Page snippet results if include_blocks and result.get("pages-content"): snippets = result["pages-content"] content_parts.append(f"## 📝 Page Snippets ({len(snippets)} found)") for i, snippet in enumerate(snippets[:limit]): # LogSeq returns snippets with 'block/snippet' key snippet_text = snippet.get("block/snippet", "").strip() if snippet_text: # Clean up snippet text snippet_text = snippet_text.replace("$pfts_2lqh>$", "").replace("$<pfts_2lqh$", "") if len(snippet_text) > 200: snippet_text = snippet_text[:200] + "..." content_parts.append(f"{i+1}. {snippet_text}") content_parts.append("") # Page name results if include_pages and result.get("pages"): pages = result["pages"] content_parts.append(f"## 📑 Matching Pages ({len(pages)} found)") for page in pages: content_parts.append(f"- {page}") content_parts.append("") # File results if include_files and result.get("files"): files = result["files"] content_parts.append(f"## 📁 Matching Files ({len(files)} found)") for file_path in files: content_parts.append(f"- {file_path}") content_parts.append("") # Pagination info if result.get("has-more?"): content_parts.append("📌 *More results available - increase limit to see more*") # Summary total_results = len(result.get("blocks", [])) + len(result.get("pages", [])) + len(result.get("files", [])) content_parts.append(f"\n**Total results found: {total_results}**") response_text = "\n".join(content_parts) return [TextContent(type="text", text=response_text)] except Exception as e: logger.error(f"Failed to search: {str(e)}") return [TextContent( type="text", text=f"❌ Search failed: {str(e)}" )] - src/mcp_logseq/tools.py:360-394 (schema)The get_tool_description method returns the Tool object defining the schema for the 'search' tool, including input parameters: query (required), limit, include_blocks, include_pages, include_files.
def get_tool_description(self): return Tool( name=self.name, description="Search for content across LogSeq pages, blocks, and files", inputSchema={ "type": "object", "properties": { "query": { "type": "string", "description": "Search query text" }, "limit": { "type": "integer", "description": "Maximum number of results to return", "default": 20 }, "include_blocks": { "type": "boolean", "description": "Include block content results", "default": True }, "include_pages": { "type": "boolean", "description": "Include page name results", "default": True }, "include_files": { "type": "boolean", "description": "Include file name results", "default": False } }, "required": ["query"] } ) - src/mcp_logseq/server.py:74-81 (registration)The registration block where all tool handlers are added to the tool_handlers dictionary, specifically including add_tool_handler(tools.SearchToolHandler()) on line 80.
logger.info("Registering tool handlers...") add_tool_handler(tools.CreatePageToolHandler()) add_tool_handler(tools.ListPagesToolHandler()) add_tool_handler(tools.GetPageContentToolHandler()) add_tool_handler(tools.DeletePageToolHandler()) add_tool_handler(tools.UpdatePageToolHandler()) add_tool_handler(tools.SearchToolHandler()) logger.info("Tool handlers registration complete")