Skip to main content
Glama

search_notes

Find existing Anki flashcards using Anki's search syntax to locate notes by content, deck, tags, or card state.

Instructions

Search for notes in Anki using the powerful built-in search syntax.

This tool allows you to find existing notes/flashcards using Anki's query language.
Results include note IDs which can be used for follow-up actions.

## Common Search Patterns

**Simple text search:**
- `dog` - notes containing "dog" (matches "doggy", "underdog")
- `dog cat` - notes with both "dog" AND "cat"
- `dog or cat` - notes with "dog" OR "cat"
- `-cat` - notes WITHOUT "cat"
- `"a dog"` - exact phrase match
- `w:dog` - whole word match only

**Field-specific search:**
- `front:dog` - Front field exactly equals "dog"
- `front:*dog*` - Front field contains "dog"
- `front:` - Front field is empty
- `front:_*` - Front field is non-empty

**Deck and tag filters:**
- `deck:French` - cards in French deck (including subdecks)
- `deck:French -deck:French::*` - only top-level French deck
- `tag:vocab` - notes with "vocab" tag
- `tag:none` - notes without any tags
- `note:Basic` - notes using "Basic" note type

**Card state:**
- `is:due` - cards due for review
- `is:new` - new cards not yet studied
- `is:learn` - cards in learning phase
- `is:review` - review cards
- `is:suspended` - suspended cards
- `is:buried` - buried cards

**Card properties:**
- `prop:ivl>=10` - interval >= 10 days
- `prop:due=0` - due today
- `prop:due=1` - due tomorrow
- `prop:lapses>3` - lapsed more than 3 times
- `prop:ease<2.5` - easier than default
- `prop:reps<10` - reviewed fewer than 10 times

**Recent activity:**
- `added:7` - added in last 7 days
- `edited:3` - edited in last 3 days
- `rated:1` - answered today
- `rated:7:1` - answered "Again" in last 7 days
- `introduced:30` - first answered in last 30 days

**Combining searches:**
- `deck:Spanish tag:verb is:due` - due Spanish verbs
- `added:7 -is:review` - new cards added this week
- `(dog or cat) deck:Animals` - dog or cat in Animals deck

Args:
    query: The Anki search query string.
    limit: Maximum notes to return (1-100, default 20).

Returns:
    JSON array of matching notes with their fields, tags, and note IDs.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesAnki search query string
limitNoMaximum number of notes to return

Implementation Reference

  • Registers the search_notes tool with FastMCP using the @mcp.tool() decorator. The handle_anki_connection_error decorator wraps it for error handling.
    @mcp.tool()
  • The core handler function for the search_notes tool. It uses AnkiConnect to find notes matching the query, limits the results, fetches note info, formats them, and returns a JSON string with the results.
    async def search_notes(
        query: str = Field(description="Anki search query string"),
        limit: int = Field(default=20, ge=1, le=100, description="Maximum number of notes to return"),
    ) -> str:
        """Search for notes in Anki using the powerful built-in search syntax.
    
        This tool allows you to find existing notes/flashcards using Anki's query language.
        Results include note IDs which can be used for follow-up actions.
    
        ## Common Search Patterns
    
        **Simple text search:**
        - `dog` - notes containing "dog" (matches "doggy", "underdog")
        - `dog cat` - notes with both "dog" AND "cat"
        - `dog or cat` - notes with "dog" OR "cat"
        - `-cat` - notes WITHOUT "cat"
        - `"a dog"` - exact phrase match
        - `w:dog` - whole word match only
    
        **Field-specific search:**
        - `front:dog` - Front field exactly equals "dog"
        - `front:*dog*` - Front field contains "dog"
        - `front:` - Front field is empty
        - `front:_*` - Front field is non-empty
    
        **Deck and tag filters:**
        - `deck:French` - cards in French deck (including subdecks)
        - `deck:French -deck:French::*` - only top-level French deck
        - `tag:vocab` - notes with "vocab" tag
        - `tag:none` - notes without any tags
        - `note:Basic` - notes using "Basic" note type
    
        **Card state:**
        - `is:due` - cards due for review
        - `is:new` - new cards not yet studied
        - `is:learn` - cards in learning phase
        - `is:review` - review cards
        - `is:suspended` - suspended cards
        - `is:buried` - buried cards
    
        **Card properties:**
        - `prop:ivl>=10` - interval >= 10 days
        - `prop:due=0` - due today
        - `prop:due=1` - due tomorrow
        - `prop:lapses>3` - lapsed more than 3 times
        - `prop:ease<2.5` - easier than default
        - `prop:reps<10` - reviewed fewer than 10 times
    
        **Recent activity:**
        - `added:7` - added in last 7 days
        - `edited:3` - edited in last 3 days
        - `rated:1` - answered today
        - `rated:7:1` - answered "Again" in last 7 days
        - `introduced:30` - first answered in last 30 days
    
        **Combining searches:**
        - `deck:Spanish tag:verb is:due` - due Spanish verbs
        - `added:7 -is:review` - new cards added this week
        - `(dog or cat) deck:Animals` - dog or cat in Animals deck
    
        Args:
            query: The Anki search query string.
            limit: Maximum notes to return (1-100, default 20).
    
        Returns:
            JSON array of matching notes with their fields, tags, and note IDs.
        """
        async with get_anki_client() as anki:
            logger.debug(f"Searching notes with query: {query}")
    
            note_ids = await anki.find_notes(query=query)
            logger.info(f"Found {len(note_ids)} notes for query: {query}")
    
            if not note_ids:
                return json.dumps({
                    "query": query,
                    "total_found": 0,
                    "notes": [],
                    "message": "No notes found matching the query."
                }, indent=2)
    
            # Limit results
            limited_note_ids = note_ids[:limit]
    
            # Fetch note details
            notes_info = await anki.notes_info(limited_note_ids)
    
            # Format results
            formatted_results = _format_search_results(notes_info)
    
            result = {
                "query": query,
                "total_found": len(note_ids),
                "returned": len(formatted_results),
                "notes": formatted_results,
            }
    
            if len(note_ids) > limit:
                result["message"] = f"Showing {limit} of {len(note_ids)} matching notes. Refine your query or increase limit for more results."
    
            return json.dumps(result, indent=2, ensure_ascii=False)
  • Input schema defined using Pydantic Field for the query parameter (required string) and optional limit (int, 1-100, default 20). Output is a formatted JSON string.
        query: str = Field(description="Anki search query string"),
        limit: int = Field(default=20, ge=1, le=100, description="Maximum number of notes to return"),
    ) -> str:
  • Helper function used by search_notes to format the retrieved notes_info into a list of simplified dictionaries including noteId, modelName, cleaned fields, and tags.
    def _format_search_results(notes_info: List[dict]) -> List[dict]:
        """Formats note search results for LLM consumption.
    
        Includes note IDs to enable follow-up actions like editing or deletion.
        """
        results = []
        for note in notes_info:
            processed_fields = {}
            for name, field_data in note.get("fields", {}).items():
                value = field_data.get("value", "")
                # Clean up code formatting for readability
                processed_value = value.replace("<pre><code>", "<code>").replace("</code></pre>", "</code>")
                processed_fields[name] = processed_value
    
            result = {
                "noteId": note.get("noteId"),
                "modelName": note.get("modelName", "UnknownModel"),
                "fields": processed_fields,
                "tags": note.get("tags", []),
            }
            results.append(result)
        return results

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/samefarrar/mcp-ankiconnect'

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