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.
47
50%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
Optimize this skill with Tessl
npx tessl skill review --optimize ./skill/SKILL.mdSearch 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:
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
)
# 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 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 contextNew 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 20Always 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 | orchestrator.comprehensive_search(query, max_results=20) |
| Filter by type | orchestrator.filter_by_criteria(items, item_types=["journalArticle"]) |
| Filter by date | orchestrator.filter_by_criteria(items, date_range=(2020, 2025)) |
| Search author | library.search_items(author, qmode="titleCreatorYear", limit=50) |
| Search by tag | library.search_by_tag([tags], limit=50) |
| Recent items | library.get_recent(limit=20) |
| Format output | format_results(items, include_abstracts=True) |
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/.
9d521ef
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.