Skip to main content
Glama
MarkusPfundstein

MCP server for Obsidian

obsidian_complex_search

Search Obsidian documents using JsonLogic queries with glob and regex operators to find files by path, content, tags, and patterns.

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
NameRequiredDescriptionDefault
queryYesJsonLogic 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 ComplexSearchToolHandler class defines the tool handler, including __init__ setting the tool name, get_tool_description providing schema and description, and run_tool executing the search via Obsidian API.
    class ComplexSearchToolHandler(ToolHandler):
       def __init__(self):
           super().__init__("obsidian_complex_search")
    
       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"]
               }
           )
    
       def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | EmbeddedResource]:
           if "query" not in args:
               raise RuntimeError("query argument missing in arguments")
    
           api = obsidian.Obsidian(api_key=api_key, host=obsidian_host)
           results = api.search_json(args.get("query", ""))
    
           return [
               TextContent(
                   type="text",
                   text=json.dumps(results, indent=2)
               )
           ]
  • Registers the ComplexSearchToolHandler instance in the tool_handlers dictionary via add_tool_handler.
    add_tool_handler(tools.ComplexSearchToolHandler())
  • The search_json method in Obsidian class performs the actual JSON logic search by posting the query to the Obsidian API endpoint /search/.
    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)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MarkusPfundstein/mcp-obsidian'

If you have feedback or need assistance with the MCP directory API, please join our Discord server