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
TableJSON 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")