obsidian_complex_search
Perform advanced searches in Obsidian vaults using JsonLogic queries with pattern matching to find documents by tags, content, or file paths.
Instructions
Complex search for documents using a JsonLogic query. Supports standard JsonLogic operators plus 'glob' and 'regexp' for pattern matching. Results must be non-falsy.
Use this tool when you want to do a complex search, e.g. for all documents with certain tags etc.
ALWAYS follow query syntax in examples.
Examples
1. Match all markdown files
{"glob": ["*.md", {"var": "path"}]}
2. Match all markdown files with 1221 substring inside them
{
"and": [
{ "glob": ["*.md", {"var": "path"}] },
{ "regexp": [".*1221.*", {"var": "content"}] }
]
}
3. Match all markdown files in Work folder containing name Keaton
{
"and": [
{ "glob": ["*.md", {"var": "path"}] },
{ "regexp": [".*Work.*", {"var": "path"}] },
{ "regexp": ["Keaton", {"var": "content"}] }
]
}
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | JsonLogic query object. ALWAYS follow query syntax in examples. Example 1: {"glob": ["*.md", {"var": "path"}]} matches all markdown files Example 2: {"and": [{"glob": ["*.md", {"var": "path"}]}, {"regexp": [".*1221.*", {"var": "content"}]}]} matches all markdown files with 1221 substring inside them Example 3: {"and": [{"glob": ["*.md", {"var": "path"}]}, {"regexp": [".*Work.*", {"var": "path"}]}, {"regexp": ["Keaton", {"var": "content"}]}]} matches all markdown files in Work folder containing name Keaton |
Implementation Reference
- The run_tool method of ComplexSearchToolHandler that executes the obsidian_complex_search tool by invoking api.search_json with the JsonLogic query argument and returning the results as formatted JSON.def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | EmbeddedResource]: if "query" not in args: raise RuntimeError("query argument missing in arguments") results = api.search_json(args.get("query", "")) return [ TextContent( type="text", text=json.dumps(results, indent=2) ) ]
- The get_tool_description method of ComplexSearchToolHandler providing the tool schema, description, and input validation for the JsonLogic query.def get_tool_description(self): return Tool( name=self.name, description="""Complex search for documents using a JsonLogic query. Supports standard JsonLogic operators plus 'glob' and 'regexp' for pattern matching. Results must be non-falsy. Use this tool when you want to do a complex search, e.g. for all documents with certain tags etc. ALWAYS follow query syntax in examples. Examples 1. Match all markdown files {"glob": ["*.md", {"var": "path"}]} 2. Match all markdown files with 1221 substring inside them { "and": [ { "glob": ["*.md", {"var": "path"}] }, { "regexp": [".*1221.*", {"var": "content"}] } ] } 3. Match all markdown files in Work folder containing name Keaton { "and": [ { "glob": ["*.md", {"var": "path"}] }, { "regexp": [".*Work.*", {"var": "path"}] }, { "regexp": ["Keaton", {"var": "content"}] } ] } """, inputSchema={ "type": "object", "properties": { "query": { "type": "object", "description": "JsonLogic query object. ALWAYS follow query syntax in examples. \ Example 1: {\"glob\": [\"*.md\", {\"var\": \"path\"}]} matches all markdown files \ Example 2: {\"and\": [{\"glob\": [\"*.md\", {\"var\": \"path\"}]}, {\"regexp\": [\".*1221.*\", {\"var\": \"content\"}]}]} matches all markdown files with 1221 substring inside them \ Example 3: {\"and\": [{\"glob\": [\"*.md\", {\"var\": \"path\"}]}, {\"regexp\": [\".*Work.*\", {\"var\": \"path\"}]}, {\"regexp\": [\"Keaton\", {\"var\": \"content\"}]}]} matches all markdown files in Work folder containing name Keaton \ " } }, "required": ["query"] } )
- src/mcp_obsidian_advanced/server.py:26-43 (registration)TOOL_MAPPING dictionary entry mapping TOOL_COMPLEX_SEARCH ("obsidian_complex_search") to ComplexSearchToolHandler class for tool registration.TOOL_MAPPING = { tools.TOOL_LIST_FILES_IN_DIR: tools.ListFilesInDirToolHandler, tools.TOOL_SIMPLE_SEARCH: tools.SearchToolHandler, tools.TOOL_PATCH_CONTENT: tools.PatchContentToolHandler, tools.TOOL_PUT_CONTENT: tools.PutContentToolHandler, tools.TOOL_APPEND_CONTENT: tools.AppendContentToolHandler, tools.TOOL_DELETE_FILE: tools.DeleteFileToolHandler, tools.TOOL_COMPLEX_SEARCH: tools.ComplexSearchToolHandler, tools.TOOL_BATCH_GET_FILES: tools.BatchGetFilesToolHandler, tools.TOOL_PERIODIC_NOTES: tools.PeriodicNotesToolHandler, tools.TOOL_RECENT_PERIODIC_NOTES: tools.RecentPeriodicNotesToolHandler, tools.TOOL_RECENT_CHANGES: tools.RecentChangesToolHandler, tools.TOOL_UNDERSTAND_VAULT: tools.UnderstandVaultToolHandler, tools.TOOL_GET_ACTIVE_NOTE: tools.GetActiveNoteToolHandler, tools.TOOL_OPEN_FILES: tools.OpenFilesToolHandler, tools.TOOL_LIST_COMMANDS: tools.ListCommandsToolHandler, tools.TOOL_EXECUTE_COMMANDS: tools.ExecuteCommandsToolHandler, }
- The Obsidian API client's search_json method, which sends the JsonLogic query via POST to the /search/ endpoint and returns the search results. This is the core implementation delegated to by the tool handler.def search_json(self, query: dict) -> Any: url = f"{self.get_base_url()}/search/" headers = self._get_headers() | { 'Content-Type': 'application/vnd.olrapi.jsonlogic+json' } def call_fn(): response = requests.post(url, headers=headers, json=query, verify=self.verify_ssl, timeout=self.timeout) response.raise_for_status() return response.json() return self._safe_call(call_fn)
- src/mcp_obsidian_advanced/server.py:96-108 (registration)The register_tools function that instantiates handlers from TOOL_MAPPING (including ComplexSearchToolHandler for obsidian_complex_search) and adds them to the tool_handlers dictionary used by list_tools and call_tool."""Register the selected tools with the server.""" tools_to_include = parse_include_tools() registered_count = 0 for tool_name in tools_to_include: if tool_name in TOOL_MAPPING: handler_class = TOOL_MAPPING[tool_name] handler_instance = handler_class() add_tool_handler(handler_instance) registered_count += 1 logger.debug(f"Registered tool: {tool_name}") logger.info(f"Successfully registered {registered_count} tools")