Markdown Converter
Agent skill for markdown-converter
Search Zotero library using code execution for efficient multi-strategy searches without crash risks. Use this skill when the user needs comprehensive Zotero searches with automatic deduplication and ranking.
Sign in to like and favorite skills
Search your Zotero library using code execution for safe, efficient, comprehensive searches.
Instead of calling MCP tools directly (which loads all results into context and risks crashes), write Python code that:
Benefits:
Zotero treats multi-word queries as AND conditions!
ā Wrong:
comprehensive_search("Atyal Atayal ę³°é
ę") ā finds 0 results (needs ALL terms)
ā
Right: Search each term separately and merge results (see Pattern 6 below)
When to use multi-term OR search:
Semantic search is now working correctly (fixed 2025-01-08). However, you may see 404 error messages in output from the semantic search engine itself - these can be ignored as our wrapper handles them correctly.
For 90% of Zotero searches, use this simple pattern:
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import SearchOrchestrator, format_results # Single comprehensive search orchestrator = SearchOrchestrator() results = orchestrator.comprehensive_search( "user's query here", max_results=20, # Return top 20 most relevant use_semantic=True # Semantic search now works correctly ) # Format and display print(format_results(results, include_abstracts=True))
This automatically:
User asks: "Find papers about embodied cognition"
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import SearchOrchestrator, format_results orchestrator = SearchOrchestrator() results = orchestrator.comprehensive_search("embodied cognition", max_results=20) print(format_results(results))
User asks: "Find recent journal articles about machine learning"
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import ZoteroLibrary, SearchOrchestrator, format_results library = ZoteroLibrary() orchestrator = SearchOrchestrator(library) # Fetch broadly (safe - filtering happens in code) items = library.search_items("machine learning", limit=100) # Filter in code filtered = orchestrator.filter_by_criteria( items, item_types=["journalArticle"], date_range=(2020, 2025) ) print(format_results(filtered[:15]))
User asks: "What papers do I have by Kahneman?"
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import ZoteroLibrary, format_results library = ZoteroLibrary() results = library.search_items( "Kahneman", qmode="titleCreatorYear", limit=50 ) # Sort by date sorted_results = sorted(results, key=lambda x: x.date, reverse=True) print(format_results(sorted_results))
User asks: "Show me papers tagged with 'learning' and 'cognition'"
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import ZoteroLibrary, format_results library = ZoteroLibrary() results = library.search_by_tag(["learning", "cognition"], limit=50) print(format_results(results[:20]))
User asks: "What did I recently add?"
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import ZoteroLibrary, format_results library = ZoteroLibrary() results = library.get_recent(limit=20) print(format_results(results))
User asks: "Find papers about Atyal or ę³°é ę" (alternate spellings/languages)
IMPORTANT: Zotero treats multi-word queries as AND conditions. For OR searches, search each term separately and merge.
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import SearchOrchestrator, format_results orchestrator = SearchOrchestrator() # Search each term separately all_results = {} for term in ['Atayal', 'ę³°é ę']: results = orchestrator.comprehensive_search(term, max_results=50, use_semantic=True) for item in results: all_results[item.key] = item # Deduplicate by key # Re-rank combined results ranked = orchestrator._rank_items(list(all_results.values()), 'Atayal ę³°é ę') # Optional: Filter for specific content filtered = [item for item in ranked if any(term in (item.title + item.abstract).lower() for term in ['atyal', 'atayal', 'ę³°é '])] print(format_results(filtered[:25], include_abstracts=True))
User asks: "Find papers about both cognition and learning"
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import SearchOrchestrator, format_results orchestrator = SearchOrchestrator() # Search both topics results1 = orchestrator.comprehensive_search("cognition", max_results=30) results2 = orchestrator.comprehensive_search("learning", max_results=30) # Find intersection keys1 = {item.key for item in results1} keys2 = {item.key for item in results2} common_keys = keys1 & keys2 if common_keys: common_items = [item for item in results1 if item.key in common_keys] print("Papers about both topics:") print(format_results(common_items)) else: print("No papers found on both topics.") print("\nCognition results:") print(format_results(results1[:10])) print("\nLearning results:") print(format_results(results2[:10]))
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import ZoteroLibrary, SearchOrchestrator, format_results library = ZoteroLibrary() orchestrator = SearchOrchestrator(library) # Fetch large dataset items = library.search_items("neural networks", limit=100) # Custom filtering recent_with_doi = [ item for item in items if item.doi and item.date and int(item.date[:4]) >= 2020 ] print(format_results(recent_with_doi[:15]))
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import ZoteroLibrary, SearchOrchestrator, format_results library = ZoteroLibrary() orchestrator = SearchOrchestrator(library) all_results = set() # Multiple search angles queries = [ "skill transfer", "transfer of learning", "generalization of skills" ] for query in queries: results = library.search_items(query, limit=30) all_results.update(results) # Rank combined results ranked = orchestrator._rank_items(list(all_results), "skill transfer") print(format_results(ranked[:20]))
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import ZoteroLibrary, SearchOrchestrator, format_results library = ZoteroLibrary() orchestrator = SearchOrchestrator(library) # Initial search initial = library.search_items("memory", limit=50) # Analyze tags tag_freq = {} for item in initial: for tag in item.tags: tag_freq[tag] = tag_freq.get(tag, 0) + 1 # Find most common tag if tag_freq: most_common_tag = max(tag_freq, key=tag_freq.get) # Refine search refined = orchestrator.filter_by_criteria( initial, required_tags=[most_common_tag] ) print(f"Papers with most common tag '{most_common_tag}':") print(format_results(refined))
SearchOrchestratorMain class for automated searching.
comprehensive_search(query, max_results=20, use_semantic=True, use_keyword=True, use_tags=True, search_limit_per_strategy=50)Performs multi-strategy search with automatic deduplication and ranking.
Parameters:
query (str): Search querymax_results (int): Maximum results to return (default: 20)use_semantic (bool): Use semantic search (default: True)use_keyword (bool): Use keyword search (default: True)use_tags (bool): Use tag search (default: True)search_limit_per_strategy (int): Items to fetch per strategy (default: 50)Returns: List of ZoteroItem objects
filter_by_criteria(items, item_types=None, date_range=None, required_tags=None, excluded_tags=None)Filter items by various criteria.
Parameters:
items (list): Items to filteritem_types (list): Allowed item types (e.g., ["journalArticle"])date_range (tuple): (min_year, max_year)required_tags (list): Tags that must be presentexcluded_tags (list): Tags that must not be presentReturns: Filtered list of ZoteroItem objects
ZoteroLibraryLow-level interface to Zotero.
search_items(query, qmode="titleCreatorYear", item_type="-attachment", limit=100, tag=None)Basic keyword search.
semantic_search(query, limit=100, search_type="hybrid")Semantic/vector search.
search_by_tag(tags, item_type="-attachment", limit=100)Search by tags.
get_recent(limit=50)Get recently added items.
get_tags()Get all tags in library.
format_results(items, include_abstracts=True, max_abstract_length=300)Format items as markdown.
Good defaults for most searches:
orchestrator.comprehensive_search( query, max_results=20, # Top 20 results search_limit_per_strategy=50 # Fetch 50 per strategy )
For quick searches (fewer results, faster):
results = orchestrator.comprehensive_search( query, max_results=10, search_limit_per_strategy=20 )
For thorough searches (more comprehensive):
results = orchestrator.comprehensive_search( query, max_results=30, search_limit_per_strategy=100 )
When you call
comprehensive_search("embodied cognition", max_results=20):
Semantic Search (if enabled):
Keyword Search (if enabled):
Tag Search (if enabled):
Processing:
Context:
Old Approach (Direct MCP):
# 5+ function calls, all results to context results1 = zotero_semantic_search("query", limit=10) # Crash risk if > 15 results2 = zotero_search_items("query", limit=10) # ... manual deduplication, no ranking # All items (50+) load into context
New Approach (Code Execution):
# 1 function call, only top results to context results = orchestrator.comprehensive_search("query", max_results=20) # Fetches 250+ items, processes in code, returns top 20
Always handle potential errors:
import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import SearchOrchestrator, format_results orchestrator = SearchOrchestrator() try: results = orchestrator.comprehensive_search("query", max_results=20) if results: print(format_results(results)) else: print("No results found. Try a broader search term.") except Exception as e: print(f"Search failed: {e}") print("Please check your Zotero MCP configuration.")
See
/Users/niyaro/Documents/Code/zotero-code-execution/examples.py for 8 complete working examples.
| Task | Code |
|---|---|
| Basic search | |
| Filter by type | |
| Filter by date | |
| Search author | |
| Search by tag | |
| Recent items | |
| Format output | |
comprehensive_search() for most queriessearch_limit_per_strategy to control thoroughness/Users/niyaro/Documents/Code/zotero-code-execution/QUICK_START.md/Users/niyaro/Documents/Code/zotero-code-execution/README.md/Users/niyaro/Documents/Code/zotero-code-execution/examples.py/Users/niyaro/Documents/Code/zotero-code-execution/HONEST_STATUS.mdOld pattern:
# Multiple manual MCP calls results1 = zotero_semantic_search("query", limit=10) results2 = zotero_search_items("query", limit=10) # Manual deduplication...
New pattern:
# One function call with code execution import sys sys.path.append('/Users/niyaro/Documents/Code/zotero-code-execution') import setup_paths from zotero_lib import SearchOrchestrator, format_results orchestrator = SearchOrchestrator() results = orchestrator.comprehensive_search("query", max_results=20) print(format_results(results))
Remember: This skill uses code execution to safely handle large searches. The implementation is in
/Users/niyaro/Documents/Code/zotero-code-execution/.